【技术分享】Use DNS Rebinding to Bypass SSRF in Java

释放双眼,带上耳机,听听看~!
Author:JoyChou@Meili-incMail:viarus@qq.comDate:201709300x00前言本篇文章会比较详细的介绍,如何使用DNSRebinding绕过Java中的SSRF。网上有蛮多资料介绍用该方法绕过常规的SSRF,但是由于Java的机制和PHP等语言不

Author: JoyChou@Meili-inc

Mail: viarus@qq.com

Date: 20170930

0x00 前言

本篇文章会比较详细的介绍,如何使用DNS Rebinding绕过Java中的SSRF。网上有蛮多资料介绍用该方法绕过常规的SSRF,但是由于Java的机制和PHP等语言不太一样。所以,我觉得,有必要单独拿出来聊一聊,毕竟目前很多甲方公司业务代码都是Java。

0x01 SSRF修复逻辑

  1. 取URL的Host

  2. 取Host的IP

  3. 判断是否是内网IP,是内网IP直接return,不再往下执行

  4. 请求URL

  5. 如果有跳转,取出跳转URL,执行第1步

  6. 正常的业务逻辑里,当判断完成最后会去请求URL,实现业务逻辑。

所以,其中会发起DNS请求的步骤为,第2、4、6步,看来至少要请求3次。因为第6步至少会执行1次DNS请求。另外,网上有很多不严谨的SSRF修复逻辑不会判断跳转,导致可以被Bypass。

0x02 DNS Rebinding

我个人理解如下:

通过自己搭建DNS服务器,返回自己定义的IP,进行一些限制的绕过。所以,我们可以利用DNS Rebinding在第一次发起DNS请求时,返回外网IP,后面全部返回内网IP 这种方式来绕过如上的修复逻辑。我们来看下是如何绕过的。

首先,修复逻辑中第2步发起DNS请求,DNS服务器返回一个外网IP,通过验证,执行到第四步。接着,修复逻辑中第4步会发起DNS请求,DNS服务器返回一个内网IP。此时,SSRF已经产生。

TTL

不过,这一切都是在TTL为0的前提下。什么是TTL?

TTL(Time To Live)是DNS缓存的时间。简单理解,假如一个域名的TTL为10s,当我们在这10s内,对该域名进行多次DNS请求,DNS服务器,只会收到一次请求,其他的都是缓存。

所以搭建的DNS服务器,需要设置TTL为0。如果不设置TTL为0,第二次DNS请求返回的是第一次缓存的外网IP,也就不能绕过了。

DNS请求过程

步骤如下:

  1. 查询本地DNS服务器(/etc/resolv.conf)

  2. 如果有缓存,返回缓存的结果,不继续往下执行

  3. 如果没有缓存,请求远程DNS服务器,并返回结果

DNS缓存机制

平时使用的MAC和Windows电脑上,为了加快HTTP访问速度,系统都会进行DNS缓存。但是,在Linux上,默认不会进行DNS缓存(https://stackoverflow.com/questions/11020027/dns-caching-in-linux) ,除非运行nscd等软件。不过,知道Linux默认不进行DNS缓存即可。这也解释了,我为什么同样的配置,我在MAC上配置不成功,Linux上配置可以。需要注意的是,IP为8.8.8.8的DNS地址,本地不会进行DNS缓存。

0x03 漏洞测试

准备如下环境:

  • Java Web应用

  • DNS服务器

我们要先了解下Java应用的TTL。Java应用的默认TTL为10s,这个默认配置会导致DNS Rebinding绕过失败。也就是说,默认情况下,Java应用不受DNS Rebinding影响。Java TTL的值可以通过下面两种方式进行修改:

  1. 修改/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/security/java.security(我MAC下的路径)里的networkaddress.cache.negative.ttl=0

  2. 通过代码进行修改java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0");

这个地方是个大坑,我之前在测试时,一直因为这个原因,导致测试不成功。这也是利用DNS Rebinding过程中,Java和PHP不一样的地方。在测试PHP时,这份PHP代码用DNS Rebinding可以绕过,类似的代码Java就不能被绕过了。

SSRF漏洞搭建

用Java Spring写了一个漏洞测试地址为http://test.joychou.org:8080/checkssrf?url=http://dns_rebind.joychou.me。URL会进行SSRF验证。SSRF修复代码如下。也可以在Github上查看https://github.com/JoyChou93/trident

/*
       * 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

给TA买糖
共{{data.count}}人
人已赞赏
HackerNews

【技术分享】Exploiting JSON CSRF

2017-9-30 5:57:34

HackerNews

360 Vulpecker Team:BlueBorne 蓝牙漏洞深入分析与PoC

2017-9-30 10:11:32

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索