PHP中SSRF的成因及利用

某天审一套野生cms的时候看到如上的PHP代码,curl的配置项比较多,怀疑是否存在ssrf漏洞,也正好想研究ssrf,所以对**什么样的curl配置会导致ssrf**这一点很感兴趣,于是展开了本次研究

PHP中SSRF的成因及利用


成因1—cURL

image.png

某天审一套野生cms的时候看到如上的PHP代码,curl的配置项比较多,怀疑是否存在ssrf漏洞,也正好想研究ssrf,所以对什么样的curl配置会导致ssrf这一点很感兴趣,于是展开了本次研究

配置项分析

  • CURLOPT_HEADER 绝大多数情况下都是0,否则会连同header一起返回(如图

image.png

  • CURLOPT_NOBODY 启用时将不对HTML中的BODY部分进行输出,若关闭则有回显决定是否为无回显布尔型SSRF的因素

image.png

  • CURLOPT_PORT  用来指定连接端口。决定SSRF是否被限制端口的因素
  • CURLOPT_PROTOCOLS  限定在传输过程中可使用的协议。这将允许你在编译libcurl时支持众多协议,默认将会使用全部它支持的协议。决定SSRF是否被限制协议的因素

  • CURLOPT_RETURNTRANSFER 将curl_exec获取的信息以文件流的形式返回,而不是直接输出。ps: 有网友说这项配置会导致ssrf无回显,经测试并非如此——置0置1对有无输出均无影响,有无输出由CURLOPT_NOBODY决定 ;实际上,这个配置项主要跟CURLOPT_BINARYTRANSFER一起使用)
  • CURLOPT_FOLLOWLOCATION 启用时会将服务器服务器返回的”Location: “放在header中递归的返回给服务器,使用CURLOPT_MAXREDIRS可以限定递归返回的数量。是否允许SSRF跳转的决定因素
  • CURLOPT_TIMEOUT 设置cURL允许执行的最长秒数。 
  • CURLOPT_TIMEOUT_MS 设置cURL允许执行的最长毫秒数。
  • CURLOPT_CONNECTTIMEOUT 在发起连接前等待的时间,如果设置为0,则无限等待。  
  • CURLOPT_CONNECTTIMEOUT_MS 尝试连接等待的时间,以毫秒为单位。如果设置为0,则无限等待
  • CURLOPT_CUSTOMREQUEST 使用一个自定义的请求信息来代替”GET”或”HEAD”作为HTTP请求。常用值如”GET”,”POST”,”CONNECT”等等。

建议配置

根据不同的需求,有不同的配置建议。如果是为了防止ssrf进内网的话,可以通过限制协议+端口+白名单地址范围来彻底杜绝ssrf,例如下面的实例代码就是较为安全的(限制白名单地址+不输出http头+限制http协议).

成因2—file_get_contents


成因3—fsockopen/fopen


SSRF的利用

类型判断

高级协议

gopher协议

gopher协议支持发出GET、POST请求:可以先拦截get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)

攻击HTTP服务

gopher可以模拟HTTP中POST和GET参数传递,进而攻击内网的服务,完成更深入的渗透。下面以一个例子来说明
例如,后端的PHP代码如下

我们发起下面的HTTP请求

再对这段请求进行URLencode,按照gopher协议的格式

构造URL时需要注意:CRLF在windows和linux中有以下区别。

换行: windows用%0d%0a, linux用%0a, macOS下用%0d
正如notepad输入界面右下角所显示的那样
image.png

放到curl中访问,可以看到在post和get传参方面已经完全模拟了刚刚的HTTP请求。
image.png
结论:gopher协议可模拟构造HTTP中POST和GET参数传递

攻击其它服务

gopher攻击内网其它服务时的一般思路如下

总结

  1. gopher协议可模拟构造HTTP中POST和GET参数传递,用burp抓HTTP包再按指定格式构造、访问即可

dict协议

dict协议可用于判断端口是否开放+读取banner判断服务
image.png
image.png

file协议

这个利用起来类似于本地文件读取(path traversal),可用来读bash_history、源码及凭据等
·image.png

bypass HTTP协议—302跳转

如果限制了只允许HTTP协议,则可以用这个302脚本来尝试使用其他协议,脚本需部署在可访问到的地方,如vps等

bypass 访问白名单

下面介绍几种bypass存在ssrf白名单限制的方法

  1. xip.io这是一个开放的重定向服务,将任何IP地址用域名的形式表示,所有的子域名都会被解析到本身,如192.168.1.1.xip.io -->192.168.1.1
  2. 特殊HTTP地址  如果白名单实现逻辑上有问题,很可能放过这种类型的URLwww.weather.com.cn@baidu-inc.com/sensitive_path;当然,实际上PHP弱类型也是一种特殊的地址
  3. 特殊ip地址
    1. 简写形式 10.1 = 10.0.0.1,ip进制转换(十进制下 3232235777 = 192.168.1.1 )
    2. ipv6的本地地址 ip6-localhost ,xip.io只支持IPv4,IPv6下也有个类似的服务,ip6.name,比如,我们可以通过x.1.ip6.name访问::1,也就是本地;另外Windows下还可以通过微软内置的ipv6-literal.net;将IPv6地址中的冒号换成横线作为ipv6-literal.net子域名,如2408-8207-1850-2a60--4c8.ipv6-literal:=.net-->2408:8207:1850:2a60::4c8,例如本地地址便是用0--1.ipv6-literal.net来访问到::1
  4. 短网址 tinyurl.comt.cngoo.gldwz.cn