前一段时间在De1CTF中的ShellShellShell以及SUCTF的Upload labs2都涉及到了利用PHP的SoapClient类进行SSRF,因此在这里记录下。
0x01 什么是Soap
SOAP是webService三要素(SOAP、WSDL、UDDI)之一:
WSDL 用来描述如何访问具体的接口。
UDDI用来管理,分发,查询webService。
SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。
其采用HTTP作为底层通讯协议,XML作为数据传送的格式。
0x02 PHP中的SoapClient类
参考链接:https://www.php.net/manual/zh/soapclient.soapclient.php
PHP 的 SOAP 扩展可以用来提供和使用 Web Services,这个扩展实现了6个类,其中的SoapClient类是用来创建soap数据报文,与wsdl接口进行交互的,同时这个类下也是有反序列化中常常用到的__call()魔术方法。
该类的构造函数如下:
1 | public SoapClient :: SoapClient (mixed $wsdl [,array $options ]) |
第一个参数是用来指明是否是wsdl模式。
第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location
和uri
选项,其中location
是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。
知道上述两个参数的含义后,就很容易构造出SSRF的利用payload了。
我们可以设置第一个参数为null
,然后第二个参数的location
选项设置为target_url
,如下
1 |
|
当把上述脚本得到的序列化串进行反序列化(unserialize),并执行一个SoapClient没有的成员函数时,会自动调用该类的__Call
方法,然后向target_url
发送一个soap请求,并且uri
选项是我们可控的地方。
0x03 CRLF Injection
CRLF是”回车 + 换行”(\r\n)
的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。
0x04 SSRF+CRLF攻击内网
实际上很多时候都需要这两个漏洞配合在一起使用,当我们我们可以从外网调用到soap的api,而攻击目标是在内网,那么就可以利用SoapClient进行SSRF攻击内网,然后配合CRLF构造POST请求增加我们的攻击面。
那么为什么在用SoapClient类进行SSRF的时候会有CRLF注入的问题呢?如下:
可以看到options参数中还有一个选项为user_agent
,运行我们自己设置User-Agent
的值。
当我们可以控制User-Agent
的值时,也就意味着我们完全可以构造一个POST请求,因为Content-Type
为和Content-Length
都在User-Agent
之下,而控制这两个是利用CRLF发送post请求最关键的地方。
最后给出wupco师傅的生成任意POST报文的POC:
1 |
|
参考链接: