Skip to content
Siber Vatan

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 .so dosyası 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 .so dosyası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 .so dosyaları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:

  1. DT_RPATH — Binary içine gömülü, DT_RUNPATH yoksa geçerli
  2. LD_LIBRARY_PATH — Ortam değişkeniyle belirtilen dizinler (secure-execution modunda yok sayılır)
  3. DT_RUNPATH — Binary içine gömülü, LD_LIBRARY_PATH'ten sonra gelir
  4. /etc/ld.so.cache — Önbellek
  5. /lib ve /usr/lib — Varsayılan dizinler

Linux Program Kütüphanesi Yükleme SüreciDinamik 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: RPATH ve RUNPATH aynı şey değildir. RPATH, LD_LIBRARY_PATH'ten önce gelirken RUNPATH sonra 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/RUNPATH zafiyetleri veya zayıf dizin izinleriyle) sahte bir .so dosyası 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 normal çalışması ve saldırganın hazırladığı dosyalar

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 .so dosyası yazar.
  • Bu fonksiyon çağrıldığında istediği işlemi yapar; parola kaydetmek, veri çalmak, komut çalıştırmak gibi.
  • Ardından RTLD_NEXT ile gerçek sistem fonksiyonunu bulup çağırır; uygulama normal akışına devam etmiş gibi görünür.

Sahte fonksiyonun kaynak kodu ve LD_PRELOAD ile çalıştırılması

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.preload ile 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_PRELOAD bir ortam değişkenidir ve sadece onu tanımlayan kullanıcının başlattığı süreçleri etkiler. Ancak /etc/ld.so.preload dosyası 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_PATH ortam değişkeni tamamen yok sayılır.
  • LD_PRELOAD iç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.preload koruması: Bu dosya boş bırakılmalı ve chattr +i komutuyla 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.
  • /tmp dizini kısıtlaması: /tmp, /var/tmp vb. dizinler noexec seç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.

Kaynakça ​

Shared Library Hijacking İçin Kaynakça