前言
总结一下关于php原生类的一些东西。目前php原生类的利用方式主要有XSS、SSRF、XXE、删文件、读文件、遍历目录等。当题目中出现一些反序列化操作,但又没有提供链子或者出现一些可控new操作,这时可能就需要利用php原生类来做一些事情。以下方法可以遍历php内置类
1 |
|
有点类似java反射的操作。
Error/Exception
XSS
适用条件
Error:php7、开启报错
Exception:php5 php7、开启报错
主要是这两个类的__tostring
方法,可以将错误信息以字符串的形式打印到页面,而当配合一些echo
、var_dump
等触发方式,即可XSS。
1 | <?php |
类内hash比较
假设有如下代码
1 |
|
需要绕过类中的
1 | if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ) |
一般想到的做法就是直接用数组绕过,但是这里也可以利用异常类输出异常的特性来绕过
看一下两个异常类的构造方法:
1 | public __construct ( string $message = "" , int $code = 0 , Throwable $previous = null ) |
指定message
是要输出的异常信息,指定code
是程序异常的返回码
1 |
|
会发现输出信息一模一样,其中输出了错误信息的行号(也就是为什么要在同一行),以及错误信息的message
但是$a != $b
,因为他们传入构造函数的code不一样,因此这样就可以绕过hash了,md5
、sha1
、eval
均会触发异常类的__tostring
方法。绕过hash之后,由于过滤了()
,我们使用include "/flag"
的形式,但是又过滤了引号,所以我们可以尝试取反,或者参数外带
1 | include ~urldecode("%D0%99%93%9E%98"); // include("/flag") |
所以最终可以得到payload
1 | $str = "?><?=include~".urldecode("%D0%99%93%9E%98")."?>"; |
SoapClient SSRF
该类触发__call
时会发送 HTTP 和 HTTPS 请求,Content-Type默认为application/xml
,target是location字段
构造函数
1 | public SoapClient :: SoapClient(mixed $wsdl [,array $options ]) |
- 第一个参数是用来指明是否是wsdl模式,将该值设为null则表示非wsdl模式。
- 第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location和uri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。
当触发__call
时,可以发送请求
1 |
|
要可控HTTP的POST报文的话,可以在第二个参数options中的UA字段进行CRLF注入,从而可控Content-Type、Content-Length、Cookie和HTTP正文包
1 |
|
SimpleXMLElement XEE
构造函数
1 | final public SimpleXMLElement::__construct ( string $data , int $options = 0 , bool $data_is_url = false , string $ns = "" , bool $is_prefix = false ) |
当第三个参数为true时,可以获取指定远程URL的xml,地址就是第一个参数$data
,第二个参数设置为2即可
evil.xml
1 |
send.xml
伪协议读文件,甚至还可以配合phar触发反序列化
1 |
send.php
1 |
|
即可在本地获取index.php
ZipArchive 删文件
ZipArchive::open
方法
1 | ZipArchive::open(string $filename, int $flags=0) |
第二个参数的几种模式:
ZipArchive::OVERWRITE
:总是以一个新的压缩包开始,此模式下如果已经存在则会被覆盖或删除,常数8。ZipArchive::CREATE
:如果不存在则创建一个zip压缩包。ZipArchive::RDONLY
:只读模式打开压缩包。ZipArchive::EXCL
:如果压缩包已经存在,则出错。ZipArchive::CHECKCONS
:对压缩包执行额外的一致性检查,如果失败则显示错误。
指定第二个参数为ZipArchive::OVERWRITE
时,可以删文件
原生文件操作类
SPL就是Standard PHP Library的缩写。据手册显示,SPL是用于解决 典型问题(standard problems) 的一组接口与类的集合。用好这里的类,可以提高开发效率,相当于一个内置的工具库
列目录类
1 | DirectoryIterator 类 |
前两个用法基本一样,第三个直接可以指定glob协议的用法
且三个类都有__tostring
方法,用于输出对应的文件名,其构造方法生成迭代器,然后利用循环逐一输出文件名。如果不利用循环直接输出的话,只会输出第一个的文件名。
前两个类的配合glob协议的用法
1 |
|
GlobIterator类可以直接匹配使用,相当于不迭代循环输出,也能够匹配到相应的文件名
1 | $a = new GlobIterator("/*flag*"); |
读文件类
1 | SplFileObject |
该类有两种读取文件的方式,一种是像读目录一样迭代读取每一行,一种是调用fpassthru
方法
第一种
1 | $context = new SplFileObject('/etc/passwd'); |
第二种
1 | (new SplFileObject('/etc/passwd'))->fpassthru(); |