Position Independent Executable¶
Ana programı bir
ET_DYNobject'i (-fPIE -pie) olarak derlemek, loader'ın onun text/data'sını randomize edilmiş bir base'e yerleştirmesini sağlar; binary'yi sabit bir adreste bırakmak yerine ASLR'yi executable'ın kendisine genişletir.
Mechanism¶
Neden çalışır
ASLR, stack'in, heap'in, mmap
bölgesinin ve shared library'lerin base'ini randomize eder — ama bir non-PIE
binary'si, program header'larına mutlak load adresleri gömülü bir ET_EXEC
ELF'idir; bu yüzden kernel onun text ve data'sını linker'ın seçtiği sabit
virtual address'e map'lemek zorundadır. Bu, her şey hareket etse bile saldırgana
bilinen code ve data'dan (gadget'lar, GOT/PLT, global function pointer'ları)
oluşan sabit bir ada verir.
Bir Position Independent Executable, bir ET_DYN object'i olarak —
shared library ile aynı ELF type'ı — yalnızca PC-relative adresleme ve symbol
referansları için bir GOT kullanılarak compile ve link edilir. Image'de hiçbir
şey sabit bir load adresi varsaymadığı için, loader, .so library'leri için
zaten yaptığı gibi, executable için tam olarak bir rastgele base seçmekte
özgürdür. Bir PIE'deki function "adresleri" aslında loader'ın base'i seçtiğinde
çözdüğü offset'lerdir.
Invariant: PIE ile, process image'inin hiçbir parçası compile-zamanı-bilinen bir adreste oturmaz. Bu son sabit bölgeyi kapatır, böylece güvenilir code-reuse için (bilinen bir mutlak yerine) tek bir info leak ön koşul haline gelir — PIE'yi, ASLR'nin tüm address space'i kapsamasını sağlayan parça yapar.
Walkthrough¶
1. PIE ile ve PIE olmadan derle, ELF type'ını karşılaştır.
$ gcc -no-pie -fno-pie demo.c -o demo_nopie
$ gcc -fPIE -pie demo.c -o demo_pie # default on most modern distros
$ readelf -h demo_nopie | grep Type
Type: EXEC (Executable file)
$ readelf -h demo_pie | grep Type
Type: DYN (Position-Independent Executable file)
ET_EXEC ⇒ sabit base; ET_DYN ⇒ relocatable, ASLR'ye uygun. (file, aynı
nedenle PIE'yi "ELF ... shared object" olarak raporlar — o bir ET_DYN'dir.)
2. Bir hardening envanteriyle doğrula. checksec, e_type alanını okur;
DYN PIE'ye işaret eder:
$ checksec --file=./demo_pie
RELRO STACK CANARY NX PIE ...
Full RELRO Canary found NX en PIE enabled
$ checksec --file=./demo_nopie
... No PIE (0x400000)
Düz 0x400000, klasik sabit x86-64 ET_EXEC base'idir — bir saldırgan için
bedava bilinen bir adres.
3. Base'in hareket etmesini (PIE) vs sabit kalmasını (non-PIE) izle. ASLR
açıkken (/proc/sys/kernel/randomize_va_space = 2):
$ for i in 1 2 3; do ./demo_pie & sleep 0.05; grep " r-xp .*demo_pie" /proc/$!/maps | head -1; done
55e6a1c1f000-... r-xp ... demo_pie
560b3f4aa000-... r-xp ... demo_pie # base differs each run
$ for i in 1 2 3; do ./demo_nopie & sleep 0.05; grep " r-xp .*demo_nopie" /proc/$!/maps | head -1; done
00400000-... r-xp ... demo_nopie
00400000-... r-xp ... demo_nopie # always 0x400000
PIE entropy/perf maliyeti getirir ve leak'lerden muaf değildir
32-bit'te PIE base entropy'si brute-force edilecek kadar küçüktür. PIE ayrıca GOT-indirection overhead'i ekler; tarihsel olarak register'ı kıt x86-32'de daha ağırdır. Ve PIE base'i yalnızca gizler — bir adres leak edildiğinde hiçbir şey yapmaz.
Detection¶
Statik olarak envanterlemek önemsizdir: readelf -h (Type: DYN), file
("shared object") veya checksec/hardening-check ("PIE enabled" /
"Position Independent Executable: yes"). Bir INTERP segment'i ve bir entry
point'i olan bir DYN bir PIE'dir; INTERP'siz bir DYN sıradan bir shared
library'dir.
Mitigation¶
(Artık risk / bypass.) PIE, yalnızca arkasındaki ASLR entropy'si ve leak'lerin yokluğu kadar güçlüdür. Tek bir pointer leak, rastgele base'i açığa çıkarır ve fixed-offset ROP'u yeniden mümkün kılar. Düşük-entropy base'ler ASLR brute force'a davetiye çıkarır ve offset2lib / partial pointer overwrite gibi partial-overwrite numaraları, tam bir leak olmadan randomization'ı yenebilir veya atlatabilir.
References¶
- Oracle Linux Security Guide. Position-Independent Executables. — https://docs.oracle.com/en/operating-systems/oracle-linux/6/security/ol_pie_sec.html
- Baeldung on Linux. Checking Whether a Linux Executable Is Position-Independent. — https://www.baeldung.com/linux/check-position-independent-executable