formkeamananxssMenengah4 mnt baca

Keamanan Form Dasar

Lindungi form dari XSS dan CSRF: htmlspecialchars, validasi whitelist, dan token CSRF.

Kenapa Form Butuh Diamankan?

Form adalah pintu masuk website-mu. Setiap input adalah kiriman dari orang asing yang bisa jadi jahat: menyuntik script, mengirim data raksasa, atau mengulang submit ribuan kali. Keamanan form dasar adalah tiga kebiasaan: jangan percaya input, bersihkan saat menampilkan, batasi yang bisa dikirim.

php
<?php
// Contoh 1: pola aman standar untuk SEMUA form
$errors = [];
$nama = trim($_POST["nama"] ?? "");

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    // 1. Validasi: tolak yang tidak memenuhi syarat
    if (strlen($nama) < 3) {
        $errors[] = "Nama minimal 3 karakter.";
    }
    if (strlen($nama) > 50) {
        $errors[] = "Nama maksimal 50 karakter.";
    }

    // 2. Kalau lolos, proses. Kalau tidak, tampilkan error.
    if ($errors === []) {
        // simpan...
        header("Location: sukses.php");
        exit;
    }
}
// 3. Tampilkan kembali dengan htmlspecialchars (XSS protection)
?>
<?php foreach ($errors as $e): ?>
    <p style="color:red"><?= htmlspecialchars($e) ?></p>
<?php endforeach; ?>
<form method="post">
    <input type="text" name="nama" maxlength="50"
           value="<?= htmlspecialchars($nama) ?>">
    <button>Kirim</button>
</form>

Perhatikan tiga lapis pertahanan: maxlength di HTML (lapisan luar, mudah dibobol), validasi panjang di PHP (lapisan inti, tidak bisa dibobol), dan htmlspecialchars saat menampilkan (mencegah script jahat jalan di browser pengunjung lain).

php
<?php
// Contoh 2: batasi request (anti spam sederhana)
session_start();
$sekarang = time();
$terakhir = $_SESSION["terakhir_kirim"] ?? 0;

if ($sekarang - $terakhir < 10) {
    die("Tunggu 10 detik sebelum mengirim lagi.");
}
$_SESSION["terakhir_kirim"] = $sekarang;
// ... proses form ...

Rate limiting sederhana ini mencegah user (atau bot) membanjiri form ribuan kali per menit. Versi serius memakai database atau cache, tapi pola session ini cukup untuk tugas sekolah dan proyek kecil.

Jebakan yang Sering Terjadi

Hanya mengandalkan validasi JavaScript. Validasi di browser mudah dimatikan (matikan JS, atau kirim via curl). JavaScript untuk kenyamanan user, PHP untuk keamanan. Selalu validasi ulang di server meski form sudah divalidasi di browser.

Menampilkan error dengan detail sistem. Pesan seperti "Query gagal: ..." membocorkan struktur databasemu ke penyerang. Ke user tampilkan pesan umum ("Terjadi kesalahan, coba lagi."), detail teknis catat ke log yang hanya bisa dibaca kamu.

Prinsip Pertahanan Berlapis

Keamanan form mengikuti prinsip defense in depth: tidak ada satu lapis yang sempurna, jadi tumpuk beberapa:

  1. HTML: required, maxlength, type yang tepat (UX + saringan kasar).
  2. PHP validasi: tolak data yang tidak memenuhi aturan (pertahanan inti).
  3. PHP sanitasi output: htmlspecialchars saat menampilkan (anti XSS).
  4. Rate limit: batasi submit per waktu (anti spam/bot).
  5. CSRF token: untuk aksi penting (anti pemalsuan request).

Setiap lapis menutup celah yang lolos dari lapis sebelumnya. Penyerang yang mematikan JavaScript lolos lapis 1 tapi tertahan lapis 2. Yang mengirim curl langsung tertahan lapis 2 dan 4. Tidak ada pertahanan tunggal yang cukup sendirian.

Catatan teknis: Atribut HTML seperti required, maxlength, dan type="email" adalah lapisan pertama yang bagus untuk UX, tapi bukan keamanan. Anggap semua yang datang dari browser sebagai "belum terverifikasi" sampai PHP memeriksanya sendiri.

Tantangan

Amankan form kritik

Ambil form kritik dari modul form-post-dasar, tambahkan: (1) htmlspecialchars di semua output, (2) token CSRF (generate di session, hidden input, verifikasi saat POST). Tes bahwa submit tanpa token ditolak.