
حل بديل عام لثغرة log4j CVE-2021-44228
يوفر هذا المشروع حلًا مؤقتًا عام الاستخدام لثغرة log4j CVE-2021-44228، ويمكن استخدامه في حال لم يتوفر لديك بديل على المدى القصير لإعادة بناء مشروعك أو لتصحيح ملفات log4j-core jars.
الفكرة وراء ذلك بسيطة للغاية: نقوم بإجبار مُحمِّل الفئات (class loader) على تحميل نسخة "فارغة" من فئة JndiLookup باستخدام خيار "-Xbootclasspath/a" في بيئة تشغيل java.
لذلك، يتكوّن الحل المؤقت بأكمله من هذه الفئة الوحيدة "org.apache.logging.log4j.core.lookup.JndiLookup.java" وليس له أي تبعيات أخرى.
يوجد أيضًا ملف pom.xml لتسهيل الترجمة وتعبئته في ملف jar عبر Maven، لكن يمكنك فعل ذلك ببساطة باستخدام JDK الذي تفضّله، عبر الأمرين "javac" و "jar".
لاحظ أن هذه النسخة الفارغة من فئة "JndiLookup" لا يمكن أن تكون متوافقة مع تنفيذ log4j2 الأصلي، لأن ذلك سيفشل في بعض حالات تحميل الفئات.
عند تطبيق الحل المؤقت سترى الرسالة التالية:
"WARN JNDI lookup class is not available because this JRE does not support JNDI.
JNDI string lookups will not be available, continuing configuration.
Ignoring java.lang.ClassCastException: class org.apache.logging.log4j.core.lookup.JndiLookup"
ستستمر Log4j2 في العمل دون مشاكل على أي حال، فقط دون استخدام أي JNDI lookup - وها نحن ذا - تم تعطيل JNDI lookup!
بمجرد ترجمة الفئة وإنشاء ملف jar، أضف الخيار "-Xbootclasspath/a:" في بداية أمر Java الخاص بك وأشر إلى الدليل الذي وضعت فيه ملف jar (مثل log4j-workaround-1.0-SNAPSHOT.jar). راجع قسم إثبات المفهوم للحصول على مثال حول كيفية القيام بذلك.
يمكن لأمر Java الذي تطبّق عليه هذا الحل المؤقت أن يشغّل أي شيء (Weblgic, Tomcat, fat jar مبني بواسطة spring, ...).
يمكنك تجاهل ما يلي إذا كنت مهتمًا بالحل المؤقت فقط، ولكنك لست مهتمًا بكيفية التحقق من أنه يعمل فعلاً.
للتحقق من صحة هذا النهج، أضفت مجلد "POC" يحتوي على مشروع Maven آخر. لم أرغب في استخدام أي اختبارات وحدة، بل فضّلت البقاء قريبًا من بيئات الإنتاج، التي تستخدم تشغيلًا صريحًا عبر سطر الأوامر لملفات fat jar أو تشغيل حاوية مثل Tomcat الذي تحققت من الحل معه.
يحتوي إثبات المفهوم على فئتين: "POC.java" لاختبار الحل المؤقت عبر سطر الأوامر، و"POCServlet.java" لاختبار ذلك في خادم تطبيقات.
يحاول كلا السيناريوهين تسجيل "${jndi:ldap://localhost/test}"، ولهذا سيحاول log4j الاتصال بـ ldap على مضيفك المحلي دون تطبيق الحل المؤقت وسيفشل مع رفض الاتصال.
لتشغيل POC عبر سطر الأوامر (بعد بنائه في Maven):
انتقل إلى الدليل "target\log4j-workaround-1.0-SNAPSHOT\WEB-INF" ثم نفّذ (إذا كنت تستخدم سطر أوامر Windows):
java -Xbootclasspath/a:..\..\..\..\target\log4j-workaround-1.0-SNAPSHOT.jar -classpath classes;lib\* com.github.grimch.log4j_workaround.poc.POC
لتشغيل POC باستخدام Tomcat:
لماذا نستخدم "-Xbootclasspath" أصلًا بدلاً من مجرد وضع jar الحل المؤقت كأول إدخال في classpath "العادي"؟ حسنًا - تتيح لك بعض الحاويات التأثير في تحميل الفئات بحيث تحظى ملفات jar الموجودة في أرشيف التطبيق المنشور بأولوية على ما يماثلها في classpath الخاص بالنظام. أما أي شيء في bootstrap classpath فله الأولوية على كل ما عداه.
إذا كنت متأكدًا مع ذلك من أنك لا تستخدم أي شيء من هذا القبيل (مثل "prefer-application-packages" في Weblogic") فيمكنك أيضًا استخدام بديل "-classpath".