> 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/second-order-sql-injection.md).

# Second-Order SQL Injection

Bu SQL Injection tipini anlamak başlarda zor gibi görünebilir ama mantığı oldukça basittir. Buna kısaca Stored (Saklı) SQLi da denir. Olayın mantığı tam olarak şudur: Zararlı SQL komutumuzu alır, hedef sitenin veri girmemize izin verdiği masum bir yerinden veritabanına enjekte ederiz.

İlk adımda, veriyi sisteme girerken hiçbir zafiyet olmayabilir. Yazılımcı işini iyi yapmış ve veriyi güvenli bir şekilde (örneğin Prepared Statements kullanarak) veritabanına almış olabilir. Ancak sorun şu ki; bu komutun içindeki tehlikeli olabilecek SQL kelimelerini (OR, UPDATE vb.) veya noktalama işaretlerini (', ; vb.) temizlemeden (sanitize etmeden) olduğu gibi veritabanına kaydeder. Yani aslında biz veritabanına SQL Injection’ı yerleştirmiş oluruz ve sistem bunu sadece zararsız bir metin sanıp saklar.

İkinci kısımda ise asıl sorunu oluştururuz. Sistem, bu enjekte ettiğimiz veriyi daha sonra başka bir sayfada, kendi veritabanının içinden çağırıp yeni bir SQL sorgusunda kullanmak ister. İşte bu noktada yazılımcı "Zaten kendi veritabanımdan geliyor, kesin güvenlidir" yanılgısına düşer ve veriyi SQL sorgusuna koyarken ekstra bir kontrolden geçirmez. Veri o sorgunun içine girdiği an enjekte ettiğimiz SQL sorgusu çalışır; ilk adımda usulca kaydettiğimiz kod, **orijinal** SQL sorgusunu bozarak kendi istediğimiz zararlı komutu çalıştırır.

Biraz karmaşık gelmiş olabilir ama ufak bir örnekle çok daha rahat anlayacağınızı düşünüyorum:

#### Örnek Senaryo: Admin Olmak

Diyelim ki hedefimizde kullanıcıların kayıt olabildiği ve şifrelerini değiştirebildiği bir forum sitesi var. Bu sitenin en yetkili hesabı `admin` kullanıcı adını kullanıyor olsun. Amacımız bu admin hesabının şifresini değiştirip sistemi ele geçirmek.

**İlk ADIM: SQL enjeksiyonu sisteme kaydetmek (Kayıt Aşaması)** Öncelikle siteye gidip sıradan bir kullanıcı gibi kayıt oluyoruz. Ancak "Kullanıcı Adı" (username) kısmına kendi adımızı yazmak yerine şu zararlı metni giriyoruz:

`admin' --` *(Not: Sonunda bir boşluk var)*

Kayıt ol butonuna bastığımızda arka planda şu güvenli (Prepared Statement) sorgu çalışıyor:

```sql
INSERT INTO users (username, password) VALUES ('admin'' -- ', '123456');
```

Yazılımcı kayıt ekranını güvenli kodladığı için, yazdığımız o tek tırnak işareti (`'`) sistemi bozmaz. Veritabanı bunu sadece garip isimli yeni bir kullanıcı sanır ve veritabanına kaydeder. Artık sistemde adı `admin' --` olan bir hesabımız var.

Veritabanındaki görüntüsü:

> **Kullanıcı Adı:** `admin' --` | **Şifre:** `123456`

**İkinci ADIM: Enjekte edilen sorguyu çalıştırmak** Şimdi kendi açtığımız bu tuhaf isimli hesaba (`admin' --` ) giriş yapıyoruz ve "Şifremi Değiştir" sayfasına gidiyoruz. Yeni şifre olarak **Hacked123** yazıp gönderiyoruz.

İşte sql injection burada gerçekleşiyor. Yazılımcı arka planda şifre değiştirme kodunu yazarken şöyle bir mantık kurmuş: *"Kullanıcı zaten sisteme giriş yapmış, kullanıcı adını kendi veritabanımdan çekiyorum. Kendi veritabanımdan gelen veriye neden güvenmeyeyim ki? Ekstra bir filtrelemeye gerek yok."*

Yazılımcının arka planda çalıştırdığı güvensiz şifre güncelleme sorgusu şöyledir:

```sql
UPDATE users SET password = 'Yeni_Sifre' WHERE username = '$mevcut_kullanici_adi';
```

Sistem, bizim veritabanında saklanan kullanıcı adımızı(`admin' --` ) alır ve hiçbir süzgeçten geçirmeden doğrudan `$mevcut_kullanici_adi` yazan yere yapıştırır.

Böylece sorgunun son hali aşağıdaki gibi olur:

```sql
UPDATE users SET password = 'Hacked123' WHERE username = 'admin' -- ';
```

**Peki Veritabanı Bunu Nasıl Okur?**

1. Veritabanı sorguyu okumaya başlar: *"Tamam, `users` tablosuna git, şifreyi `Hacked123` yap..."*
2. Kimi bulacağına bakar: `WHERE username = 'admin'` *"Anlaşıldı, adı `admin` olan kullanıcıyı buldum."*
3. Sonra bizim koyduğumuz çift tireye (`--` ) denk gelir: *"Aha, yorum satırı işareti! Demek ki bundan sonra gelen o son tırnak işaretinin ve geri kalan her şeyin hiçbir önemi yok.”*

**Peki ne oldu?** Biz kendi hesabımızın şifresini değiştirirken, enjekte ettiğimiz kullanıcı adımız(`admin’ --`) sorguyu değiştirip SQLi’n başarıyla çalışmasını sağladı. Sistem **gerçek adminin** şifresini `Hacked123` olarak güncelledi.
