freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Java代码审计之SSRF
2022-07-06 16:08:19
所属地 福建省

漏洞介绍

SSRF漏洞(服务器端请求伪造):是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)。

SSRF漏洞原理

SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。利用的是服务端的请求伪造。SSRF是利用存在缺陷的web应用作为代理攻击远程和本地的服务器。
Java网络请求中常见的几种协议:

file、ftp、http、https、jar、mailto、netdoc

urlConnection/vul

使用file:///协议读取本地文件(或其他协议)
http://localhost:8080/ssrf/urlConnection/vuln?url=file:///c:/windows/win.ini
这里调用的是HttpUtils.URLConnection(url)

public String URLConnectionVuln(String url) {
	return HttpUtils.URLConnection(url);
}

而URLConnection里又调用了URL.openConnection()来发起请求,这个请求可以直接执行url协议(伪协议)

public static String URLConnection(String url) {
	try {
		URL u = new URL(url);
		URLConnection urlConnection = u.openConnection();
		BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request
		// BufferedReader in = new BufferedReader(new InputStreamReader(u.openConnection().getInputStream()));
		String inputLine;
		StringBuilder html = new StringBuilder();

		while ((inputLine = in.readLine()) != null) {
			html.append(inputLine);
		}
		in.close();
		return html.toString();
	} catch (Exception e) {
		logger.error(e.getMessage());
		return e.getMessage();
	}
}

代码跟踪
发现传入的url被带入_URLConnection方法中_
图片.png
_进入URLConnection方法,发现url对象u直接调用_openConnection方法并简单判断了是否为空,无过滤
图片.png
回显出系统内部文件内容
图片.png

urlConnection/sec(修复方法)

访问url为http://localhost:8080/ssrf/urlConnection/sec?url=http://baidu.com
这里先是对url调用了SecurityUtil.isHttp()来进行检查,随后又

@GetMapping("/urlConnection/sec")
public String URLConnectionSec(String url) {

	// Decline not http/https protocol
	if (!SecurityUtil.isHttp(url)) {
		return "[-] SSRF check failed";
	}

	try {
		SecurityUtil.startSSRFHook();
		return HttpUtils.URLConnection(url);
	} catch (SSRFException | IOException e) {
		return e.getMessage();
	} finally {
		SecurityUtil.stopSSRFHook();
	}

}

SecurityUtil.isHttp()比较简单,就是判断url是否是以http://或https://开头

public static boolean isHttp(String url) {
	return url.startsWith("http://") ||url.startsWith("https://");
}

单纯的ban掉其他协议显然是不够的,还不能够防止对内网进行探测,于是在获取url内容之前,开启了一个hook来对用户行为进行监听,SecurityUtil.startSSRFHook(),就有效防止了ssrf攻击
代码跟踪
url在进入中有个_isHttp方法_
图片.png
进入_isHttp方法,发现事先判断了是否是http或https_
图片.png
我们传入的是ftp,所以判断为false,页面输出[-] SSRF check failed"
图片.png

openStream

openStream()方法的实现也是调用了 openConnection生成一个 URLConnection 对象,然后再通过这个对象调用的getInputStream()方法的
访问url为
http://localhost:8080/ssrf/openStream?url=file:///c:/windows/win.ini
通过WebUtils.getNameWithoutExtension(url) + "." +WebUtils.getFileExtension(url)来获取下载文件名
然后执行如下代码:

URL u = new URL(url);
inputStream = u.openStream()

来看一下openStream(),也是调用了openConnection(),也会根据传入的协议的不同来进行处理

public final InputStream openStream() throws java.io.IOException {
	return openConnection().getInputStream();
}

由此可以得知,同样也可以进行ssrf来探测内网以及文件下载。
图片.png
修复方案同上

关键词

URLConnection    openConnection    openStream
# 代码审计 # 代码审计; # 代码审计入门
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者