前言
总结php中反序列化时会用到的原生类;php中内置很多原生的类,在CTF中常以echo new $a($b);
这种形式出现,当看到这种关键字眼时,就要考虑本题是不是需要原生类利用了
目录遍历类
DirectoryIterator
这个类会创建一个指定目录的迭代器,当遇到echo
输出时会触发Directorylterator
中的__toString()
方法,输出指定目录里面经过排序之后的第一个文件名,而一般情况第一个文件都是点号。没什么用,但是Directorylterator
可以配合glob协议使用;与glob://协议结合将无视open_basedir对目录的限制
1 |
|
FilesystemIterator
该类继承于Directorylterator
,所以在用法上基本也是一样的。
GlobIterator
通过类名也不难看出,这是个自带glob
协议的类,所以调用时就不必再加上glob://
了
1 |
|
文件读取类
SplFileObject
当用文件目录遍历到了敏感文件时,可以用SplFileObject
类,同样通过echo触发SplFileObject
中的__toString()
方法。(该类不支持通配符,所以必须先获取到完整文件名称才行)
除此之外其实SplFileObject
类,只能读取文件的第一行内容,如果想要全部读取就需要用到foreach函数,但若题目中没有给出foreach函数的话,就要用伪协议读取文件的内容
1 |
|
输出如下:
1 |
|
base64解码:
1 |
|
报错类
Error/Exception
ERROR 适用于php7版本
Error类就是php的一个内置类用于自动自定义一个Error,它内置有一个toString的方法。
EXCEPTION 适用于php5、7版本
这个类利用的方式和原理和Error 类一模一样,但是适用于php5和php7,相对之下更加好用
Error/Exception_XSS
[BJDCTF 2nd]xss之光
扫后台,有.git 泄露,githack下载下来
1 |
|
源码只有这三行;可触发序列化中的魔术方法__toString
1 |
|
flag就在cookies中
Error/Exception_绕过哈希比较
1 |
|
1 | Exception: deadbeef in E:\phpstudy\phpstudy_pro\WWW\test.php:2 |
当变量a,b同时触发__toString()
方法时,虽对象不同,但执行__toString()
方法后,返回结果相同;这里需要注意a,b赋值时,必须要在同一行上,因为执行__toString()
方法时会返回行号。虽然强碰撞也可以绕过,但是还是不如用报错类绕过的好,强碰撞绕过的字符非常长,如果对字符长度做了限制的话可以考虑利用报错类绕过哈希比较
其他类
ReflectionMethod 获取类方法的相关信息
可以结合getDocComment()
方法,用它来获取类中各个函数注释内容
1 |
|
1 | http://127.0.0.1/test.php?a=ReflectionMethod&b=Sentiment&c=a |
SoapClient 类进行 SSRF
PHP 的内置类 SoapClient
是一个专门用来访问web服务的类,SOAP 协议是一种基于 XML 的协议,用于在 Web 应用程序之间进行交互,主要用于 Web 服务;WSDL:是一种 XML 文档,用于描述 Web 服务。
该内置类有一个 __call
方法,当 __call
方法被触发后,它可以发送 HTTP 和 HTTPS 请求。正是这个 __call
方法,使得 SoapClient 类可以被我们运用在 SSRF 中。
该类的构造函数如下:
1 | public SoapClient :: SoapClient(mixed $wsdl [,array $options ]) |
- 第一个参数是用来指明是否是wsdl模式,将该值设为null则表示非wsdl模式。
- 第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location和uri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。
1 |
|
1 | ubuntu@zIxyd:~$ nc -lnnp 6666 |
从结果我们可以看到SOAPAction参数可控,我们可以在SOAPAction处注入恶意的换行,这样一来我们POST提交的header就是可控的,我们就可以通过注入来执行我们想要执行的操作了。
尝试传入token,发现新的问题,Content-Type在SOAPAction
的上面,就无法控制Content-Type
,也就不能控制POST的数据
在header里User-Agent
在Content-Type
前面,通过user_agent
同样可以注入CRLF,控制Content-Type
的值
尝试控制token
1 |
|
1 | ubuntu@zIxyd:~$ nc -lnnp 6666 |
成功控制
使用SoapClient反序列化+CRLF可以生成任意POST请求。
1 | Deserialization + __call + SoapClient + CRLF = SSRF |
SoapClient__Example
ctfshow_web259
hint:
1 | #flag.php |
源码:
1 | #index.php |
目的是在index.php通过反序列化一个原生类向flag.php发送请求,然后flag.php用file_put_contents把flag放到flag.txt里
exp
1 |
|
ZipArchive 类来删除文件
- 适用于PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL zip >= 1.1.0
- 一个用 Zip 压缩的文件存档。
可以通过本类执行一些文件操作,在CTF可以用来删除waf
常用类方法:
1 | ZipArchive::addEmptyDir:添加一个新的文件目录 |
实例代码:
1 |
|
该方法用来打开一个新的或现有的zip存档以进行读取,写入或修改。
1 | filename:要打开的ZIP存档的文件名。 |
ZipArchive_Example
新建一个waf.txt文件,内容如下
1 | this_is_test |
新建一个test.php文件,内容如下
1 |
|
代码很明显,只有不存在waf.txt文件,即可rce; 存在open函数,通过ZipArchive直接调用open方法删除目标机上的文件
poc:
1 |
|