SSRF(Server-Side Request Forgery): 服务端请求伪造, 是一个利用服务端探测内网服务资源的漏洞,用一个最简单的例子来理解这个漏洞:比如一个添加图文的功能,填入标题内容和封面图然后提交在网站前台显示,对于这个功能的图片它除了可以让你上传以外,还支持填入远程图片地址,如果你填入了远程的图片地址,则该网站会加载远程图过来进行显示,而如果程序写法不严谨或者过滤不严格,则加载图片地址的这个功能可能就可以包含进行一些恶意的脚本文件,或者你输入内网的 ip 或者一些系统的文件都会被解析执行
而一般我们是无法请求到系统上的文件的,内网的 ip 我们也是无法访问的,有了 SSRF 后,我们提交的加载连接是有服务器进行加载解析,实际上相当于我们以存在 SSRF 这个服务器为跳板进行的一些加载操作,我们在附一张图加深理解
我们知道了 SSRF 的原理后,自然就能想到其危害点有哪些
SSRF一般在一些请求url资源的时候会遇到,如?url=https://ip:prot/xxx.jpg请求别的站点的静态资源之类的
在 java中(高版本jdk)仅支持如下协议
// 构造方法, 生成一个 URL 对象
new URL(String url)
// 返回一个 URLConnection 实例, 表示与 URL 引用的远程对象的 URL
// 每次当调用此 URL 的协议处理程序的 URLStreamHandler.openConnection(URL) 方法时, 都会创建一个新的 URLConnection 实例
public URLConnection openConnection() throws IOException
应该注意的是,URLConnection 实例不会在创建时建立实际的网络连接, 这只会在调用 URLConnection.connect() 时发生
// 构造与指定 URL 的 URL 连接
protected URLConnection(URL url)
与URLConnection的区别
这个类只能用http协议
@GetMapping("httpUrlConnection")
public ResponseVO httpUrlConnection(@RequestParam("url") String url) {
try {
// 创建一个连接
URLConnection urlConnection = new URL(url).openConnection();
// 强转为 HttpURLConnection
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
// 获取url中的资源
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), StandardCharsets.UTF_8));
StringBuilder stringBuilder = new StringBuilder();
String data;
while ((data = bufferedReader.readLine()) != null) {
stringBuilder.append(data);
}
return ResponseVO.success(stringBuilder.toString());
} catch (IOException e) {
log.error(ERROR_MSG, url, e);
return ResponseVO.fail(ResponseCodeEnum.FAIL, ERROR_RESPONSE_MSG);
}
}
请求地址
GET hhtp://127.0.0.1:8080/ssrf/httpUrlConnection?url=http://ssrf.xxxx.ceye.io
@GetMapping("urlConnection")
public ResponseVO urlConnection(@RequestParam("url") String url, HttpServletResponse response) {
URLConnection urlConnection = null;
try {
urlConnection = new URL(url).openConnection();
} catch (IOException e) {
log.error(ERROR_MSG, url, e);
return ResponseVO.fail(ResponseCodeEnum.FAIL, ERROR_RESPONSE_MSG);
}
try (BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder stringBuilder = new StringBuilder();
String data;
while ((data = bufferedReader.readLine()) != null) {
stringBuilder.append(data);
}
return ResponseVO.success(stringBuilder.toString());
} catch (IOException e) {
log.error(ERROR_MSG, url, e);
return ResponseVO.fail(ResponseCodeEnum.FAIL, ERROR_RESPONSE_MSG);
}
}
GET http://127.0.0.1:8080/ssrf/urlConnection?url=file:///D:\code\idea_workspace\toalibaba\security-study\fortify\src\main\resources\mapper\UserMapper.xml
GET http://127.0.0.1:8080/ssrf/urlConnection?url=netdoc:///D:\code\idea_workspace\toalibaba\security-study\fortify\src\main\resources\mapper\UserMapper.xml
jar 协议语法,jar:{url}!/{entry},url是文件的路径,entry是想要解压出来的文件
当然这里url不仅仅是http协议,也可以是file协议或者netdoc
jar协议处理文件过程
http://127.0.0.1:8080/ssrf/urlConnection?url=jar:http://127.0.0.1:4444/sql.txt.zip!/sql.txt