Shared Library Hijacking ve LD_PRELOAD
Muhammet Rıdvan Yeniay · @ridvanyeniay
Linux Programları Kütüphaneleri Nasıl Yükler?
Herhangi bir C programı derlediğinizde her şey tek bir dosyaya gömülmez; program çalışma zamanında ihtiyaç duyduğu fonksiyonları sistem kütüphanelerinden alır. Bu kütüphaneler .so uzantılıdır (Shared Object) ve /lib, /usr/lib gibi dizinlerde bulunur.
Neden Shared Library Kullanılır?
- Disk Alanından Tasarruf: Kütüphane kodları her bir çalıştırılabilir program dosyasının içine ayrı ayrı konulmaz; bunun yerine bir referans yerleştirilir. Bu sayede programların boyutları daha küçük olur ve diskte gereksiz kod tekrarı engellenir.
- Bellek Verimliliği: Bir
.sodosyası işletim sistemi tarafından belleğe yalnızca bir kez yüklenir. O kütüphaneye ihtiyaç duyan birçok süreç ve uygulama, bellekteki aynı kod bloğunu paylaşarak çalışır; böylece sistem belleği daha verimli kullanılmış olur. - Kolay Güncelleme ve Güvenlik: Bir kütüphanede hata düzeltmesi veya kritik bir yama yapıldığında yalnızca ilgili
.sodosyasını güncellemek yeterlidir. - Modüler Mimari ve Eklenti Desteği: Geliştiricilerin monolitik yazılımlar yerine modüler sistemler kurmasını kolaylaştırır. Bir program çalışır durumdayken
dlopen()gibi çağrılar aracılığıyla.sodosyalarını sonradan belleğe yükleyebilir veya bellekten çıkarabilir.
Dinamik bağlayıcı (genellikle ld.so) ise Linux'ta dinamik olarak derlenmiş bir program çalıştırıldığında devreye giren ve programın ihtiyaç duyduğu paylaşımlı kütüphaneleri diskten bulup belleğe yükleyen çekirdek bir sistem bileşenidir.
Örnek olarak printf() çağırdığınızda bu fonksiyon aslında libc.so içinde yer alır. Program başlatıldığında dinamik bağlayıcı bu kütüphaneleri bulup belleğe yükler.
Kütüphane Yükleme Mekanizması
Dinamik bağlayıcının çalışma şeklini doğru anlamak için iki ayrı kavramı birbirinden ayırt etmek gerekir:
1. Sembol Çözümleme Önceliği:
LD_PRELOAD ortam değişkeninde belirtilen kütüphaneler, programın tüm bağımlılıklarından önce yüklenir ve sembol çözümlemesinde en yüksek önceliğe sahip olur. Bu bir dizin arama sırası değildir; doğrudan sembol önceliği mekanizmasıdır.
2. Kütüphane Dosyasının Aranacağı Dizin Sırası:
Eğer kütüphane yolu açıkça belirtilmemişse, dinamik bağlayıcı dosyayı şu sırayla arar:
DT_RPATH— Binary içine gömülü,DT_RUNPATHyoksa geçerliLD_LIBRARY_PATH— Ortam değişkeniyle belirtilen dizinler (secure-execution modunda yok sayılır)DT_RUNPATH— Binary içine gömülü,LD_LIBRARY_PATH'ten sonra gelir/etc/ld.so.cache— Önbellek/libve/usr/lib— Varsayılan dizinler
Dinamik bağlayıcının kütüphane arama akışı: LD_PRELOAD en yüksek önceliğe sahipken, kütüphane bulunamazsa sırayla diğer dizinler taranır.
Not:
RPATHveRUNPATHaynı şey değildir.RPATH,LD_LIBRARY_PATH'ten önce gelirkenRUNPATHsonra gelir. Bu ayrım güvenlik değerlendirmelerinde kritik öneme sahiptir.
Liste sırayla taranır ve ilk bulunan kullanılır. Yani bir fonksiyonu öncelikli olan kütüphane tanımlamışsa, sistem kütüphanesi hiç sorulmaz.
İşte LD_PRELOAD saldırısı tam burada devreye girer.
Kavram Tutarlılığı: Hijacking Varyantları
Shared Library Hijacking genel bir terimdir. İki temel varyantı bulunur:
- Dizin/RPATH Hijacking: Yazılabilir bir dizine (örneğin
RPATH/RUNPATHzafiyetleri veya zayıf dizin izinleriyle) sahte bir.sodosyası koyarak sistemin onu yüklemesini sağlamak. - LD_PRELOAD Hijacking: Arama yoluna ihtiyaç duymadan sembol önceliğini doğrudan ele geçirmek. Bu hijacking'in en kolay ve etkili türüdür.
Bu yazıda ağırlıklı olarak LD_PRELOAD varyantı ele alınmaktadır.
LD_PRELOAD Nedir?
LD_PRELOAD, Linux'ta bir ortam değişkenidir. Bu değişken, dinamik bağlayıcıya program başlamadan önce belirli bir kütüphaneyi yüklemesini ve fonksiyon ararken önceliği oraya vermesini söyler.
Bu özellik genellikle geliştirme aşamasında kolaylık sağlaması için kullanılmaktadır. Örneğin bellek sızıntısı tespit araçları, performans profil araçları ya da debug sırasında bir kütüphanedeki tek bir fonksiyonu geçici olarak değiştirmek için kullanılır.
Ama aynı mekanizma saldırganın eline geçtiğinde sonuç değişebilir.
Shared Library Hijacking Nasıl Çalışır?
Saldırının mantığı şudur: dinamik bağlayıcı fonksiyon ararken öncelikli listeyi kullanır. Saldırgan, hedef uygulamanın çağırdığı bir sistem fonksiyonuyla aynı adı taşıyan kendi fonksiyonunu, sisteme onu daha önce yüklemesini söyleyerek araya sokabilir.

