Author: JoyChou@Meili-inc
0x00 前言
0x01 SSRF修复逻辑
-
取URL的Host
-
取Host的IP
-
判断是否是内网IP,是内网IP直接return,不再往下执行
-
请求URL
-
如果有跳转,取出跳转URL,执行第1步
-
正常的业务逻辑里,当判断完成最后会去请求URL,实现业务逻辑。
0x02 DNS Rebinding
TTL
DNS请求过程
-
查询本地DNS服务器(
/etc/resolv.conf
) -
如果有缓存,返回缓存的结果,不继续往下执行
-
如果没有缓存,请求远程DNS服务器,并返回结果
DNS缓存机制
0x03 漏洞测试
-
Java Web应用
-
DNS服务器
-
修改
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/security/java.security(我MAC下的路径)
里的networkaddress.cache.negative.ttl=0
-
通过代码进行修改
java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0");
SSRF漏洞搭建
/*
* check SSRF (判断逻辑为判断URL的IP是否是内网IP)
* 如果是内网IP,返回false,表示checkSSRF不通过。否则返回true。即合法返回true
* URL只支持HTTP协议
* 设置了访问超时时间为3s
*/
public static Boolean checkSSRF(String url) {HttpURLConnection connection;
String finalUrl = url;
try {
do {
// 判断当前请求的URL是否是内网ip
Boolean bRet = isInnerIpFromUrl(finalUrl);
if (bRet) {
return false;
}connection = (HttpURLConnection) new URL(finalUrl).openConnection();
connection.setInstanceFollowRedirects(false);
connection.setUseCaches(false); // 设置为false,手动处理跳转,可以拿到每个跳转的URL
connection.setConnectTimeout(3*1000); // 设置连接超时时间为3s
//connection.setRequestMethod("GET");
connection.connect(); // send dns request
int responseCode = connection.getResponseCode(); // 发起网络请求 no dns request
if (responseCode >= 300 && responseCode < 400) {
String redirectedUrl = connection.getHeaderField("Location");
if (null == redirectedUrl)
break;
finalUrl = redirectedUrl;
// System.out.println("redirected url: " + finalUrl);
} else
break;
} while (connection.getResponseCode() != HttpURLConnection.HTTP_OK);
connection.disconnect();
} catch (Exception e) {
return true;
}
return true;
}/*
内网IP:
10.0.0.1 - 10.255.255.254 (10.0.0.0/8)
192.168.0.1 - 192.168.255.25