Keamanan aplikasi web bukan lagi opsional, terutama untuk website bisnis. Dua jenis serangan yang paling sering menyebabkan kebocoran data dan kerugian finansial adalah:
- SQL Injection
- Cross-Site Scripting (XSS)
Ironisnya, kedua serangan ini sudah dikenal lebih dari 20 tahun, tetapi masih menjadi penyebab utama insiden keamanan hingga hari ini — termasuk di aplikasi PHP modern.
Masalahnya bukan karena PHP tidak aman, melainkan karena:
- Implementasi yang salah
- Kurangnya pemahaman konteks input & output
- Developer terlalu percaya data dari user
Artikel ini membahas cara mencegah SQL Injection dan XSS di PHP secara menyeluruh, dari level kode hingga praktik production.
Contents
- 1 1. Memahami Ancaman: SQL Injection & XSS
- 2 2. SQL Injection di PHP: Contoh Nyata & Cara Mencegahnya
- 3 3. Solusi Utama: Prepared Statement (WAJIB)
- 4 4. Kesalahan Fatal Terkait SQL Injection
- 5 5. Validasi & Sanitasi Input (Lapisan Tambahan)
- 6 6. XSS di PHP: Contoh Nyata & Dampaknya
- 7 7. Solusi Utama XSS: Output Escaping
- 8 8. Jenis XSS & Cara Menanganinya
- 9 9. Content Security Policy (CSP): Lapisan Proteksi Tambahan
- 10 10. Amankan Session & Cookie (XSS Related)
- 11 11. Gunakan ORM & Framework dengan Benar
- 12 12. Amankan API & AJAX Endpoint
- 13 13. Logging & Monitoring Serangan
- 14 14. Studi Kasus Nyata
- 15 15. Checklist PHP Security: SQL Injection & XSS
- 16 16. Kesalahan Umum Developer PHP
- 17 Kesimpulan
- 18 Related Posts
1. Memahami Ancaman: SQL Injection & XSS
1.1 Apa Itu SQL Injection?
SQL Injection terjadi ketika input user:
- Langsung dimasukkan ke query SQL
- Tanpa validasi & parameter binding
Dampak:
- Bypass login
- Dump database
- Hapus data
- Ambil data sensitif
1.2 Apa Itu XSS (Cross-Site Scripting)?
XSS terjadi ketika:
- Data user ditampilkan kembali ke browser
- Tanpa escaping yang benar
Dampak:
- Session hijacking
- Deface website
- Pencurian data user
- Malware injection
2. SQL Injection di PHP: Contoh Nyata & Cara Mencegahnya
2.1 Contoh Kode Rentan SQL Injection (SALAH)
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users
WHERE username = '$username'
AND password = '$password'";
$result = mysqli_query($conn, $query);
Jika user input:
' OR 1=1 --
👉 Login langsung tembus.
3. Solusi Utama: Prepared Statement (WAJIB)
3.1 Contoh Aman dengan PDO
$stmt = $pdo->prepare(
"SELECT * FROM users
WHERE username = :username
AND password = :password"
);
$stmt->execute([
':username' => $username,
':password' => $password
]);
📌 Prepared statement memisahkan data dari query, sehingga input tidak pernah dieksekusi sebagai SQL.
3.2 Prepared Statement dengan MySQLi
$stmt = $conn->prepare(
"SELECT * FROM users WHERE username = ?"
);
$stmt->bind_param("s", $username);
$stmt->execute();
4. Kesalahan Fatal Terkait SQL Injection
❌ Escape manual (addslashes)
❌ Filter input tapi tetap concat string
❌ Mengandalkan frontend validation
❌ Percaya data dari internal API
📌 Satu-satunya solusi benar adalah parameter binding.
5. Validasi & Sanitasi Input (Lapisan Tambahan)
Prepared statement melindungi query, tapi validasi tetap penting.
Contoh Validasi
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new Exception("Email tidak valid");
}
📌 Validasi ≠ keamanan SQL
📌 Validasi = kualitas data
6. XSS di PHP: Contoh Nyata & Dampaknya
6.1 Contoh Kode Rentan XSS
echo $_GET['name'];
Jika user akses:
<script>alert('Hacked')</script>
👉 Script dieksekusi di browser.
7. Solusi Utama XSS: Output Escaping
7.1 Escape HTML dengan Benar
echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
📌 Escape saat OUTPUT, bukan saat input.
7.2 Contoh di Template (Blade / PHP Native)
<?= htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8') ?>
Laravel:
{{ $userInput }}
8. Jenis XSS & Cara Menanganinya
8.1 Stored XSS
- Data disimpan di database
- Ditampilkan ke user lain
➡ Solusi: Escape output di semua tempat render
8.2 Reflected XSS
- Data langsung dari URL
➡ Solusi: Escape output
8.3 DOM-based XSS
- Terjadi di JavaScript
➡ Solusi:
- Hindari
innerHTML - Gunakan
textContent
9. Content Security Policy (CSP): Lapisan Proteksi Tambahan
Tambahkan header:
Content-Security-Policy: default-src 'self'
📌 CSP tidak menggantikan escaping, tapi membatasi dampak XSS.
session_set_cookie_params([
'httponly' => true,
'secure' => true
]);
👉 JavaScript tidak bisa mencuri session.
11. Gunakan ORM & Framework dengan Benar
Laravel, Symfony:
- Default aman dari SQL Injection
- Default auto-escape output
📌 Masalah muncul saat developer mem-bypass fitur keamanan.
12. Amankan API & AJAX Endpoint
❌ Jangan percaya JSON input
❌ Jangan expose error detail
❌ Validasi payload
📌 API juga target SQL Injection & XSS.
13. Logging & Monitoring Serangan
- Log query error
- Monitor payload aneh
- Alert percobaan injection
📌 Serangan sering dicoba berulang kali.
14. Studi Kasus Nyata
Website Bisnis Lokal
Masalah:
- Data user bocor
- Deface halaman
Penyebab:
- Query concat
- Tidak escape output
Solusi:
- Prepared statement
- Output escaping global
- CSP
Hasil:
- Tidak ada insiden ulang
- Audit keamanan lolos
15. Checklist PHP Security: SQL Injection & XSS
SQL Injection
✅ Prepared statement
✅ No string concat
✅ DB user privilege minimal
XSS
✅ Escape output
✅ CSP header
✅ HttpOnly cookie
✅ Hindari inline JS
16. Kesalahan Umum Developer PHP
❌ “Input sudah saya filter”
❌ “User internal aman”
❌ “Framework sudah handle semuanya”
📌 Keamanan bukan asumsi, tapi disiplin.
Kesimpulan
PHP aman dari SQL Injection & XSS jika digunakan dengan benar.
Masalah keamanan bukan soal bahasa pemrograman, tapi:
- Cara menulis kode
- Konsistensi
- Awareness developer
Website yang aman bukan yang tidak pernah diserang, tapi yang tidak pernah berhasil ditembus.
Dengan menerapkan praktik di atas, Anda:
- Melindungi data user
- Menjaga reputasi bisnis
- Menghindari kerugian besar