
ماسح ذكي لـ Log4Shell/Log4j/CVE-2021-44228
على الرغم من وجود أدوات ممتازة تم إصدارها لمساعدة المؤسسات على فحص بيئاتها بحثًا عن التطبيقات المعرضة للثغرة الحرجة Log4J / CVE-2021-44228، إلا أنني شعرت بأن:
وهكذا وُلد Log4Shell Sentinel. Log4Shell Sentinel هو ماسح يعتمد على الملفات ويتمتع ببعض الميزات الفريدة. ليس الغرض منه استبدال جميع الأدوات المتاحة الأخرى، لكنه يمكن أن يكمّلها.
Log4Shell Sentinel هو ماسح يعتمد على الملفات. يبحث عن التطبيقات المبنية على Java عن طريق فحص النظام المستهدف بحثًا عن مكونات بالتنسيقات التالية:
| نوع الملف | التفاصيل |
|---|---|
| Simple jar | هذه هي الحالة التي لا يكون فيها ملف log4j-core مضمنًا. |
| Fat / Uber jar | الملف uber jar هو ملف jar يحتوي على كل من فئاتك / حزمتك وجميع تبعيات تطبيقك (المكتبات والموارد وملفات البيانات الوصفية) داخل ملف jar واحد. هذا هو خيار النشر الأكثر استخدامًا. |
| WAR | ملف war (أرشيف تطبيق الويب) هو ملف يحتوي على كود JSP وHTML وJavaScript بالإضافة إلى مكتباتك ومواردك الأخرى. هذا التنسيق أقل استخدامًا. |
| EAR | ملف ear (أرشيف تطبيق المؤسسة) هو تنسيق آخر كان أكثر استخدامًا مع Jakarta EE لأغراض النشر. |
ويبحث عن نسخ من ملفات log4j-core المعرضة للخطر. ثم يقوم بما يلي:
حساب تجزئة MD5 للمكوّن. يتيح ذلك للمحلل تحديد نفس التطبيق الذي يعمل على أجهزة / حاويات مختلفة والتعامل معها كاكتشاف واحد
بالنسبة للملفات التي يُحدد أنها تنتمي إلى حاوية مثل: /var/lib/docker/overlay2/192768f471818601094bf4edd96d14bfc0e2b178a04a2efd00b2231ad4e46b33/merged/app/spring-boot-application.jar، يقوم بالجزء الأصعب من العمل وهو ربط الملف بالصورة المقابلة. على سبيل المثال، يترجم ما سبق إلى الصورة التالية: ghcr.io/christophetd/log4shell-vulnerable-app:latest. وبما أن بيئات تشغيل الحاويات المختلفة تخزّن هذا الربط بطرق مختلفة، فإن هذا يمكن أن يوفر على المحلل ساعات من الإحباط. كما يتيح ذلك للمحلل التعامل مع عدد من الحاويات التي تشغّل تطبيقًا واحدًا كاكتشاف واحد.
يقوم بإزالة التطابقات غير المفيدة مثل التطابقات المقابلة للحاويات غير العاملة حاليًا بما في ذلك الصور المخزنة مؤقتًا. يتيح ذلك للمحلل التركيز على ما هو مهم ويوفر له مرة أخرى ساعات من العمل غير الضروري
يتيح للمحلل تجاهل التطابقات بناءً على:
يتيح ذلك للمحلل إزالة التطبيقات التي يعرف أنها غير معرضة للخطر أو التي تتوافق مع تطبيقات تعتمد على سطر الأوامر (CLI) لا تشكل تهديدًا. على سبيل المثال، إذا تم اكتشاف نسخة من Logstash، يمكن للمحلل اختيار تجاهلها إذا كان لا يشغّل الأداة أو يشغّلها فقط من سطر الأوامر من حين لآخر.
تم تحسينها للعمل مع أدوات إدارة التهيئة الخاصة بك مثل Ansible، مما يمنحك القدرة على فحص بيئتك بسرعة في دقائق
للحصول على تفاصيل حول إثراء البيانات الوصفية الذي أضافه Log4Shell Sentinel، راجع منشور مدونتي.
أسهل طريقة هي ببساطة تنزيل الملف الثنائي المُجمَّع مسبقًا.
مرة أخرى، هذا الأمر مباشر. ومع ذلك، من المرجح أنك سترغب في بناء نسخة مُجمَّعة بشكل ثابت (statically compiled) لتجنب أي اختلافات متعلقة بـ GLIBC في بيئتك. تستخدم الأداة الوحدات التالية التي تستخدم CGO افتراضيًا:
os/usernetلبناء نسخة مُجمَّعة بشكل ثابت تستخدم إصدارات Go من هذه المكتبات، ما عليك سوى استنساخ المستودع ثم تشغيل:
$ CGO_ENABLED=0 go build -ldflags="-s -w"
$ ldd log4shell_sentinel
not a dynamic executable
$ ./log4shell_sentinel -h
NAME:
Log4Shell Sentinel - by Osama Elnaggar
USAGE:
log4shell_sentinel [global options] command [command options] [arguments...]
VERSION:
v1.0.0
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--path value, -p value Path to search (default: ".")
--no-banner, --nb Suppress banner (default: false)
--no-messages, --nm Suppress messages except for CSV output (default: false)
--no-header, --nh Suppress header in CSV output (default: false)
--imd5 value, --im value Ignore MD5 hashes. Refer to the GitHub page for expected format
--ipath value, --ip value Ignore file path matches. Refer to the GitHub page for expected format
--icimage value, --ic value Ignore container image matches. Refer to the GitHub page for expected format
--print-headers, --ph Print CSV Headers only (default: false)
--help, -h show help (default: false)
--version, -v print the version (default: false)
بشكل افتراضي، سيقوم الفحص بفحص الدليل الحالي ببساطة. على سبيل المثال:
$ ./log4shell_sentinel
░█░░░█▀█░█▀▀░█░█░█▀▀░█░█░█▀▀░█░░░█░░░░░█▀▀░█▀▀░█▀█░▀█▀░▀█▀░█▀█░█▀▀░█░░
░█░░░█░█░█░█░░▀█░▀▀█░█▀█░█▀▀░█░░░█░░░░░▀▀█░█▀▀░█░█░░█░░░█░░█░█░█▀▀░█░░
░▀▀▀░▀▀▀░▀▀▀░░░▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░▀▀▀░▀▀▀░▀░▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀
- A CVE-2021-44228/CVE-2021-45046/CVE-2021-45105 Scanner
- v1.0.0
- by Osama Elnaggar
[*] WARNING: Running as non-root user.
Non-readable files / dirs will be skipped
Container mapping will fail
[*] Starting shallow scan ............ [DONE]
[*] Starting deep scan ............... [DONE]
[*] Calculating MD5 hashes ........... [DONE]
[*] Performing container image lookups [DONE]
[*] Processing ignore list(s) ........ [DONE]
[*] Generating output ................ [DONE]
IP,Hostname,AppName,Team,Ignore (Y/N),Comments,MD5Hash,Timestamp,Container,ContainerImage,FullPath,Version
192.168.121.121,server3,,,,,4e615cd580758b70c49ade1f79103328,2021-12-21T07:38:09Z,true,ghcr.io/christophetd/log4shell-vulnerable-app:latest,/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,log4j-core-2.14.1.jar
ستحصل فورًا على تحذير إذا قمت بتشغيله كمستخدم غير root لأنه يتطلب صلاحيات root:
ستظل تعمل بدون صلاحيات root ولكنها قد لا تعطيك أفضل النتائج.
تبدو عينة الاكتشاف كما يلي:
IP,Hostname,AppName,Team,Ignore (Y/N),Comments,MD5Hash,Timestamp,Container,ContainerImage,FullPath,Version
192.168.121.121,server3,,,,,4e615cd580758b70c49ade1f79103328,2021-12-21T07:38:09Z,true,ghcr.io/christophetd/log4shell-vulnerable-app:latest,/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,log4j-core-2.14.1.jar
بعض الحقول تُترك فارغة عن قصد ليقوم المحلل بتعبئتها في Excel وما إلى ذلك. يوضح الجدول التالي وصفًا مختصرًا لكل حقل:
تأتي الأداة مع الخيارات التالية:
من الميزات الفريدة لـ Log4Shell Sentinel التي لا توجد في أي أداة أخرى القدرة على ترجمة ملفات jar الموجودة في فحوصات نظام الملفات مثل:
/var/lib/docker/overlay2/192768f471818601094bf4edd96d14bfc0e2b178a04a2efd00b2231ad4e46b33/merged/app/spring-boot-application.jar
إلى صورة الحاوية المقابلة (ما سبق يُترجم إلى ghcr.io/christophetd/log4shell-vulnerable-app:latest على سبيل المثال). وبما أن بيئات تشغيل الحاويات المختلفة تخزّن هذا الربط بطرق مختلفة، فإن هذا يمكن أن يوفر على المحلل ساعات من الإحباط. كما يتيح ذلك للمحلل التعامل مع عدد من الحاويات التي تشغّل تطبيقًا واحدًا كاكتشاف واحد. يدعم الحل حاليًا عمليات الربط التالية:
قد يكون عدد التطبيقات التي تم تحديدها هائلًا في البداية، أو قد ترغب في التركيز على مجموعة فرعية معينة من التطبيقات المحددة مثل تلك المعرضة للمستخدمين الخارجيين أولاً. أو قد ترغب في التركيز على نطاق امتثال معين. لدعم ذلك، تدعم الأداة تحديد قائمة. يدعم Log4Shell حاليًا 3 قوائم تجاهل:
بدلاً من القوائم البسيطة، تتوقع الأداة ملف CSV كمدخلات. وهذا يشجع المحلل على توثيق سبب تجاهله لاكتشاف معين. بينما يعالج المحلل الاكتشافات ويحدد التطبيقات غير المعرضة للخطر باستخدام تحليل مصدر برمجي يدوي أو آلي أو أدوات DAST وما إلى ذلك.
القائمة عبارة عن ملف CSV بسيط بالتنسيق التالي:
MD5Sum,AppName,Reason
قد يكون العمودان AppName و Reason فارغين، لكنهما موجودان لتتمكن من تتبع سبب تضمين أو استبعاد تطبيقات معينة.
ملاحظة نظرًا لأن هذه الميزة تستخدم تجزئة MD5 المحسوبة للتطبيق، فإنها ستعمل فقط مع التطبيقات التي تكون من نوع fat / uber jars أو EARs أو WARs.
على سبيل المثال، إذا كان لدينا الاكتشاف التالي:
IP,Hostname,AppName,Team,Ignore (Y/N),Comments,MD5Hash,Timestamp,Container,ContainerImage,FullPath,Version
192.168.121.121,server3,,,,,4e615cd580758b70c49ade1f79103328,2021-12-21T07:38:09Z,true,ghcr.io/christophetd/log4shell-vulnerable-app:latest,/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,log4j-core-2.14.1.jar
وحددنا أن التطبيق ليس معرضًا للخطر، يمكننا ببساطة حفظ ما يلي في hashes.csv:
4e615cd580758b70c49ade1f79103328,Demo App,Not vulnerable
ثم إعادة تشغيله:
# ./log4shell_sentinel --im hashes.csv --path /
سيتم حذف الاكتشاف أعلاه.
القائمة عبارة عن ملف CSV بسيط بالتنسيق التالي:
Container Image,AppName,Reason
بناءً على المثال السابق، يمكننا إخباره بتجاهل أي اكتشاف تكون فيه صورة الحاوية: ghcr.io/christophetd/log4shell-vulnerable-app:latest عن طريق إنشاء ملف images.csv بهذا الشكل:
ghcr.io/christophetd/log4shell-vulnerable-app:latest,,
ثم تشغيله عن طريق:
# ./log4shell_sentinel --ic images.csv -p /
مرة أخرى، سيتم حذف اكتشافنا السابق.
مرة أخرى، هذا ملف CSV بسيط بالتنسيق التالي:
Path,AppName,Reason
باستخدام المثال أعلاه، إذا أنشأنا ملف paths.csv التالي:
/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,Demo App,Not vulnerable
سيتم حذف الاكتشاف السابق.
تحذير عند الإمكان، من الأفضل استخدام تجزئة MD5 أو اسم صورة الحاوية للحذف لأن المسار قد لا يكون فريدًا
بينما من الجيد تمامًا تشغيل Log4Shell Sentinel على خادم واحد، فإنه يتألق حقًا عند دمجه مع أداة إدارة التهيئة المفضلة لديك (Ansible، Chef، Puppet، Salt، AWS SSM، وما إلى ذلك) أو حتى أدوات SSH المتوازية البسيطة مثل parellel-ssh.
يمنحك هذا فوائد عديدة منها:
للحصول على مثال كامل لهذا التطبيق العملي، راجع منشور مدونتي.
راجع قسم الفحص الشامل لبيئتك.
root (يتطلب الوصول إلى المكان الذي قد تكون تطبيقاتك مثبتة فيه) أو عدم تحديد المسار path الصحيح. يُنصح بتشغيله كمستخدم root وتعيين --path /اعتبارًا من الإصدار v1.0.0، تدعم الأداة حاليًا الربط لـ:
إذا كنت تستخدم أي شيء آخر، فلن يعمل الربط. إذا كنت تستخدم أحد ما سبق، فقد يكون السبب أنك لا تشغّل الأداة كمستخدم root أو أن الملفات / المقابس (sockets) المستخدمة موجودة في موقع غير افتراضي.
تم التطوير بواسطة: Osama Elnaggar
| الحقل | مثال | الوصف |
|---|
| IP | 192.168.121.121 | إذا كان الجهاز يحتوي على عدة عناوين IP، تتم إضافة عنوان IP الأساسي |
| Hostname | server3 | اسم المضيف |
| AppName | يُترك للمستخدم لإكماله بعد انتهاء الفحص | |
| Team | يُترك للمستخدم لإكماله بعد انتهاء الفحص | |
| Ignore (Y/N) | يُترك للمستخدم لإكماله بعد انتهاء الفحص | |
| Comment | يُترك للمستخدم لإكماله بعد انتهاء الفحص | |
| MD5Hash | 4e615cd580758b70c49ade1f79103328 | بصمة فريدة للتطبيق |
| Timestamp | 2021-12-21T07:38:09Z | طابع زمني عند إجراء الفحص. هذا مفيد إذا كنت تريد تجميع عمليات فحص متعددة لنفس المضيف |
| Container | true | صحيح = هذه حاوية |
| ContainerImage | ghcr.io/christophetd/log4shell-vulnerable-app:latest | إذا تم اكتشاف حاوية، فهذه هي الصورة المقابلة لها |
| FullPath | /run/containerd/io.containerd. runtime.v2.task/k8s.io/.../spring-boot-application.jar | المسار الكامل للاكتشاف. في هذا المثال، ملف JAR المعرض للخطر جزء من ملف fat / uber jar |
| Version | log4j-core-2.14.1.jar | إصدار lo4j-core الذي تم اكتشافه |
| الخيار | التفاصيل |
|---|
--path value, -p value | يحدد المسارات التي سيتم البحث فيها. افتراضيًا، يبحث في الدليل الحالي. مهم يُنصح بتعيينه على / لتغطية نظام الملفات بالكامل |
--no-banner, --nb | يخفي الشعار (banner) |
--no-messages, --nm | يخفي الرسائل مثل رسائل التقدم |
--no-header, --nh | يخفي ترويسة مخرجات CSV. يُنصح بهذا عند تشغيله على خوادم متعددة |
--imd5 value, --im value | تجاهل تجزئات MD5. مزيد من التفاصيل في قسم قوائم التجاهل |
--ipath value, --ip value | تجاهل تطابقات مسار الملف. مزيد من التفاصيل في قسم قوائم التجاهل |
--icimage value, --ic value | تجاهل تطابقات صورة الحاوية. مزيد من التفاصيل في قسم قوائم التجاهل |
--print-headers, --ph | طباعة ترويسات CSV فقط. عند تشغيل Log4Shell Sentinel على خوادم متعددة وتجميع النتائج، عادةً ما تقوم بتعطيل إخراج الترويسة. يخرج هذا الأمر الترويسة فقط حتى تتمكن من إضافتها إلى ورقة Excel الخاصة بك |