命令注入漏洞
接口:POST localhost:5000/snmp
请求参数:
{"host":"test","asset_type":"pc","version":"1`touch /tmp/test.txt`","community":"public"}
注入成功分析
从接口名称,以及接口请求方法可以看出,这是一个对snmp管理对接口,那么何为snmp呢?
简单网络管理协议(SNMP)是一个与网络设备交互的简单方法,一个网络 设备以守护进程的方式运行SNMP代理,该守护进程能够响应来自网络的各种请求信息。
该SNMP代理提供大量的对象标识符(OID-Object Identifiers)。一个OID是一个唯一的键值对。该代理存放这些值并让它们可用。
一个SNMP管理器(客户)可以向代理查询键值对中的特定信息。由于OID都非常长,使得人们难以记住,或者对他非常感冒。
因此,人们就设计了一种将数字OID翻译为人们可读的格式。这种翻译映射被保存在一个被称为 "管理信息基础"(Management Infomation Base) 或MIB的、可传递的无格式文本文件里。
使用SNMP或者向SNMP设备查询,你不需要使用MIB,但是,如果没有MIB,你就得猜测你正在查看的数据是什么。
某些情况下,不使用MIB也非常简单,例如查看主机名、磁盘使用率数字,或者端口状态信息。
SNMP v3 在前面的版本上增加了安全能力和远程配置能力,SNMPv3结构为消息安全和VACM(View-based Access Control Model)引入了USM(User-based Security Model)。这个结构支持同时使用不同的安全机制,接入控制,消息处理模型。SNMP v3 也引入使用SNMP SET命令动态配置 SNMP agent而不失MIB对象代表agent配置。
这些动态配置支持能够增加,删除,修改和配置远程或本地实体。
SNMP V3有三个可能的安全级别: noAuthNoPriv, authNoPriv, 和 authPriv.
noAuthNoPriv 级别指明了没有认证或私密性被执行.
authNoPriv 级别指明了认证被执行但没有私密性被执行.
authPriv 级别指明了认证和私密性都被执行.
auth---认证 支持MD5 or SHA;
priv---加密 支持DES or RSA;
接口能被攻击者注入成功的原因是,开发者需要根据参数构造相应的snmp控制台执行命令。在参数验证不够严谨的情况下,会将攻击者构造的参数带入到命令中执行。
从请求body中可以看出,攻击者注入了一条创建文件的命令touch /tmp/test.txt
,因为开发者安全能力不足,或者没有考虑到该情况,导致命令被执行
接口请求后,可以在服务器中查看该文件是否被创建,从而验证是否被成功注入
root@1596979f06df:/tmp# ls
tmpm89hn269
root@1596979f06df:/tmp# ls
test.txt tmpm89hn269
可以看到,成功生成了文件。那如果攻击者将该命令改为执行脚本,那危害就会几何放大。
那,我们该如何修复此类漏洞呢?
命令注入修复
1、该接口,我明确知道版本号是1、2、3,因此,我可以判断版本号是否在这些值内,如果不在范围内,就return返回,中断程序的执行,有效防止命令注入。
2、也可以做类型判断,将版本号强势转成int类型,然后判断版本号是否在该版本列表内,如果不是,也中断程序执行。
我在代码中采用的是将该值做类型转换,可以过滤掉其他不必要的字符。
比如参数 version
的值是 "2`touch /tmp/test.txt`",进行类型转换( intval($version)
)后,该值就被转换成了数字 2
,将注入字符串给过滤掉了,修复了该注入漏洞。
扩展
命令注入漏洞,大多都是在字符串中夹杂了可执行的命令脚本。而我们通过程序,在终端执行命令的时候,又会隐秘的执行注入命令,因此过滤这些特殊字符,可以很有效的防范此类注入。
而这些特殊字符中,又以反引号(`)为最。从我们的安全测试报告中可以总结出,大部分的注入脚本都是被反引号包裹者的,因此过滤这类字符就可以防止大部分的脚本注入攻击。
网友评论