var name =
requset.get("name") `
var cmd ="echo 'Hello " + name + "'"
RUN_CMD(cmd)`
外部输⼊,进⾏简单的拼接,最终放⼊⼀个执⾏外部命令的
函数中去执⾏ 但命令执⾏的函数,
都⼀定存在这个rce吗?
如果不⼀定存在RCE,
它们之间的差别是什么
实际安全领域的讨论中,”RCE” 通常被广泛用来指代远程代码执行漏洞。
代码执行与命令执行区别
RCE与命令注入区别
$user_input =
$_GET['input'];`
system('whoami ' .$user_input);`
如果用户能够控制 $_GET['input']的值 在系统上面执行任意指令
便算是通过命令注入来造成RCE,
如果不是在系统上面执行
在应用程序上面执行 就只能算
命令注入
可利用函数
远程代码执行
eval() //把字符串作为PHP代码执行
-
eval()
: -
功能:执行一个字符串表达式,并返回表达式的值。 -
风险:如果执行的字符串来自不可信的源,则可能执行恶意代码。 -
exec()
: -
功能:执行存储在字符串或代码对象中的Python语句。 -
风险:与 eval()
类似,如果执行的代码来源不安全,可能导致安全漏洞。 -
pickle.loads()
/pickle.load()
:pickle.loads()
/pickle.load()
: -
功能:反序列化pickle对象。 -
风险:如果反序列化的数据来自不可信的源,攻击者可能利用pickle的特性执行任意代码。 -
getattr()
: -
功能:获取对象的属性值。 -
风险:如果属性名和对象是动态提供的,并且来源不安全,可能被用来执行不安全的方法。 -
subprocess.Popen()
/ 相关函数: -
功能:执行外部命令和程序。 -
风险:如果外部命令的输入部分来自用户输入或不安全的源,可能被用于执行恶意命令。 -
os.system()
/os.popen()
: -
功能:执行系统命令。 -
风险: 同 subprocess.Popen()
,如果命令字符串不安全,可能导致代码注入
-
攻击者构建恶意对象: -
攻击者创建了一个特制的序列化对象,这个对象在反序列化时会触发执行代码的逻辑。 -
利用的是Apache Commons Collections中的 InvokerTransformer
类,这个类可以调用任意方法。攻击者将其配置为执行恶意代码,比如运行一个外部命令。 -
序列化并发送对象: -
这个恶意对象被序列化为字节流,并发送到目标Java应用程序。 -
目标应用反序列化: -
Java应用程序接收到这个对象,并开始反序列化过程。 -
在反序列化过程中, InvokerTransformer
被触发,执行了预设的恶意代码。
漏洞分析
InvokerTransformer
类的transform
方法可以用来执行任意代码,而在反序列化过程中,对象的方法会自动执行。因此,攻击者可以构造一个当被反序列化时会自动执行恶意操作的对象。防御措施
-
限制反序列化:在Java应用中,应限制或完全避免反序列化来自不可信源的数据。 -
使用安全库:使用更新的安全库,例如更新的Apache Commons Collections版本,这些版本已修复了此类漏洞。 -
使用对象白名单:在反序列化时,应用程序应该实现白名单机制,只允许预定义的安全类被反序列化。
远程命令执行
-
exec
– 执行一个外部程序 -
passthru
– 执行外部程序并且显示原始输出 -
proc_open
– 执行一个命令,并且打开用来输入/输出的文件指针 -
shell_exec
– 通过shell 执行命令并将完整的输出以字符串的方式返回 -
system
– 执行外部程序,并且显示输出
-
os.system()
– 执行系统指令 -
os.popen()
– popen()方法用于从一个命令打开一个管道 -
subprocess.call()
– 执行由参数提供的命令
-
Runtime.getRuntime().exec()
-
ProcessBuilder()
RCE与系统的交互
用户态 系统调用 内核态
用户态与内核态
-
操作系统有两种运行模式:用户态和内核态。用户态限制了程序对关键系统资源的访问,以防止用户程序直接与硬件交互,可能导致系统不稳定或不安全。内核态则允许操作系统内核访问和控制硬件。
系统调用的作用
-
系统调用是用户态与内核态之间的桥梁。当用户程序需要执行如文件操作、网络通信等需要更高权限的任务时,它会通过系统调用请求操作系统内核执行这些任务。系统调用是一种受控的机制,它确保了即使在执行这些高权限操作时,系统的安全性和稳定性也得到保护。
RCE与系统调用
-
RCE攻击通常涉及操纵系统调用来执行恶意代码。例如,在Linux系统中,攻击者可能会利用不安全的程序逻辑,通过注入恶意命令来控制 exec()
系统调用,从而在受影响的系统上执行任意代码。
RCE漏洞的复杂性与跨语言特性
-
RCE漏洞的复杂性在于它们可以跨越不同的编程语言和应用架构。例如,一个Web应用的RCE漏洞可能起始于一个简单的PHP脚本注入,但最终可能导致在底层服务器的操作系统上执行恶意命令。
RCE的跨平台特性
-
RCE不局限于任何特定的编程语言或平台。它们可以出现在任何处理外部输入的程序中,从服务器端的Web应用程序(如PHP、Java、Python)到客户端的桌面应用程序(如C++或Java应用程序)。
syscall系统调用
-
操作系统将运行模式分为了 用户态和内核态 他们中间通过系统调用syscall来进行交互,用户态可以通过syscall来对内核态发起调用系统特权指令的请求,而请求的结果内核态可以通过syscall返回给用户态,最大程度保障了操作系统的安全稳定(用户空间通过向内核空间发出Syscall,产生[软中断]、而让程序陷入内核态,执行相应的操作)
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main() {
// 打开文件
int file_descriptor =open("example.txt",
O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR);
if (file_descriptor== -1) {
perror("Erroropening file");
return 1;
}
// 写入文件
const char *text ="Hello, System Call!";
ssize_t bytes_written= write(file_descriptor,
text, strlen(text));
if (bytes_written== -1) {
perror("Errorwriting to file");
close(file_descriptor);
return 1;
}
// 关闭文件
close(file_descriptor);
return 0;
}
open
、write
和close
等函数都是系统调用。open
用于打开文件,write
用于写入文件,close
用于关闭文件。这些函数提供了对底层文件系统的访问,涉及到了内核态的操作。syscall
指令触发从用户态到内核态的切换,执行相应的系统调用。这里的例子演示了如何创建一个文件并写入内容,是系统调用在文件操作中的简单应用。系统调用 fork与execve
bash -c whoami
时,用户输入的是bash -c whoami
而内核态执行的是bash(pid:52350) -->
sys_fork -->
bash(pid:52796) -->
sys_execve -->
/bin/whoami(pid:52796)
-
bash -c: 这部分命令告诉系统使用bash来执行一段特定的代码。 -
whoami: 这部分命令是 bash -c
要执行的具体代码,它将返回当前执行这段代码的用户的用户名。
-
用户输入: bash -c whoami
-
Shell解析: Shell(用户界面)解析用户输入,发现 bash -c
是一条命令,并理解后面的whoami
是bash -c
要执行的代码。 -
创建新进程(bash): Shell 使用系统调用 fork
创建一个新的进程(子进程),让子进程执行bash
。 -
新进程(bash)的PID(Process ID)为52796。 -
执行新进程(bash): 子进程(bash)开始执行,解释 bash -c whoami
。 -
创建新进程(whoami): 在 bash -c
的执行过程中,bash
发现后面要执行whoami
,于是使用系统调用fork
再创建一个新的进程(子进程),让这个新进程执行whoami
。 -
新进程(whoami)的PID为52796。 -
执行新进程(whoami): 子进程(whoami)开始执行,它是 bash -c
的一个子过程,执行的是whoami
命令。 -
系统调用(execve): 子进程(whoami)调用 execve
系统调用来执行/bin/whoami
。 -
加载程序: execve
系统调用加载/bin/whoami
程序到子进程(whoami)的内存空间。 -
执行程序: 子进程(whoami)开始执行 /bin/whoami
程序。 -
返回结果: /bin/whoami
程序执行完成后,将结果返回给子进程。 -
退出子进程(whoami): 子进程(whoami)执行完毕后退出。 -
返回结果给父进程(bash): 子进程(whoami)的执行结果返回给了父进程(bash)。 -
退出父进程(bash): 父进程(bash)等待子进程(whoami)执行完毕后,也退出。
fork
和execve
等系统调用bash -c whoami
在内核态得到执行,返回了当前用户的用户名RCE漏洞的原理与成功执行的条件
Shell 与 RCE 漏洞
Shell作为用户与操作系统交互的接口,在RCE漏洞的产生中扮演了关键角色。当应用程序通过shell执行外部命令时,如果这些命令包括未经过滤或转义的用户输入,就可能导致RCE漏洞。这种情况下,恶意构造的输入被shell解释执行,从而允许攻击者运行任意代码。 Fork-Execve过程与RCE
在Unix和类Unix系统中,进程的创建和命令的执行通常通过 fork()
和execve()
系统调用实现。当应用程序以拥有shell权限的用户身份运行,并使用这些系统调用执行外部命令时,恶意输入的拼接可能触发RCE漏洞。相比之下,直接使用execve()
执行命令通常更安全,因为它不会创建新的shell进程,从而减少了恶意输入被解释执行的可能性。PHP的特殊情况
在PHP中,许多执行外部命令的函数实际上是通过调用 sh -c
来执行命令的。这增加了RCE的风险,因为它为恶意输入提供了一个直接的执行路径。受限情况下的RCE利用
在受限的环境中,例如沙箱环境、受限的服务器配置或权限受限的账户,RCE的实现更具挑战性。在这些环境中,攻击者可能无法直接执行任意命令,但仍可以通过利用现有进程或应用程序的特定功能和参数来实现RCE。 示例:利用Curl进行RCE
在一个只允许执行 curl
命令的沙箱环境中,攻击者可能利用curl
的功能和shell的命令替换来绕过限制。例如,通过构造如下命令:bashCopy code
curl https://example.com/file.txt -o >(cat)在这个示例中, >(cat)
是一种命令替换的语法,它允许将cat
命令的输出结果作为文件路径传递给-o
参数。这种方法可以被用来绕过写入文件的限制,直接在标准输出上显示下载的内容,从而在受限环境中实现间接的RCE。(cat) 的命令替换:>(cat) 是一种命令替换的语法。在这个上下文中,它的作用是将 cat 命令的输出结果作为文件路径传递给 -o 参数
构造的目的是在沙箱环境中绕过将内容写入文件的限制,而是直接输出到标准输出,使得你可以在沙箱环境中查看下载的内容,而无需直接写入文件
原文始发于微信公众号(安全客):解析RCE:原理、利用条件与受限环境下的探索