Mehmet

WFN Üye
Konular
1,851
Mesajlar
1,852
Çözüm
0
Ticaret Puanı
0
Üyelik
1 Ay 6 Gün
Konum
YurtDışı
Web Sitesi
Var
Alanı
Google Adsense
1/1
Konu sahibi
Command injection, kullanıcının kontrol ettiği verinin işletim sistemi komutuna güvenli sınırlar olmadan eklenmesi ve saldırganın uygulama adına ek komutlar çalıştırabilmesidir. Sorun yalnızca girdinin beklenmeyen bir değer olması değil, uygulamanın bu girdiyi kabuk tarafından yorumlanan bir komut metnine dönüştürmesidir. Başarılı bir saldırı; dosya okuma, veri değiştirme, yetki kötüye kullanımı veya sunucuda çalışan uygulamanın erişebildiği kaynakların ele geçirilmesiyle sonuçlanabilir.

Nasıl çalışır?​


Uygulama, örneğin bir dosya adını veya alan adını alıp bunu system, exec, shell_exec, os.system ya da kabuk çağıran benzer bir işleve doğrudan verirse risk oluşur. Kabuk; ;, &&, ||, komut değiştirme karakterleri ve yönlendirme işaretleri gibi özel karakterleri ayrı bir komut anlamında yorumlayabilir.

Varsayımsal olarak şu PHP kodu güvensizdir:

Kod:
$file = $_GET['file'] ?? '';
$output = shell_exec('cat ' . $file);

Uygulama normalde report.txt değerini bekler. Ancak saldırganın gönderdiği değer komut ayırıcı içeren bir metne dönüşürse, uygulama yalnızca dosyayı okumak yerine ek bir işletim sistemi komutu da çalıştırabilir. Bunun gerçekleşip gerçekleşmeyeceği kullanılan işletim sistemi, kabuk, PHP ayarı ve uygulama kullanıcısının yetkilerine bağlıdır; fakat güvenlik açığının temel nedeni değişmez: dış girdinin komut metnine birleştirilmesi.

En güvenli çözüm, dosya işlemi için hiç kabuk komutu kullanmamaktır:

PHP:
<?php
// Yalnız size ait denemede küçük, herkese açık rapor dosyası önceden hazırdır.
// Dizin ve dosya güvenilmeyen kullanıcılarca değiştirilemez olmalıdır.
$files = ['rapor' => '/srv/example-data/public-report.txt'];
$key = $_GET['id'] ?? '';

if (!is_string($key) || !isset($files[$key])) {
    http_response_code(400);
    exit('Geçersiz rapor');
}

$text = file_get_contents($files[$key]);
if ($text === false) {
    http_response_code(500);
    exit('Rapor okunamadı');
}

header('Content-Type: text/plain; charset=UTF-8');
echo $text;

Dosyayı sunan PHP kodu için uygun PHP sunucusu gerekir. id=rapor metni döndürür, bilinmeyen veya dizi tipindeki id 400 verir; dosya yolu girdiden türetilmez. Kod yalnız herkese açık küçük rapor içindir; özel dosyada ayrıca oturum ve dosya bazlı yetki kontrolü gerekir. Üretimde hata ayrıntıları ekrana basılmamalıdır. Burada komut kabuğu devreye girmez. İhtiyaç gerçekten harici bir program çalıştırmaksa, kabuk üzerinden metin birleştirmek yerine kullanılan dilin kabuk açmayan süreç API’si ve ayrı argüman desteği tercih edilmelidir. Argümanların yine de izin verilen değerlerle sınırlandırılması gerekir; yalnızca kaçışlama fonksiyonuna güvenmek tasarım hatasını ortadan kaldırmaz.

Benzer sorunlardan ayırma​


Bir girdinin komuta eklenmesi her zaman aynı tür etkiyi doğurmaz. Aşağıdaki ayrım, düzeltme kararını kolaylaştırır.

