Genel Bakış
OS Komut Enjeksiyonu, bir uygulamanın temizlenmemiş, saldırgan tarafından kontrol edilen verileri bir sistem kabuk yorumlayıcısına ilettiği bir güvenlik açığıdır. Yorumlayıcı, enjekte edilen belirteçleri uygulama sürecinin ayrıcalıklarıyla ayrı OS komutları olarak yürütür. Tek bir başarılı istismar herhangi bir ek güvenlik açığı zincirlenmesi gerektirmeksizin tam ana makine ele geçirilmesiyle sonuçlanabileceğinden bu güvenlik açığı sınıfı sürekli olarak en tehlikeli kategoriler arasında yer almaktadır.
Zayıflık CWE-78 olarak kataloglanmış olup daha geniş Enjeksiyon kategorisinin (OWASP A03:2021) bir üyesidir. Enjekte edilen yükün uygulama düzeyindeki yorumlayıcıyı değil OS kabuğunu hedef alması bakımından Kod Enjeksiyonundan (CWE-94) ayrılır.
Nasıl çalışır?
Savunmasız uygulamalar genellikle statik komut parçalarını kullanıcı tarafından sağlanan değerlerle birleştirerek OS komut dizeleri oluşturur. Bu girdideki kabuk üst karakterleri kabuk tarafından yorumlanarak komut ayırma ve zincirlemeye olanak tanır. Yaygın saldırı kalıpları şunlardır:
- Noktalı virgül ayırıcısı (
;) – hedeflenen komutu sonlandırarak yeni bir komut başlatır:ping 127.0.0.1; id - Boru operatörü (
|) – birinci komutun çıktısını enjekte edilen komuta yönlendirir:girdi | cat /etc/passwd - Mantıksal VE / VEYA (
&&,||) – sonraki komutları koşullu olarak çalıştırır:dir && whoami - Ters tırnak / dolar-parantez ikamesi (
`komut`,$(komut)) – komut çıktısını satır içine gömer:echo $(id) - Yeni satır enjeksiyonu (
%0a) – görünür üst karakterleri engelleyen filtreleri atlar. - Bant dışı (kör) enjeksiyon – komut çıktısının HTTP yanıtında yansıtılmadığı durumlarda sızdırma DNS sorguları veya HTTP geri çağrıları yoluyla gerçekleşir.
Savunmasız kod kalıpları pek çok dil ve çalışma zamanında mevcuttur:
- PHP:
exec(),shell_exec(),passthru(),system(), ters tırnak operatörü - Python:
os.system(),subprocess.call(shell=True),os.popen() - Java: Argüman kabuk dizesi olarak kullanıcı girdisinden oluşturulduğunda
Runtime.exec() - Node.js:
child_process.exec() - Ruby:
system(), ters tırnak operatörü,IO.popen()
Uygulama komut çıktısını görüntülemese bile güvenlik açığı istismar edilebilir (kör enjeksiyon). Zaman tabanlı yoklama (örn. sleep 5 veya ping -n 5 127.0.0.1 enjekte etmek) görünür çıktı olmadan istismar edilebilirliği doğrulayabilir.
İş etkisi
Başarılı bir OS Komut Enjeksiyonu istismarı, saldırgana ele geçirilen uygulama süreciyle aynı OS düzeyinde ayrıcalıklar tanır. Sonuçlar şunları kapsar:
- Tam ana makine ele geçirilmesi – rastgele dosya okuma/yazma, süreç yürütme ve iç ağlar üzerinde yanal hareket.
- Veri sızdırma – veritabanı kimlik bilgilerine, özel anahtarlara, ortam değişkenlerine ve hassas dosyalara (
/etc/shadow, uygulama yapılandırma dosyaları) erişim. - Kalıcılık – uygulama yeniden başlatmalarından sağ kurtulan arka kapılar, web kabukları veya cron görevlerinin yüklenmesi.
- Hizmet kesintisi – verilerin kasıtlı olarak imha edilmesi veya şifrelenmesi, süreç sonlandırma veya ağ kesintisi.
- Uyumluluk ve hukuki maruziyet – GDPR, PCI DSS, KVKK, HIPAA ve benzer çerçevelerin ihlali; buna eşlik eden bildirim yükümlülükleri ve potansiyel para cezaları.
- İtibar kaybı – iyi bilinen ve önlenebilir bir güvenlik açığı sınıfından kaynaklanan ihlalin kamuoyuna açıklanması sıklıkla müşteri güvenine zarar verir.
Nasıl düzeltilir?
- Kabuk çağrısından tamamen kaçının. En etkili savunma, kabuk dağıtım işlevlerini bağımsız değişken dizileri kabul eden ve hiçbir zaman kabuk çağırmayan API düzeyindeki eşdeğerleriyle değiştirmektir. Örneğin Python'da
os.system("ping " + host)yerinesubprocess.run(["ping", host], shell=False)kullanın. Bağımsız değişken dizisi formları, bağımsız değişkenler kabuk ayrıştırması olmadan doğrudan işletim sistemine iletildiğinden kabuk üst karakteri yorumlamasını engeller. - Girdiyi katı biçimde doğrulayın ve izin listesi (allowlist) kullanın. OS komut çağrısından kaçınmak mümkün değilse kullanıcı tarafından sağlanan değerleri yalnızca alfanümerik karakterler gibi bilinen güvenli karakterlerin katı bir izin listesiyle kısıtlayın. Eşleşmeyen herhangi bir girdi için reddedip işlemi sonlandırın. Yalnızca üst karakterleri engellemeye dayalı red listeleri yetersizdir ve kolayca atlatılır.
- Kabuk bağımsız değişkenlerini doğru biçimde çıkış yapın (escape edin). İzin listesi uygulanamaz olduğunda dile özgü çıkış işlevlerini kullanın: Python'da
shlex.quote(), PHP'deescapeshellarg(). Asla özel bir çıkış yordamı yazmayın. - En az ayrıcalık ilkelerini uygulayın. Uygulamayı gereken minimum izinlere sahip özel bir OS kullanıcısı altında çalıştırın. Başarılı bir enjeksiyonun patlama yarıçapını sınırlamak için dosya sistemi ad alanlarını, konteynerleri veya hapsedilmiş ortamları (jail) kullanın.
- Gereksiz kabuk özelliklerini devre dışı bırakın. Mümkün olduğunda uygulama çalışma zamanı ortamında kabuk yorumlayıcılarının kullanımını devre dışı bırakın veya kısıtlayın (örn. PHP'de
php.iniiçindekidisable_functionsyönergesi aracılığıyla). - Güvenlik odaklı kod incelemesi ve SAST uygulayın. CI/CD ardışık düzenlerinde kirlenmiş veri kaynaklarıyla kabuk çağrısı havuzlarını hedefleyen statik analiz kuralları ekleyin.
- Çalışma zamanı koruması dağıtın. Web Uygulaması Güvenlik Duvarları (WAF) ve Çalışma Zamanı Uygulama Öz Koruması (RASP) ajanları yaygın enjeksiyon kalıplarını tespit edip engelleyebilir; ancak birincil hafifletici tedbirler olarak değil, derinlemesine savunma önlemleri olarak değerlendirilmelidir.
- Düzenli sızma testi gerçekleştirin. Manuel testler ve otomatik tarama—Sensagraph web'e açık uç noktalar üzerindeki OS Komut Enjeksiyonunu tespit eder—sürekli bir güvenlik programının parçası olmalıdır.
Kaynaklar
- OWASP – Komut Enjeksiyonu (Command Injection)
- OWASP Top 10 2021 – A03: Enjeksiyon
- OWASP Kopya Kağıdı – OS Komut Enjeksiyonu Savunması
- MITRE CWE-78 – OS Komutunda Kullanılan Özel Öğelerin Uygunsuz Nötralizasyonu
- PortSwigger Web Security Academy – OS Komut Enjeksiyonu
- Python Belgeleri – subprocess modülü (güvenli API düzeyinde çağrım)
- PHP Kılavuzu – escapeshellarg()