声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。
关注VX公粽号“锐鉴安全”查阅更多实战案例!
Part-01
SSRF漏洞基本知识
SSRF(Server-Side Request Forgery)漏洞,即服务器端请求伪造漏洞,是一种常见的网络安全漏洞。攻击者能够利用目标服务器去访问其自身无法直接访问的内部资源或外部资源。攻击者通过构造恶意的请求,让服务器代替其发起请求,从而达到获取敏感信息、执行命令、发起进一步攻击等目的。一般出现在以下场景中。
- 内网信息探测
攻击者可以通过构造特定的 URL,让服务器去访问内网中的其他服务器,获取内部网络拓扑、主机信息、服务端口等敏感信息。例如,攻击者可以让目标服务器访问
http://192.168.0.100:8080
,探测内网中该 IP 地址上运行的服务。 - 敏感文件读取
如果服务器具有读取本地文件的权限,攻击者可以利用 SSRF 漏洞构造 URL,让服务器读取本地的敏感文件,如
/etc/passwd
文件获取用户账号信息,或者读取数据库配置文件等。 - 端口扫描
攻击者可以借助服务器发起对不同端口的连接尝试,判断哪些端口是开放的,为进一步攻击做准备。比如,通过循环访问不同端口号的 URL,如
http://target.com:80
、http://target.com:443
等,来确定服务器开放的端口。 - 攻击第三方服务
攻击者可以构造请求,让服务器去访问一些第三方服务,并利用服务器的身份进行操作。例如,利用服务器发送恶意的邮件、短信,或者调用第三方支付接口进行非法支付等。
Part-02
SSRF漏洞代码审计技巧
在Java 中 SSRF 仅支持 sun.net.www.protocol 下所有的协议:http、https、file、ftp、mailto、jar 及 netdoc 协议,正是由于上述协议的限制,以及传入的 URL 协议必须和重定向后的 URL 协议一致的原因,使得 Java 中的 SSRF 并不能像 PHP 中一样使用 gopher 协议来拓展攻击面。
SSRF 会使用 HTTP 请求远程地址,因此代码审计时我们要特别留意能够发起 HTTP 请求的类及函数,还是通过搜索关键字来完成初步漏洞定位。如下。
HttpURLConnection.getInputStream
URLConnection.getInputStream
HttpClient.execute
OkHttpClient.newCall.execute
Request.Get.execute
Request.Post.execute
URL.openStream
ImageIO.read
以下是会引发SSRF漏洞的错误写法,供审计过程中参考。
1.urlConnection
urlConnection 是一个抽象类,表示指向 URL 指定资源的活动链接,它有两个直接子类,分别是 HttpURLConnection 和 JarURLConnection。在默认情况下,urlConnection 的参数没有有效控制时会引起 SSRF 漏洞。
try {
String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
//send request
String inputLine;
StringBuffer html = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
html.append(inputLine);
}
in.close();
return html.toString();
}catch(Exception e) {
e.printStackTrace();
return "fail";
}
2.HttpURLConnection
HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求与 POST 请求。同样的,在没有过滤的默认情况下其会产生 SSRF 漏洞。
try {
String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
HttpURLConnection httpUrl = (HttpURLConnection)urlConnection;
BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //send
request
String inputLine;
StringBuffer html = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
html.append(inputLine);
}
in.close();
return html.toString();
}catch(Exception e) {
e.printStackTrace();
return "error";
}
3.Request
Request 与 Python 中的 request 对象类似,其主要用来发送 HTTP 请求。在没有过滤的默认情况下会产生 SSRF 漏洞。
try {
String url = request.getParameter("url");
return Request.Get(url).execute().returnContent().toString();
}catch(Exception e) {
e.printStackTrace();
return "fail";
}
4.openStream
通过 URL 对象的 openStream()方法,能够得到指定资源的输入流。这时如果 URL 对象可控,则会产生 SSRF 漏洞。
try {
String downLoadImgFileName = Files.getNameWithoutExtension(url) + "." +Files.getFileExtension(url);
// download
response.setHeader("content-disposition", "attachment;fileName=" + downLoadImgFileName);
URL u = new URL(url);
int length;
byte[] bytes = new byte[1024];
inputStream = u.openStream(); // send request
outputStream = response.getOutputStream();
while ((length = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, length);
}
}catch (Exception e) {
e.printStackTrace();
}finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
5.HttpClient
HttpClient 是 Apache Jakarta Common 下的一个子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。但是在默认情况下,其也会产生 SSRF 漏洞。
try {
client.execute(httpGet);
BufferedReader rd = new BufferedReader(new InputStreamReader (client.execute (httpGet).
getEntity(). getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while((line = rd.readLine()) != null) {
result.append(line);
}
return result.toString();
} catch (Exception var7) {
var7.printStackTrace();
return "fail";
}
从上述的代码来看,java自带代码包其实没问题,最终造成ssrf漏洞的根本原因为未进行url过滤,导致可以请求内网资源。实战案例可阅作者VX公粽号的“【漏洞挖掘】SSRF漏洞挖掘实战”一文。
Part-03
SSRF漏洞修复方法
- 严格的输入验证
对用户输入的 URL 进行严格的合法性检查,包括检查 URL 的格式、协议、域名等,只允许合法的、预期的 URL 通过。
- 限制请求范围
明确服务器允许访问的 URL 范围,禁止访问内网 IP 地址、敏感端口等。可以使用白名单机制,只允许访问特定的域名或 IP 地址段。
- 使用安全的网络配置
在内网和外网之间设置防火墙等安全设备,限制服务器对外网的访问权限,同时对内网的服务进行合理的访问控制,减少 SSRF 漏洞可能带来的危害。
- 及时更新和修复
保持服务器软件、框架等的及时更新,修复已知的安全漏洞,因为很多 SSRF 漏洞是由于软件本身存在的缺陷导致的。