No-exec / NX

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Basic Information

Le No-Execute (NX) bit, également connu sous le nom Execute Disable (XD) dans la terminologie Intel, est une fonctionnalité de sécurité matérielle conçue pour atténuer les effets des attaques buffer overflow. Lorsqu’il est implémenté et activé, il distingue les régions mémoire destinées au code exécutable de celles destinées aux données, comme le stack et le heap. L’idée principale est d’empêcher un attaquant d’exécuter du code malveillant via des vulnérabilités de buffer overflow en plaçant le code malveillant sur le stack par exemple et en dirigeant le flux d’exécution vers celui-ci.

Les systèmes d’exploitation modernes appliquent NX via les attributs de la page table qui sous-tendent les en-têtes de programme ELF. Par exemple, l’en-tête PT_GNU_STACK combiné aux propriétés GNU_PROPERTY_X86_FEATURE_1_SHSTK ou GNU_PROPERTY_X86_FEATURE_1_IBT permet au loader de savoir si le stack doit être RW ou RWX. Quand NX est activé et que le binaire a été lié avec un stack non exécutable (-z noexecstack), toute tentative de rediriger l’exécution vers des pages de données contrôlées par l’attaquant (stack, heap, buffers mmap’ed, etc.) déclenchera une faute à moins que ces pages n’aient été explicitement marquées comme exécutables.

Detecting NX quickly

  • checksec --file ./vuln affichera NX enabled ou NX disabled en fonction de l’en-tête de programme GNU_STACK.
  • readelf -W -l ./vuln | grep GNU_STACK expose les permissions du stack ; la présence d’un flag E indique que le stack est exécutable. Example:
$ readelf -W -l ./vuln | grep GNU_STACK
GNU_STACK      0x000000 0x000000 0x000000 0x000000 0x000000 RW  0x10
  • execstack -q ./vuln (de prelink) est utile lors de l’audit de grandes collections de binaires car il affiche X pour les binaires qui ont encore une pile exécutable.
  • À l’exécution, /proc/<pid>/maps montrera si une allocation est rwx, rw-, r-x, etc., ce qui est utile pour vérifier les moteurs JIT ou les allocateurs personnalisés.

Contournements

Primitives de réutilisation de code

Il est possible d’utiliser des techniques telles que ROP pour contourner cette protection en exécutant des morceaux de code exécutable déjà présents dans le binaire. Les chaînes typiques incluent :

  • Ret2libc
  • Ret2syscall
  • Ret2dlresolve when the binary does not import system/execve
  • Ret2csu or Ret2vdso to synthesize syscalls
  • Ret2… — any dispatcher that lets you stitch controlled register state with existing executable code to invoke syscalls or library gadgets.

La procédure est généralement : (1) leak un pointeur code ou libc via un info leak, (2) résoudre les bases des fonctions, et (3) créer une chaîne qui n’a jamais besoin d’octets exécutables contrôlés par l’attaquant.

Sigreturn Oriented Programming (SROP)

SROP construit un faux sigframe sur une page en écriture et pivote l’exécution vers sys_rt_sigreturn (ou l’équivalent ABI pertinent). Le noyau “restaure” alors le contexte forgé, accordant instantanément le contrôle total de tous les registres généraux, de rip et de eflags. Des challenges CTF récents (par exemple, la tâche Hostel dans n00bzCTF 2023) montrent comment les chaînes SROP invoquent d’abord mprotect pour passer la pile en RWX, puis réutilisent la même pile pour du shellcode, contournant ainsi NX même lorsqu’un seul gadget syscall; ret est disponible. Consultez la SROP page dédiée pour plus d’astuces spécifiques à l’architecture.

Ret2mprotect / ret2syscall pour basculer les permissions

Si vous pouvez appeler mprotect, pkey_mprotect, ou même dlopen, vous pouvez légitimement demander un mapping exécutable avant d’exécuter le shellcode. Un petit squelette pwntools ressemble à :

from pwn import *
elf = ELF("./vuln")
rop = ROP(elf)
rop.mprotect(elf.bss(), 0x1000, 7)
payload = flat({offset: rop.chain(), offset+len(rop.chain()): asm(shellcraft.sh())})

La même idée s’applique aux chaînes ret2syscall qui mettent rax=__NR_mprotect, pointent rdi vers une page mmap/.bss, stockent la longueur désirée dans rsi et définissent rdx=7 (PROT_RWX). Une fois qu’une région RWX existe, l’exécution peut sauter en toute sécurité dans des octets contrôlés par l’attaquant.

Primitives RWX des moteurs JIT et des noyaux

Les moteurs JIT, interprètes, pilotes GPU et sous-systèmes du kernel qui émettent dynamiquement du code sont un moyen courant de retrouver de la mémoire exécutable même sous des politiques NX strictes. La vulnérabilité du kernel Linux de 2024 CVE-2024-42067 a montré que des défaillances dans set_memory_rox() laissaient les pages eBPF JIT à la fois écrites et exécutables, permettant aux attaquants d’y placer des gadgets ou des blobs de shellcode entiers à l’intérieur du kernel malgré les attentes NX/W^X. Les exploits qui prennent le contrôle d’un compilateur JIT (BPF, JavaScript, Lua, etc.) peuvent donc faire en sorte que leur payload vive dans ces zones RWX et n’ont besoin que d’un seul overwrite de pointeur de fonction pour sauter dedans.

Réutilisation de code sans retour (JOP/COP)

Si les instructions ret sont durcies (par ex. CET/IBT) ou si le binaire manque de gadgets ret expressifs, basculez vers Jump-Oriented Programming (JOP) ou Call-Oriented Programming (COP). Ces techniques construisent des dispatchers qui utilisent des séquences jmp [reg] ou call [reg] trouvées dans le binaire ou les bibliothèques chargées. Elles respectent toujours NX car elles réutilisent du code exécutable existant, mais elles contournent des mitigations qui surveillent spécifiquement de longues chaînes d’instructions ret.

ROP & JOP

References

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks