> 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/in-band-sql-injection.md).

# In-Band SQL Injection

Bu teknik SQL Injection’ın en kolay tespit edilen ve sömürülen hali olarak kabul edilir. Türkçesi Bant-içi SQL Enjeksiyonu’dur.

Aynı kanal üzerinden hem veri gönderip hem de sonuç alındığı anlamına gelir. Örneğin sorguyu bir URL ile göndermek ve cevabı aynı sayfa üzerinde görmek.

Kendi altında 2 türü vardır:

1- **Error-Based(Hata Tabanlı) SQL Injection**

2- **UNION-Based(Birleştirme Tabanlı) SQL Injection**

***

**Error-Based SQL Injection:**

**Temel Mantık:** Veritabanında SQL Injection zafiyeti varsa ve sistem hataları ekrana basıyorsa; SQL sorgusunu kasıtlı olarak bozup, dönen detaylı hata mesajlarına bakarak veritabanının yapısını anlamak ve veri sızdırmaktır.

Gerçek dünyada, veritabanından dönen bu detaylı hata mesajları çok yüksek ihtimalle geliştiriciler tarafından kapatılır. Bu durumda, SQL sorgusunu manipüle ettiğimizde sunucu bize sadece genel bir **500 Internal Server Error** döner. Bu, veritabanının gerçek hata mesajı değildir ancak arka planda bir şeyleri bozduğumuzu kanıtlar. Hata mesajı bizden gizlendiği için veriyi ekranda göremeyiz, ancak zafiyetin varlığını anlarız *(Not: Ekranda veri göremediğimiz bu senaryolar, daha çok ileride göreceğimiz **Blind (Kör) SQL Injection** konusuna girer)*.

**Asıl "In-Band" Error-Based SQL Injection** ise, veritabanının döndürdüğü teknik hatayı ekranda net bir şekilde görebildiğimiz senaryodur.

**Örnek Senaryo:** Aşağıdaki gibi bir sorguda, veritabanı sürüm bilgisini (string/metin formundadır) bir tam sayıya (integer) çevirmeye çalışalım:

```sql
SELECT * FROM users WHERE id = 1 AND 1=CONVERT(int, (SELECT @@version))
```

Veritabanı, versiyon metnini sayıya çeviremeyeceği için işlemi yarıda keser ve ekrana içindeki veriyi de barındıran şöyle bir hata mesajı fırlatır:

> *Conversion failed when converting the nvarchar value 'Microsoft SQL Server 2019 (RTM) - 15.0.2000.5...' to data type int.*

Gördüğünüz gibi, hata mesajının içine sıkışmış olan veritabanı versiyonunu başarıyla çaldık.

**Önemli Bir Detay (Fingerprinting):** Bu verdiğimiz `CONVERT` payload'u özel olarak Microsoft SQL Server (MSSQL) içindir. Eğer saldırdığınız sistem MySQL olsaydı bu komut çalışmazdı. MySQL'de benzer hata tabanlı sonuçlar almak için genellikle `EXTRACTVALUE` veya `UPDATEXML` gibi XML ayrıştırma (parsing) fonksiyonları kullanılarak veritabanı kasıtlı olarak hataya zorlanır. Hedefin hangi veritabanını kullandığını bilmek bu yüzden hayati önem taşır.

***

**UNION-Based SQL Injection:**

Mantığı `SELECT` sorgusunu manipüle ederek `UNION` (Birleştir) operatörüyle başka bir `SELECT` sorgusunu koda eklemek ve kendi istediğimiz verileri orijinal verilerin arasına sıkıştırarak ekrana yansıtmaktır.

Peki `UNION` tam olarak ne yapar? Normalde e-ticaret sitesinde "Hediyeler" kategorisine tıkladığınızda veritabanı size bir tablo döner (Ürün Adı, Fiyatı, Resmi vb.). `UNION` operatörü, bu orijinal tablonun hemen altına **ikinci bir tabloyu** yapıştırmamızı sağlar.

Yani sisteme şunu demiş oluruz: *"Bana Hediyeler kategorisindeki ürünleri getir... **BİRLEŞTİR (UNION)** ...Bana veritabanındaki tüm kullanıcı adlarını ve şifreleri getir."*

Sonuç? Ekranda hediyelik eşyaların listelendiği sayfanın en altında, `administrator` hesabının şifresini kabak gibi görürsünüz!

Ancak bu işlemi kafamıza göre yapamayız. Başarılı bir UNION saldırısı yapabilmek için veritabanının bizden istediği **İki Altın Kural** vardır:

**1. Sütun Sayıları Eşit Olmalı (Column Count)** Orijinal sorgu kaç tane sütun (kolon) çekiyorsa, bizim yazdığımız zararlı `UNION` sorgusu da tam olarak o kadar sütun çekmelidir. Eğer ürünler tablosu 3 sütun (Örn: `isim`, `fiyat`, `stok`) getiriyorsa, bizim sorgumuz 2 sütun getirirse veritabanı hata verir ve çalışmaz.

**2. Veri Tipleri Uyumlu Olmalı (Data Types)** Çektiğimiz verilerin tipleri (metin, sayı vb.) birbiriyle eşleşmek zorundadır. Örneğin orijinal tablodaki 2. sütun sadece "Sayı" (Integer) kabul ediyorsa, biz o sütuna kullanıcıların şifrelerini (Metin/String) çekmeye çalışırsak veritabanı yine hata verir.

**UNION-Based SQLi manipüle etmenin temel adımları:**

**Adım 1: Sütun Sayısını Bulmak** Önce orijinal sorgunun kaç sütun döndürdüğünü bulmalıyız. Bunun için `NULL` (boş veri) değerini kullanırız. Çünkü `NULL` her veri tipine uyum sağlar. Hata almayana kadar `NULL` sayısını artırırız:

* `' UNION SELECT NULL --` (Hata verdi, demek ki 1 sütun değil)
* `' UNION SELECT NULL, NULL --` (Hata verdi, demek ki 2 sütun değil)
* `' UNION SELECT NULL, NULL, NULL --` (Sayfa düzgün yüklendi! Harika, demek ki tam 3 sütun var.)

**Alternatif Yöntem (ORDER BY)**: Sütun sayısını bulmanın siber güvenlik uzmanları arasında çok yaygın olan bir diğer yolu da `ORDER BY` komutunu kullanmaktır. Sayfa hata verene kadar sayıyı artırırız:

* `' ORDER BY 1 --` (Sayfa normal yüklendi, demek ki en az 1 sütun var)
* `' ORDER BY 2 --` (Sayfa normal yüklendi)
* `' ORDER BY 3 --` (Sayfa normal yüklendi)
* `' ORDER BY 4 --` (Hata verdi! Veritabanı "4. sütun yok ki ona göre sıralayayım" dedi. Demek ki tablomuz tam olarak 3 sütunlu.)

**Adım 2: Metin (String) Sütununu Bulmak** Kullanıcı adı ve şifre gibi veriler metindir. Bu yüzden bulduğumuz 3 sütundan hangisinin metin kabul ettiğini test etmeliyiz:

* `' UNION SELECT 'a', NULL, NULL --` (Hata verdi, 1. sütun sayı bekliyor)
* `' UNION SELECT NULL, 'a', NULL --` (Sayfa yüklendi ve ekranda 'a' harfini gördük! Demek ki 2. sütuna metin çekebiliriz.)

**Adım 3: Veriyi Çalmak** Sütun sayısını (3) ve metin sütununu (2. sütun) bulduğumuza göre artık asıl veriyi çekebiliriz:

* `' UNION SELECT NULL, username, NULL FROM users --`
* `' UNION SELECT NULL, password, NULL FROM users --`

(Not: Eğer sadece tek bir metin sütunumuz varsa, iki veriyi tek sütuna sıkıştırmak için birleştirme operatörleri kullanılır. Örn: Oracle/PostgreSQL'de `username || '~' || password` kullanılırken, MySQL'de `CONCAT(username, '~', password)` fonksiyonu kullanılır.)

* `' UNION SELECT NULL, username || '~' || password, NULL FROM users --`

Şimdi burada öğrendiklerimizi pratik edelim. Bunun için portswigger lablerini çözücez verdiğim sırada çözebilirsiniz, keyfi sırayla da çözebilirsiniz. Geçmeden önce Burp Suite’in çok temel özelliklerini bilmeniz işinizi çok kolaylaştırır. Proxy ile istek yakalama ve repeater a atıp gönderme gibi. Çözemediğiniz lablarda eklediğim çözümlere bakabilirsiniz, çözerken portswigger’ın sqli cheatsheetine bakmanızı tavsiye ederim: <https://portswigger.net/web-security/sql-injection/cheat-sheet>

