From c95c5223743a0ede0e7ef086ec67ef46fe0c8dfa Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 17 Jul 2025 00:13:16 +0000 Subject: [PATCH] Translated ['src/binary-exploitation/common-binary-protections-and-bypas --- .../relro.md | 92 ++++++++++++++++--- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md b/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md index efae1b946..dce7287d6 100644 --- a/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md +++ b/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md @@ -4,30 +4,96 @@ ## Relro -**RELRO** označava **Relocation Read-Only**, i to je bezbednosna funkcija koja se koristi u binarnim datotekama kako bi se smanjili rizici povezani sa **GOT (Global Offset Table)** prepisivanjima. Postoje dve vrste **RELRO** zaštita: (1) **Delimični RELRO** i (2) **Potpuni RELRO**. Obe preuređuju **GOT** i **BSS** iz ELF datoteka, ali sa različitim rezultatima i implikacijama. Konkretno, postavljaju **GOT** sekciju _pre_ **BSS**. To jest, **GOT** je na nižim adresama od **BSS**, što onemogućava prepisivanje **GOT** unosa prelivanjem promenljivih u **BSS** (zapamtite da se pisanje u memoriju dešava od nižih ka višim adresama). +**RELRO** označava **Relocation Read-Only** i to je mitigacija koju implementira linker (`ld`) koja pretvara podskup ELF-ovih segmenata podataka u **samo za čitanje nakon što su sve relokacije primenjene**. Cilj je sprečiti napadača da prepisuje unose u **GOT (Global Offset Table)** ili druge tabele povezane sa relokacijom koje se dereferenciraju tokom izvršavanja programa (npr. `__fini_array`). -Hajde da razložimo koncept na njegove dve različite vrste radi jasnoće. +Moderni linkeri implementiraju RELRO tako što **preuređuju** **GOT** (i nekoliko drugih sekcija) tako da se nalaze **pre** **.bss** i – što je najvažnije – kreiraju posvećen `PT_GNU_RELRO` segment koji se premapira `R–X` odmah nakon što dinamički učitač završi sa primenom relokacija. Kao rezultat, tipični preljevi bafera u **.bss** više ne mogu da dođu do GOT-a i primitivne operacije za proizvoljno pisanje ne mogu se koristiti za prepisivanje pokazivača funkcija koji se nalaze unutar stranice zaštićene RELRO-om. -### **Delimični RELRO** +Postoje **dva nivoa** zaštite koje linker može da generiše: -**Delimični RELRO** koristi jednostavniji pristup za poboljšanje bezbednosti bez značajnog uticaja na performanse binarne datoteke. Delimični RELRO čini **.got samo za čitanje (ne-PLT deo GOT sekcije)**. Imajte na umu da je ostatak sekcije (kao što je .got.plt) i dalje moguće pisati i, stoga, podložan napadima. Ovo **ne sprečava GOT** da bude zloupotrebljen **iz ranjivosti slobodnog pisanja**. +### Partial RELRO -Napomena: Po defaultu, GCC kompajlira binarne datoteke sa Delimičnim RELRO. +* Proizvedeno sa flagom `-Wl,-z,relro` (ili samo `-z relro` kada se direktno poziva `ld`). +* Samo **ne-PLT** deo **GOT**-a (deo koji se koristi za relokacije podataka) se stavlja u segment samo za čitanje. Sekcije koje treba da se modifikuju u vreme izvršavanja – najvažnije **.got.plt** koja podržava **lazy binding** – ostaju zapisive. +* Zbog toga, **primitivna operacija za proizvoljno pisanje** još uvek može preusmeriti tok izvršavanja prepisivanjem PLT unosa (ili izvođenjem **ret2dlresolve**). +* Uticaj na performanse je zanemarljiv i stoga **skoro svaka distribucija već godinama isporučuje pakete sa barem Partial RELRO (to je podrazumevano u GCC/Binutils od 2016)**. -### **Potpuni RELRO** +### Full RELRO -**Potpuni RELRO** pojačava zaštitu tako što **čini celu GOT (i .got i .got.plt) i .fini_array** sekciju potpuno **samo za čitanje.** Kada se binarna datoteka pokrene, svi adrese funkcija se rešavaju i učitavaju u GOT, zatim, GOT se označava kao samo za čitanje, efikasno sprečavajući bilo kakve izmene tokom izvršavanja. +* Proizvedeno sa **oba** flaga `-Wl,-z,relro,-z,now` (poznato i kao `-z relro -z now`). `-z now` prisiljava dinamički učitač da reši **sve** simbole unapred (eager binding) tako da **.got.plt** nikada ne mora ponovo da se piše i može sigurno da se mapira kao samo za čitanje. +* Ceo **GOT**, **.got.plt**, **.fini_array**, **.init_array**, **.preinit_array** i nekoliko dodatnih internih glibc tabela završavaju unutar segmenta samo za čitanje `PT_GNU_RELRO`. +* Dodaje merljiv početni prekorak (sve dinamičke relokacije se obrađuju pri pokretanju) ali **nema prekoraka u vreme izvršavanja**. -Međutim, kompromis sa Potpunim RELRO je u pogledu performansi i vremena pokretanja. Pošto je potrebno da se reše svi dinamički simboli prilikom pokretanja pre nego što se GOT označi kao samo za čitanje, **binarne datoteke sa omogućеним Potpunim RELRO mogu doživeti duže vreme učitavanja**. Ova dodatna prekomerna opterećenja prilikom pokretanja su razlog zašto Potpuni RELRO nije omogućен po defaultu u svim binarnim datotekama. +Od 2023. godine nekoliko mainstream distribucija prešlo je na kompajliranje **sistemskog alata** (i većine paketa) sa **Full RELRO podrazumevano** – npr. **Debian 12 “bookworm” (dpkg-buildflags 13.0.0)** i **Fedora 35+**. Kao pentester, stoga treba da očekujete da se susretnete sa binarnim datotekama gde je **svaki GOT unos samo za čitanje**. -Moguće je videti da li je Potpuni RELRO **omogućen** u binarnoj datoteci sa: +--- + +## Kako proveriti RELRO status binarne datoteke ```bash -readelf -l /proc/ID_PROC/exe | grep BIND_NOW +$ checksec --file ./vuln +[*] '/tmp/vuln' +Arch: amd64-64-little +RELRO: Full +Stack: Canary found +NX: NX enabled +PIE: No PIE (0x400000) +``` +`checksec` (deo [pwntools](https://github.com/pwncollege/pwntools) i mnogih distribucija) analizira `ELF` zaglavlja i prikazuje nivo zaštite. Ako ne možete koristiti `checksec`, oslonite se na `readelf`: +```bash +# Partial RELRO → PT_GNU_RELRO is present but BIND_NOW is *absent* +$ readelf -l ./vuln | grep -E "GNU_RELRO|BIND_NOW" +GNU_RELRO 0x0000000000600e20 0x0000000000600e20 ``` -## Bypass -Ako je Full RELRO omogućen, jedini način da se zaobiđe je da se pronađe drugi način koji ne zahteva pisanje u GOT tabelu za dobijanje proizvoljne izvršne radnje. +```bash +# Full RELRO → PT_GNU_RELRO *and* the DF_BIND_NOW flag +$ readelf -d ./vuln | grep BIND_NOW +0x0000000000000010 (FLAGS) FLAGS: BIND_NOW +``` +Ako se binarni program izvršava (npr. set-uid root pomoćnik), još uvek možete pregledati izvršni fajl **putem `/proc/$PID/exe`**: +```bash +readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO +``` +--- -Napomena da je **LIBC-ova GOT obično Partial RELRO**, tako da se može modifikovati sa proizvoljnim pisanjem. Više informacija u [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.** +## Omogućavanje RELRO prilikom kompajliranja vlastitog koda +```bash +# GCC example – create a PIE with Full RELRO and other common hardenings +$ gcc -fPIE -pie -z relro -z now -Wl,--as-needed -D_FORTIFY_SOURCE=2 main.c -o secure +``` +`-z relro -z now` ради за оба **GCC/clang** (prolazi nakon `-Wl,`) i **ld** direktno. Kada koristite **CMake 3.18+** možete zatražiti Full RELRO sa ugrađenim presetom: +```cmake +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # LTO +set(CMAKE_ENABLE_EXPORTS OFF) +set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) +set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro,-z,now") +``` +--- + +## Tehnike zaobilaženja + +| RELRO nivo | Tipična primitivna | Moguće tehnike eksploatacije | +|-------------|-------------------|----------------------------------| +| Nema / Delimična | Arbitrarna pisanja | 1. Prepisivanje **.got.plt** unosa i preusmeravanje izvršenja.
2. **ret2dlresolve** – kreirati lažni `Elf64_Rela` & `Elf64_Sym` u segmentu koji se može pisati i pozvati `_dl_runtime_resolve`.
3. Prepisivanje pokazivača funkcija u **.fini_array** / **atexit()** listi. | +| Potpuna | GOT je samo za čitanje | 1. Potražiti **druge pokazivače na kod koji se može pisati** (C++ vtables, `__malloc_hook` < glibc 2.34, `__free_hook`, povratni pozivi u prilagođenim `.data` sekcijama, JIT stranice).
2. Zloupotreba *relativnih čitanja* primitiva za curenje libc i izvođenje **SROP/ROP u libc**.
3. Umetanje zlonamerne deljene biblioteke putem **DT_RPATH**/`LD_PRELOAD` (ako je okruženje pod kontrolom napadača) ili **`ld_audit`**.
4. Eksploatacija **format-string** ili delimično prepisivanje pokazivača za preusmeravanje toka kontrole bez dodirivanja GOT-a. | + +> 💡 Čak i sa Potpunim RELRO, **GOT učitanih deljenih biblioteka (npr. libc sama)** je **samo Delimični RELRO** jer su ti objekti već mapirani kada učitavač primeni relokacije. Ako dobijete **arbitrarnu pisanje** primitivu koja može ciljati stranice druge deljene biblioteke, još uvek možete preusmeriti izvršenje prepisivanjem libc-ovih GOT unosa ili `__rtld_global` steka, tehnika koja se redovno koristi u modernim CTF izazovima. + +### Primer zaobilaženja iz stvarnog sveta (2024 CTF – *pwn.college “enlightened”*) + +Izazov je isporučen sa Potpunim RELRO. Eksploit je koristio **off-by-one** za korupciju veličine heap chunk-a, iscurio libc sa `tcache poisoning`, i konačno prepisao `__free_hook` (van RELRO segmenta) sa jednim gadgetom za dobijanje izvršenja koda. Nije bilo potrebno pisanje u GOT. + +--- + +## Nedavna istraživanja i ranjivosti (2022-2025) + +* **glibc 2.40 deprecira `__malloc_hook` / `__free_hook` (2025)** – Većina modernih heap eksploata koji su zloupotrebljavali ove simbole sada mora preći na alternativne vektore kao što su **`rtld_global._dl_load_jump`** ili C++ tabele izuzetaka. Zbog toga što hook-ovi žive **van** RELRO, njihovo uklanjanje povećava težinu zaobilaženja Potpunog RELRO-a. +* **Binutils 2.41 “max-page-size” ispravka (2024)** – Greška je omogućila poslednjih nekoliko bajtova RELRO segmenta da dele stranicu sa podacima koji se mogu pisati na nekim ARM64 verzijama, ostavljajući mali **RELRO razmak** koji se mogao pisati nakon `mprotect`. Upstream sada usklađuje `PT_GNU_RELRO` sa granicama stranica, eliminišući taj ivični slučaj. + +--- + +## Reference + +* Dokumentacija za Binutils – *`-z relro`, `-z now` i `PT_GNU_RELRO`* +* *“RELRO – Potpuni, Delimični i Tehnike zaobilaženja”* – blog post @ wolfslittlered 2023 {{#include ../../banners/hacktricks-training.md}}