SorunTemel nedenÖncelikli yaklaşım
Command injectionGirdi yeni bir işletim sistemi komutu çalıştırabiliyorKabuk çağrısını kaldırmak veya güvenli süreç API’sine geçmek
Argument injectionGirdi aynı programa beklenmeyen seçenek ya da argüman ekliyorArgümanları ayrı geçirmek ve izin verilen değerleri açıkça sınırlamak
Path traversalGirdi, izin verilen dizinin dışındaki dosyaya erişim sağlıyorSabit kök dizin, yol doğrulama ve erişim yetkisi denetimi kullanmak

Örneğin bir süreç API’si kabuk kullanmasa bile saldırganın değeri programın bir seçeneği olarak yorumlanıyorsa yeni kabuk komutu çalışmasa bile argument injection oluşabilir. Bu, komut enjeksiyonu savunmasında ayrıca ele alınan bir alt risk sınıfıdır. Bu nedenle yalnız özel karakterleri silmek yerine verinin hangi işlem için gerekli olduğunu belirlemek gerekir.

Uygulanabilir düzeltme adımları​


  1. Kodda kullanıcı verisini komut metnine ekleyen çağrıları bulun. Web formlarını değil, arka plan işleri, yönetim panelleri, yedekleme görevleri ve dosya dönüştürme işlemlerini de inceleyin.
  2. Harici komut gerekmiyorsa işlemi doğrudan uygulama kütüphanesiyle yapın. Dosya okumada dosya API’si, arşiv işlemlerinde uygun arşiv kütüphanesi, DNS veya ağ işlemlerinde ilgili protokol kütüphanesi kullanılmalıdır.
  3. Harici program zorunluysa komut adını sabit tutun, kullanıcı girdisini ayrı argüman olarak geçirin ve kabuk yorumlamasını devre dışı bırakan süreç yöntemini seçin.
  4. Her argüman için beklenen veri türünü belirleyin. Dosya adı, sayısal kimlik veya seçenek gibi değerleri allowlist ile sınırlandırın; geçersiz girdiyi işlemden önce reddedin.
  5. Düzeltmeden sonra normal değerler, boş değerler, çok uzun değerler, ayraç karakterleri ve seçenek biçimindeki değerlerle test yapın. Sonuç beklenmedik komut çalışması, yetkisiz dosya erişimi veya hatalı seçenek değil, güvenli bir reddetme olmalıdır.
  6. Uygulamanın işletim sistemi hesabını yalnızca ihtiyaç duyduğu dosya ve işlemlere yetkilendirin. Bu, açığı ortadan kaldırmaz; açığın etkisini sınırlar. Olay kayıtlarında ham gizli verileri saklamadan reddedilen istekleri ve ilgili işlem bağlamını izleyin.

Bir test girdisi reddedildiğinde bu tek başına açığın kapandığını kanıtlamaz. Kod yolu gerçekten kabuğa ulaşıyor mu, alternatif bir endpoint aynı işlemi yapıyor mu ve kullanılan kütüphane girdiyi nasıl işliyor soruları da incelenmelidir. Açık bir command injection bulgusu varsa ilgili kod yolu düzeltilip tekrar test edilmeli, aynı işlevi çağıran arka plan görevleri de gözden geçirilmelidir.

Sık sorulan sorular​

escapeshellarg kullanınca bütün sorunlar çözülür mü?​

Tek argümanı kabuk için kaçışlamak, hedef programın o argümanı seçenek olarak yorumlamasını her zaman engellemez. Program destekliyorsa seçenek sonlandırıcı ve dar değer listesi gerekir; yine de önce kabuksuz kütüphane yolunu seçin. İşletim sistemi ve API koşullarını ayırın.

Konteynerde çalışmak açığı ortadan kaldırır mı?​

Hayır. Uygulama hesabının dosya, ağ ve bağlı hizmet yetkileri konteyner içinde de kullanılabilir. İzolasyon ve düşük yetki etkiyi sınırlayan katmanlardır; güvenilmeyen girdiyi komut metnine dönüştüren kod yolunun düzeltilmesi gerekir.
 

Sende şimdi bize katılmak ister misin?

Kayıt ol

Bize katılım kolay ve ücretsizdir!

Konuyu görüntüleyenler

Bu konuyu şu anda görüntüleyen üye bulunmuyor.