Sırayla çözmeniz gereken lab’lar:

1- Lab: <https://portswigger.net/web-security/sql-injection/lab-retrieve-hidden-data>

{% content-ref url="/pages/jBUin0OndhNcx3eLZGTC" %}
[SQL injection vulnerability in WHERE clause allowing retrieval of hidden data Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-vulnerability-in-where-clause-allowing-retrieval-of-hidden-data-cozumu.md)
{% endcontent-ref %}

***

2- Lab: <https://portswigger.net/web-security/sql-injection/lab-login-bypass>

{% content-ref url="/pages/kd9XU2Hu2yVWoBwklDFm" %}
[SQL injection vulnerability allowing login bypass Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-vulnerability-allowing-login-bypass-cozumu.md)
{% endcontent-ref %}

***

3- Lab: <https://portswigger.net/web-security/sql-injection/union-attacks/lab-determine-number-of-columns>

{% content-ref url="/pages/lJISv5QllCF6pvu2KxDK" %}
[SQL injection UNION attack, determining the number of columns returned by the query Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-union-attack-determining-the-number-of-columns-returned-by-the-query-cozumu.md)
{% endcontent-ref %}

***

4- Lab: <https://portswigger.net/web-security/sql-injection/union-attacks/lab-find-column-containing-text>

Çözümü:

{% content-ref url="/pages/s5vT3fadEQZxqB6Io05a" %}
[SQL injection UNION attack, finding a column containing text Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-union-attack-finding-a-column-containing-text-cozumu.md)
{% endcontent-ref %}

***

5- Lab: <https://portswigger.net/web-security/sql-injection/examining-the-database/lab-querying-database-version-oracle>

{% content-ref url="/pages/K0Op682hTrNclrfdIhiA" %}
[SQL injection attack, querying the database type and version on Oracle Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-attack-querying-the-database-type-and-version-on-oracle-cozumu.md)
{% endcontent-ref %}

***

6- Lab: <https://portswigger.net/web-security/sql-injection/examining-the-database/lab-querying-database-version-mysql-microsoft>

{% content-ref url="/pages/10RHH5iIgkrZBczr386a" %}
[SQL injection attack, querying the database type and version on MySQL and Microsoft Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-attack-querying-the-database-type-and-version-on-mysql-and-microsoft-cozumu.md)
{% endcontent-ref %}

***

7- Lab: <https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables>

{% content-ref url="/pages/B7DJYAmsb953Qcm2QSNg" %}
[SQL injection UNION attack, retrieving data from other tables Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-union-attack-retrieving-data-from-other-tables-cozumu.md)
{% endcontent-ref %}

***

8- Lab: <https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-multiple-values-in-single-column>

{% content-ref url="/pages/j9Euv6wXFEThdNpaZvjs" %}
[SQL injection UNION attack, retrieving multiple values in a single column Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-union-attack-retrieving-multiple-values-in-a-single-column-cozumu.md)
{% endcontent-ref %}

***

9- Lab: <https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-non-oracle>

{% content-ref url="/pages/L2DbXQ6cq3eCVoPkqUXy" %}
[SQL injection attack, listing the database contents on non-Oracle databases Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-attack-listing-the-database-contents-on-non-oracle-databases-cozumu.md)
{% endcontent-ref %}

***

10- Lab: <https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-oracle>

{% content-ref url="/pages/b25RitpMmHd9r7NdiA4h" %}
[SQL injection attack, listing the database contents on Oracle Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/sql-injection-attack-listing-the-database-contents-on-oracle-cozumu.md)
{% endcontent-ref %}

***

11. Lab (Özel Kapanış): Görünür Hata Tabanlı Veri Sızdırma:

<https://portswigger.net/web-security/sql-injection/blind/lab-sql-injection-visible-error-based>

{% content-ref url="/pages/gwNsgGdZlm32Rqw3k8Sz" %}
[Visible error-based SQL injection Çözümü](/sqli-egitimi/sql-injection-sqli-egitim-modulu-ve-portswigger/in-band-sql-injection/visible-error-based-sql-injection-cozumu.md)
{% endcontent-ref %}
