> For the complete documentation index, see [llms.txt](https://emre-ermenek.gitbook.io/sqli-egitimi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://emre-ermenek.gitbook.io/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/filter-evasion-techniques-filtre-atlatma-teknikleri.md).

# Filter Evasion Techniques(Filtre Atlatma Teknikleri)

#### Filter Evasion (Filtre ve WAF Atlatma Teknikleri)

Şu ana kadar SQL Injection'ın çeşitli türlerini öğrendik. Ancak gerçek dünyada, hedefe `' OR 1=1 --` payload'u gönderdiğinizde çoğu zaman sistem sizin payloadunuzu kabul etmez.

Çünkü yazılımcılar ve sistem yöneticileri hackerların işini zorlaştırmak için kapıya **WAF (Web Application Firewall - Web Uygulama Güvenlik Duvarı)** veya uygulama içi filtreler koyarlar. Bu filtreler, gelen verinin içinde `UNION`, `SELECT`, `OR`,`Tırnak İşareti` veya hatta `Boşluk` karakteri arar. Eğer bulursa isteği anında engeller.

Bu filtreleri atlatmak (bypass) çok önemlidir. Gelin nasıl yapabileceğimize dair tekniklere bakalım:

#### 1. Büyük/Küçük Harf Kullanmak(Case Manipulation)

Yazılımcılar bazen filtreleri çok basit yazar. Örneğin PHP'deki `str_replace` fonksiyonu ile sistemden sadece büyük harfli "OR" kelimesini siliyor olabilirler.

* **Engellenen:** `admin' OR 1=1 --`
* **Bypass:** Kelimenin harf büyüklüklerini değiştirerek filtreyi aşabiliriz

```sql
admin' oR 1=1 --
admin' Or 1=1 --
```

#### 2. Karakter Kodlama (Character Encoding)

WAF'lar genellikle okuyabildikleri metinleri engeller. Eğer metni tarayıcının veya veritabanının anlayabileceği ama filtrenin okuyamayacağı bir dile çevirirsek (Encode edersek) filtreyi aşabiliriz.

(Cyberchef sitesini kullanarak girdileri siz de encode edip görebilirsiniz.)

**→ URL Encoding:** İnternet tarayıcılarının dilidir; boşluk yerine `%20`, tek tırnak yerine `%27` kullanılır. Ancak modern WAF'lar artık bu temel kodlamayı tanıyıp engelleyebiliyor. İşte burada **Double URL Encoding (Çift Kodlama)** dediğimiz teknik işe yarayabilir.

* **Peki Neden İşe Yarar?** Eğer biz tek tırnağı (`%27`) bir kez daha kodlarsak `%2527` elde ederiz(`%` işaretinin kendisi URL dilinde `%25` olarak kodlanır.). WAF bu veriyi yakaladığında **sadece bir kez** çözer (decode eder) ve karşısında zararsız gibi duran `%27` metnini görür, geçişine izin verir. Ancak bu veri arka plandaki asıl sunucuya ulaştığında, sunucu bunu **ikinci kez** çözer ve `%27` tek tırnağa (`'`) dönüşür.

**→ Hexadecimal (Onaltılık) Encoding:** Hatırlarsanız OOB (Out-of-Band) bölümünde HEX'in kullanımından bahsetmiştik. Filtreler metin ararken, hex karşılığına bakmayabilir.

* **Normal:** `SELECT * FROM users WHERE name = 'admin'`
* **Hex:** `SELECT * FROM users WHERE name = 0x61646d696e` (Özellikle MySQL veritabanı 0x61646d696e değerini otomatik olarak admin kelimesine çevirir ama filtre bunu sadece anlamsız bir sayı dizisi sanır.)

**→ Unicode Encoding:** Bazen filtreler sadece standart İngilizce karakterleri (ASCII) tarayacak şekilde tasarlanmıştır. Bu durumda harfleri Unicode kaçış dizileriyle (escape sequences) gizleyebiliriz.

* **Normal:** `admin`
* **Unicode:** `\\u0061\\u0064\\u006d\\u0069\\u006e` (Filtre bu ters eğik çizgileri gördüğünde zararlı bir kelime bulamaz ve isteği geçirir. Ancak WAF'ın arkasındaki web uygulaması veriyi (örneğin JSON içinden) alıp çözerken bu kodları "admin" kelimesine dönüştürür ve veritabanına saf "admin" olarak gönderir.)

#### 3. "Boşluk" Tuşu Yasaklandığında (No Spaces Allowed)

Bazen geliştiriciler sadece klavyedeki o standart boşluk karakterini filtreler. Bunu aşmak için kelimeleri boşluk bırakmadan ayırmanın farklı yollarını kullanırız:

* **SQL Yorum Satırları (`/**/`):** SQL dillerinde `/*` ile `*/` arasına yazılan her şey yorumdur ve veritabanı bunu es geçer. Biz de boşluk koymak yerine kelimelerin arasına boş yorum satırları sıkıştırırız.
  * **Engellenen:** `SELECT * FROM users`
  * **Bypass:** `SELECT/**/*/**/FROM/**/users`
* **Görünmez Karakterler (Tab ve Yeni Satır):** Veritabanları sadece boşluk tuşunu değil, "Tab" (sekme) ve "Enter" (yeni satır) tuşlarını da boşluk gibi kabul eder. Eğer sistem sadece normal boşluğu engellediyse, kelimelerin arasına `\\t` (Tab) veya `\\n` (Yeni Satır) karakterleri koyarak da filtreyi aşabiliriz.
  * **Bypass:** `SELECT\\t*\\tFROM\\tusers`
* **URL Karakterleri:** Üstteki yöntemi web üzerinden gönderirken (örneğin URL'ye yazarken) bu görünmez karakterlerin URL-encoded (kodlanmış) hallerini kullanmak en etkili yöntemdir. WAF'lar `%20`'yi (Boşluk) engeller ama diğerlerini gözden kaçırabilir. İşte boşluk yerine kullanabileceğiniz alternatif görünmez karakterler listesi:
  * `%09` (Yatay Tab)
  * `%0A` (Yeni Satır / Line Feed)
  * `%0C` (Sayfa/Form Atlatma / Form Feed)
  * `%0D` (Satır Başı / Carriage Return)
  * `%A0` (Bölünemez Boşluk / Non-breaking space)
  * **Bypass:** `SELECT%0A*%0AFROM%0Cusers`

#### 4. Tırnak İşareti Yasaklandığında (No-Quote SQLi)

Tek tırnak (`'`) veya çift tırnak (`”`) kullanmamızı sistem engellerse ne yapabiliriz?

* **Sayısal Değerler:**. Eğer SQL Injection yaptığımız yer bir metin değil de sayı alanıysa (örneğin URL'de `id=5` yazıyorsa), arka plandaki sorgu muhtemelen `WHERE id = 5` şeklindedir yani her zaman tırnak işareti gerekmeyebilir. Bu durumda tırnak filtrelerini aşmaya çalışmak yerine doğrudan `5 OR 1=1` yazarak filtreyi hiç muhatap almadan atlatabiliriz.
* **CONCAT() Fonksiyonu:** Tırnak kullanmadan harfleri tek tek ASCII veya Hex olarak birleştiririz.

  `... WHERE username = CHAR(97, 100, 109, 105, 110)` veya `CONCAT(0x61, 0x64...)` (Tırnak kullanmadan admin kelimesini oluşturduk.)
* **SQL Yorum Satırı Kullanımı:** Genelde yazılımcı sorguyu şöyle yazar: `SELECT * FROM users WHERE username = '$user' AND status = 1` , user yerine admin'-- yazmanız işe yaramaz. Yazsanız da sistem o tırnağı filtreler (önüne \ koyarak etkisiz hale getirir) ve sorgu arka planda `... WHERE username = 'admin\\'--'` şekline dönüşür, yani işe yaramaz. Ama bazen sorguyu şöyle yazarlar: `SELECT * FROM users WHERE username = $user AND status = 1` bu durumda bizim zaten tırnak işareti kullanmamız gerekmez `admin--` diye gönderince de çalışır.

***

Gerçek dünyada (Black-Box bir testte) hedefin hangi filtreyi veya WAF'ı kullandığını asla doğrudan göremezsiniz. Bu yüzden filtre atlatmak tamamen sabır ve deneme-yanılma işidir. Tabii eğer sistemin kaynak koduna erişiminiz varsa (örneğin açık kaynaklı bir projeyse), kodu inceleyerek uygulamanın kendi filtreleme mantığını okuyabilirsiniz. Bu size WAF hakkında bilgi vermese de uygulamanın arka planda veriyi nasıl işlediğini ve zayıf noktalarını gösterir.

Bir sonraki kısımda size kısaca otomasyon mantığından bahsetmek istiyorum. Ama geçmeden önce aşağıdaki labı çözmenizi tavsiye ederim. Takılırsanız çözüme bakabilirsiniz:

1- Lab: <https://portswigger.net/web-security/sql-injection/lab-sql-injection-with-filter-bypass-via-xml-encoding>

{% content-ref url="/pages/j8fmUNuT5R9Wbhzky5cF" %}
[SQL injection with filter bypass via XML encoding Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/filter-evasion-techniques-filtre-atlatma-teknikleri/sql-injection-with-filter-bypass-via-xml-encoding-cozumu.md)
{% endcontent-ref %}
