Ders 23 - Stored XSS (Medium Level)
Bu yazıda güvenlik düzeyi Medium seviyesine yükseltilmiş DVWA'da Stored XSS'e karşı ne gibi bir güvenlik önlemi alındığı incelenecektir ve alınan güvenlik önlemine rağmen yine Stored XSS saldırısı düzenlenebilir mi sorusuna yanıt aranacaktır.

Dersin Hedefi

Hedefiniz Medium seviyesindeki güvenliği keşfedip nasıl aşabileceğinizi öğrenmektir.

Stored XSS'e Karşı Önlem

Geçen ders nasıl Stored XSS saldırısı yapılırı hem teorik hem de pratik olarak görmüştük. O derste bizim Stored XSS saldırısı düzenleyebilmemizin nedeni aşağıdaki kaynak kodun sayfada kullanılıyor olmasından dolayıydı:

Low Level:
<?php 

if( isset( $_POST[ 'btnSign' ] ) ) { 
    // Get input 
    $message = trim( $_POST[ 'mtxMessage' ] ); 
    $name    = trim( $_POST[ 'txtName' ] ); 

    // Sanitize message input 
    $message = stripslashes( $message ); 
    $message = mysql_real_escape_string( $message ); 

    // Sanitize name input 
    $name = mysql_real_escape_string( $name ); 

    // Update database 
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysql_query( $query ) or die( '
' . mysql_error() . '
' ); //mysql_close(); } ?>


5. satırdaki $message değişkeni DWVA ekranındaki ilk metin kutusunun değerini tutmaktadır. 6. satırdaki $name değişkeni ise DWVA ekranındaki ikinci meitn kutusunun (textarea'nın) değerini tutmaktadır. 8. satırdan 13. satıra kadar sanitizing, yani ayıklama işlemi yapılmaktadır. Bu ayıklama işlemleri sadece SQL Injection saldırılarını önlemek için yapılmıştır. Fakat Stored XSS saldırısı için herhangi bir önlem yer almamaktadır. İşte bu yüzden geçen ders Stored XSS saldırısında bulunabilmiştik. Şimdi güvenlik seviyesi Medium'ken ne yapılmış bir bakalım:

Medium Level:
<?php 

if( isset( $_POST[ 'btnSign' ] ) ) { 
    // Get input 
    $message = trim( $_POST[ 'mtxMessage' ] ); 
    $name    = trim( $_POST[ 'txtName' ] ); 

    // Sanitize message input 
    $message = strip_tags( addslashes( $message ) ); 
    $message = mysql_real_escape_string( $message ); 
    $message = htmlspecialchars( $message ); 

    // Sanitize name input 
    $name = str_replace( '<script>', '', $name ); 
    $name = mysql_real_escape_string( $name ); 

    // Update database 
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysql_query( $query ) or die( '
' . mysql_error() . '
' ); //mysql_close(); } ?>


Bu kaynak kodda ilk planda görünen iki güvenlik açığı vardır. İlki 14. satırda yer almaktadır. O satıra göre kullanıcıdan gelen veride eğer <script> kelimesi varsa silinmektedir. Bu görünüşte saldırganları köşeye sıkıştıran bir hamledir. Çünkü saldırgan XSS saldırılarında javascript kodu kullanabilmek için illaki <script> tag'a ihtiyaç duyacaktır. Onun için bu tag olmazsa olmazdır. Fakat bundan daha önceki derslerde gördüğümüz üzere str_replace() fonksiyonu recursive çalışmadığı için iç içe <script> kullanımıyla str_replace() barikatı atlatılabilmektedir. Yani



str_replace()'e girmeden önce:
<scr<script>ipt> Buraya Javascript kodları gelecek </script>

str_replace()'e girdikten sonra:
<script> Buraya Javascript kodları gelecek </script>



str_replace()'den geçen veriden arta kalanlar yine <script> tag'ını oluşturacak ve saldırgan hedefine varabilmiş olacaktır.

Kaynak koddaki ikinci güvenlik açığı ise ekrandaki metin kutularına istemci taraflı karakter limiti konmuşken sunucu taraflı karakter limitinin konulmayışıdır. Daha açık konuşacak olursak ekranda yer alan metin kutularına html ile karakter limiti konmuşken PHP ile karakter limiti konulmamıştır. Bu bir hatadır. Çünkü istemciye yollanan her veri manipule edilebilirdir. Dolayısıyla istemci taraflı barikatlara asla güvenilmemelidir. Hatırlarsanız geçen ders textArea'nın maxlength="50" değerini maxlength="1000" yaparak karakter limitinden kurtulmuştuk ve zararlı kodu kutuya sığdırabilmiştik. Halbuki html'le olduğu kadar PHP ile de karakter limiti konsaydı bu durumda saldırgan belki istemci taraflı barikatı aşacaktı ama sunucuyu geçemeyecekti. Böylece gelen veri limiti aştığı için mesela veritabanına kaydolmayacaktı. Bu yüzden yukarıdaki kaynak koda en basitinden bir if - else yapısıyla limit aşıldığında uyarı ver, limit sağlandığında ise veritabanına kaydet gibi kodlar eklenebilir.

Medium seviyesinin iyi yaptığı bir iş varsa o da ilk metin kutusuna uygulanan filtredir. İlk metin kutusundan gelen veriye 9. satırda strip_tags() fonksiyonu ile kusursuz bir sanitizing (ayıklama) işlemi uygulanmaktadır. Bu fonksiyon kullanıcıdan gelen verideki tüm html ve php tag'larını silmektedir. Böylece saldırgan yazacağı tek bir tag'ı dahi veritabanına kaydettiremeyecektir.
Bu yazı 22.01.2016 tarihinde, saat 12:02:17'de yazılmıştır. 22.01.2016 tarihi ve 14:09:49 saatinde ise güncellenmiştir.
Yazar : Hasan Fatih ŞİMŞEK Görüntülenme Sayısı : 4780
Yorumlar
hasan bayar
Siteniz çok güzel, google'dan buldum. Keşke daha önce keşfetmiş olsaydım. Hakikaten güzel bilgiler barındırıyor.
Bu yorum 07.03.2016 tarihinde, saat 15:00:55'de gönderilmiştir.
deneme
e scscriptript yazarsa bu aşılır ?
Bu yorum 18.11.2016 tarihinde, saat 15:15:38'de gönderilmiştir.
Hasan Fatih ŞİMŞEK
Merhaba Hasan Bayar, yorumun için teşekkürler. İyi çalışmalar.
Bu yorum 27.08.2018 tarihinde, saat 08:47:10'de gönderilmiştir.
Hasan Fatih ŞİMŞEK
Diğer arkadaş, dediğin gibi <sc<script>ipt> yazarsa da aşılır. Yani <script> içerisine <script>'i istediğin yerine koyabilirsin. Her türlü olur.
Bu yorum 27.08.2018 tarihinde, saat 08:48:03'de gönderilmiştir.
Yorum Ekle
*
* (E-posta adresiniz yayınlanmayacaktır.)
*
*

#Arşiv


#Giriş

ID :
Şifre :