Hesap makinesi uygulamasının LD_PRELOAD olmadan standart çalışması ve saldırganın hazırladığı dosyalar: hook_divide.so, libmath.so
- Saldırgan, hedef fonksiyonla aynı imzaya sahip sahte bir fonksiyon içeren bir
.sodosyası yazar. - Bu fonksiyon çağrıldığında istediği işlemi yapar; parola kaydetmek, veri çalmak, komut çalıştırmak gibi.
- Ardından
RTLD_NEXTile gerçek sistem fonksiyonunu bulup çağırır; uygulama normal akışına devam etmiş gibi görünür.

Sahte fonksiyonun (hook) kaynak kodu ve LD_PRELOAD ile çalıştırıldığında araya girerek gizli mesajı (Altay) yazdırması.
İyi ayarlanırsa kullanıcı hiçbir zaman fark etmez.
Saldırı Neden Bu Kadar Etkilidir?
- Görünmezlik: Uygulama kullanıcıya tam olarak beklediği sonucu döndürür. Hata mesajı yoktur, davranış değişikliği yoktur. Log sistemleri tipik olarak bu tür müdahaleleri kayıt altına almaz.
- Geniş Kapsam: Sahte kütüphane
/etc/ld.so.preloadile sisteme yüklendiğinde yalnızca tek bir uygulamayı değil, o fonksiyonu kullanan ve setuid olmayan tüm uygulamaları etkiler. - Kalıcılık ve Yetki Ayrımı:
LD_PRELOADbir ortam değişkenidir ve sadece onu tanımlayan kullanıcının başlattığı süreçleri etkiler. Ancak/etc/ld.so.preloaddosyası sistem genelindedir. Saldırgan root yetkisi elde edip bu dosyaya yazarsa, kalıcılık sağlar ve kullanıcı hiçbir şey yazmadan her oturumda hook devreye girer. - Düşük İz: Yeni bir süreç başlatılmaz, ağ bağlantısı kurulmaz, şüpheli bir dosya çalıştırılmaz. Standart IDS/IPS sistemleri bu tür in-process müdahaleleri genellikle yakalamakta zorlanır.
Setuid ve Secure-Execution İstisnası
Dinamik bağlayıcı, setuid/setgid biti ayarlanmış (örneğin root yetkisiyle çalışan passwd veya su gibi) programlarda "secure-execution" modunda çalışır. Bu modda:
LD_LIBRARY_PATHortam değişkeni tamamen yok sayılır.LD_PRELOADiçin içinde slash (/) bulunan (dizin belirten) yollar reddedilir.- Yalnızca standart güvenli dizinlerde bulunan ve kendisi de setuid yetkisine sahip olan kütüphanelerin yüklenmesine izin verilir.
Bu nedenle ortam değişkeni tabanlı LD_PRELOAD saldırıları setuid programlara karşı doğrudan işe yaramaz.
Sıkılaştırma
/etc/ld.so.preloadkoruması: Bu dosya boş bırakılmalı vechattr +ikomutuyla immutable hale getirilmelidir. Immutable flag eklendiğinde dosya değiştirilemez bir hale gelir. Böylece saldırgan sisteme eriştiğinde kalıcılık mekanizmasını kullanamayabilir./tmpdizini kısıtlaması:/tmp,/var/tmpvb. dizinlernoexecseçeneğiyle mount edilmelidir. Bu sayede saldırgan sahte kütüphanesini bu dizinlere kopyalayıp oradan yüklemeye çalışsa bile sistem izin vermez. Ancak bu tek başına yeterli bir koruma değildir; saldırgan sistemde yazılabilir başka bir dizin bulabilir.

