Keamanan: User, Hak Akses (GRANT), dan Menangkal SQL Injection
Membuat user MySQL dengan hak seminimal mungkin memakai CREATE USER, GRANT, REVOKE, memahami prinsip least privilege, SQL injection, prepared statement, dan penyimpanan password.
Jangan pakai root untuk aplikasimu!
Saat memasang MySQL, kamu mendapat akun root yang boleh melakukan apa saja, termasuk menghapus semua database. Banyak pemula menaruh root di file konfigurasi aplikasi web. Jika aplikasi itu diretas, peretas ikut menjadi dewa di databasemu.
Prinsip yang harus dipegang: Least Privilege, beri setiap akun hak paling minimal yang dibutuhkan untuk tugasnya.
Membuat user dan memberi hak
-- 1) buat user (akun = nama + dari mana ia boleh terhubung)
CREATE USER 'kasir'@'localhost' IDENTIFIED BY 'Rahasia#2024';
-- 2) beri hak secukupnya
GRANT SELECT ON tokoku.produk TO 'kasir'@'localhost';
GRANT SELECT, INSERT ON tokoku.pesanan TO 'kasir'@'localhost';
-- 3) lihat hasilnya
SHOW GRANTS FOR 'kasir'@'localhost';
-- mencabut hak
REVOKE INSERT ON tokoku.pesanan FROM 'kasir'@'localhost';
-- menghapus user
DROP USER 'kasir'@'localhost';
'kasir'@'localhost'berarti userkasirhanya boleh terhubung dari server itu sendiri.'kasir'@'%'berarti dari mana saja (hati-hati!).'kasir'@'192.168.1.%'membatasi ke jaringan tertentu.- Format hak:
GRANT jenis_hak ON database.tabel TO user.tokoku.*= semua tabel di database;*.*= seluruh server (hindari!). - Hak yang umum:
SELECT,INSERT,UPDATE,DELETE,CREATE,ALTER,DROP,EXECUTE.ALL PRIVILEGES= semuanya. WITH GRANT OPTIONmembolehkan user itu membagikan haknya: jarang diperlukan.
Contoh pembagian peran
| Akun | Hak yang wajar |
|---|---|
| Aplikasi web | SELECT, INSERT, UPDATE, DELETE pada database aplikasinya saja |
| Laporan / BI | SELECT saja (read-only) |
| Migrasi / deploy | CREATE, ALTER, DROP, INDEX (dipakai sementara saat deploy) |
| Admin database | ALL, dipegang segelintir orang, tidak dipakai harian |
Catatan simulator: perintah akun dan hak akses diterima dan dicatat sebagai simulasi, tetapi tidak benar-benar membatasi apa pun di dalam latihan. Penilai memeriksa penulisan perintahmu (apakah memenuhi prinsip least privilege).
SQL Injection: serangan paling terkenal
Misalkan aplikasi membuat query dengan menempelkan input pengguna mentah-mentah:
$sql = "SELECT * FROM users WHERE email = '" . $_POST['email'] . "' AND password = '" . $_POST['pass'] . "'";
Penyerang mengetik di kolom email: ' OR '1'='1' -- . Query berubah menjadi:
SELECT * FROM users WHERE email = '' OR '1'='1' -- ' AND password = '...'
'1'='1' selalu benar, dan -- mengomentari sisanya. Penyerang masuk tanpa password. Variasi lebih ganas: '; DROP TABLE users; --.
Pertahanan: prepared statement
Pisahkan perintah dari data. Data dikirim terpisah sehingga tidak pernah dianggap sebagai SQL:
// PHP (PDO)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND password = ?');
$stmt->execute([$email, $pass]);
// Node.js (mysql2)
const [rows] = await conn.execute('SELECT * FROM users WHERE email = ?', [email]);
// Laravel
DB::select('SELECT * FROM users WHERE email = ?', [$email]); // atau Eloquent / Query Builder
Aturan baja: jangan pernah menyambung string SQL dengan input pengguna. Gunakan prepared statement / query builder / ORM. Nama tabel dan kolom tidak bisa di-bind sebagai parameter, jadi untuk itu cocokkan dengan daftar putih (whitelist) yang kamu tentukan sendiri.
Kebiasaan keamanan lain
- Password pengguna: jangan simpan polos. Simpan hash (bcrypt/argon2 dari bahasa pemrogramanmu), bukan
MD5. - Kata sandi database panjang & acak; simpan di
.env, bukan di Git. - Jangan buka port 3306 ke internet; batasi dengan firewall atau jaringan privat. Jalankan
mysql_secure_installationsetelah memasang. - Gunakan koneksi terenkripsi (TLS) bila aplikasi dan database berada di server berbeda.
- Rutin backup dan uji restore (bab berikutnya), serta aktifkan log untuk audit.