Soal 1Mengapa memvalidasi di server juga, padahal nilai formnya sudah diperiksa di layar?
Hal yang Perlu Diwaspadai soal Keamanan — Jangan Percayai Input, Lindungi Rahasia
Artikel ini adalah bagian dari kursus Dasar-Dasar Teknologi Informasi, yang membangun dari nol pengetahuan TI praktis yang minimal kamu butuhkan untuk memprogram dan melakukan vibe coding.
Ada dua hal mendasar: tidak memercayai input pengguna, dan melindungi informasi rahasia. Diagram menunjukkan bagaimana SQL injection dan XSS terjadi.
Artikel ini membahas dua dari hal yang perlu diwaspadai soal keamanan.
Yang pertama adalah tidak memakai teks yang diketik pengguna apa adanya, dan yang kedua adalah tidak menaruh nilai rahasia di tempat yang bisa dibaca lebih banyak orang.
- Alasan validasi input dilakukan di server
- SQL injection, yang terjadi ketika input disambung ke sebuah perintah, dan placeholder
- XSS, yang dicegah dengan escaping tepat sebelum ditampilkan ke layar
- Tempat kamu boleh menyimpan informasi rahasia seperti API key dan password
Begitu salah satunya terjadi setelah kamu mempublikasikan aplikasinya, keadaannya tidak bisa dikembalikan, dan data yang telanjur terbaca tidak bisa ditarik kembali.
"Tidak ada validasi input" berarti memakai nilai yang masuk apa adanya
Validasi input adalah memastikan nilai yang masuk sesuai format, panjang, dan rentang yang kamu harapkan sebelum kamu memakainya.
Kamu menetapkan syarat untuk setiap kolom: nama sampai 50 karakter, penilaian bintang dari 1 sampai 5.
| Nilai yang masuk | Syarat yang ditetapkan sebelumnya | Yang dilakukan server |
|---|---|---|
| Kolom nama: Budi | Sampai 50 karakter → sesuai | Lanjut disimpan |
| Penilaian bintang: 7 | Angka 1 sampai 5 → tidak sesuai | Ditolak tanpa disimpan |
| Isi: dibiarkan kosong | Satu karakter atau lebih → tidak sesuai | Ditolak tanpa disimpan |
Hanya baris pertama yang memenuhi syarat dan lanjut disimpan; dua baris lainnya tidak disimpan, dan server mengembalikan bagian mana yang tidak sesuai.
Pemeriksaan di layar dijalankan oleh JavaScript (program yang berjalan di dalam browser) yang dikirim ke perangkat pengguna.
Pengguna bisa mematikannya, dan mereka juga bisa mengirim data langsung ke server tanpa memakai browser.
Pemeriksaan di layar ada untuk mendorong pengguna memperbaiki isiannya, dan hanya validasi di server yang menentukan boleh atau tidaknya sebuah nilai dipakai.
Kalau kamu menyimpan tanpa validasi, nilai yang tidak memenuhi syarat tetap ada di database apa adanya.
Penilaian bintang di luar 1 sampai 5 mengacaukan rata-rata dan urutan, dan nilai yang tidak terbaca sebagai angka menghentikan proses penghitungannya.
Memperbaiki nilai yang sudah telanjur masuk berarti memeriksa sisa datanya satu per satu.
Periksa nilainya di server sebelum kamu memakainya
Validasi input adalah melihat apakah nilai yang tiba memenuhi syarat yang kamu tetapkan, sebelum kamu memakainya.
Pemeriksaan di layar ada supaya pengguna memperbaiki isiannya saat itu juga dan bisa dimatikan sebelum dikirim, jadi kamu memeriksa hal yang sama sekali lagi di server.
Kalau input disambung ke sebuah perintah, teks yang diketik ikut berjalan sebagai perintah
Ketika mencari ulasan tersimpan berdasarkan nama, server merangkai sebuah perintah dalam SQL (Structured Query Language. Bahasa yang menyampaikan perintah ke database).
Ketika teks input disambung ke string itu, seluruhnya diteruskan sebagai satu string.
- SELECT * FROM reviews WHERE name =
- Perintah untuk mengambil baris yang name-nya cocok dari tabel reviews
- Bentuk ini sudah ditulis di dalam kode sebelumnya
- Budi — nama biasa
- ' OR '1'='1 — teks yang mengandung simbol
- Apa yang diketik pengguna masuk ke posisi ini apa adanya
Setelah diteruskan, bagian yang ditulis developer dan bagian dari kolom nama menjadi bagian dari satu string yang sama.
Database membaca satu string yang diterimanya sebagai perintah, seluruhnya sekaligus.
| Teks yang dimasukkan di kolom nama | Perintah yang terbentuk dari sambungan itu | Yang dikembalikan database |
|---|---|---|
| Budi | name = 'Budi' | Hanya ulasan milik Budi |
| Budi' | name = 'Budi'' | Perintahnya rusak dan menghasilkan error |
| ' OR '1'='1 | name = '' OR '1'='1' | Semua ulasan |
Teks input yang dieksekusi sebagai perintah alih-alih sebagai nilai disebut injection, dan yang terjadi di database disebut SQL injection.
Cara penulisan yang mencegahnya adalah placeholder (cara penulisan yang menandai hanya posisi nilai di dalam perintah dengan sebuah simbol, lalu meneruskan nilainya secara terpisah).
Ketika diteruskan terpisah, database tidak membaca nilainya sebagai perintah; database mencari teks itu sebagai nama dan berakhir dengan 0 baris.
Validasi memeriksa format sebuah nilai, sedangkan placeholder memastikan nilainya diperlakukan sebagai nilai apa pun formatnya.
Keduanya punya tugas yang berbeda, jadi kamu melakukan keduanya.
Jangan menyambung perintah dan teks input menjadi satu string
Ketika teks input disambung ke sebuah perintah, simbol yang diketik pun terbaca sebagai bagian dari perintah itu.
Meneruskan perintah dan nilai secara terpisah membuat teks yang mengandung simbol diperlakukan sekadar sebagai nama, jadi kamu menyiapkan keduanya: validasi yang memeriksa format, dan cara penulisan yang memperlakukan nilai sebagai nilai apa pun formatnya.
Kalau tidak diubah tepat sebelum ditampilkan, sebuah kiriman berjalan di browser pengguna lain
Hal yang sama terjadi di tempat sebuah kiriman ditampilkan ke layar.
Teks input yang dieksekusi sebagai JavaScript di browser pengguna lain disebut XSS (Cross-Site Scripting).
Pada keduanya, input terbaca sebagai perintah; hanya pihak yang membacanya yang berbeda.
Penanganan di sisi tampilan adalah escaping (mengubah karakter yang punya arti khusus menjadi bentuk yang tampil sebagai karakter biasa).
Pembedanya bukan saat penyimpanan, melainkan tepat sebelum teksnya muncul di layar.
| Karakter yang punya arti khusus di HTML | Cara penulisan setelah diganti | Karakter yang terlihat di layar |
|---|---|---|
| < | < | < |
| > | > | > |
| & | & | & |
| " | " | " |
| ' | ' | ' |
Kalau diganti tepat sebelum tampil, kiriman tetap jadi teks biasa
Kalau kamu menampilkan sebuah kiriman apa adanya ke layar, apa pun yang bercampur di dalamnya akan berjalan di browser pengguna lain.
Yang menghentikannya adalah penggantian yang dilakukan tepat sebelum ditampilkan, dan karena yang diganti hanya simbolnya, teks yang dilihat pembaca tidak berubah.
Hentikan nilai rahasia sebelum lebih banyak orang bisa membacanya
Poin yang lain adalah tempat informasi rahasia disimpan.
Yang kamu lihat di sini adalah berapa banyak orang yang bisa membaca tempat kamu menaruhnya.
- .env — nilai API key dan password
- File konfigurasi yang hanya dipakai di komputer kamu
- server.js — kode yang berjalan di server
- .gitignore — daftar file yang tidak dicatat
- .env.example — contoh yang hanya berisi namanya
- index.html — layar ulasan
- script.js — kode yang berjalan di halaman
Semakin ke dalam bingkainya, semakin banyak orang yang bisa membacanya: siapa pun bisa membaca script.js, dan begitu server.js dicatat di Git, semua orang yang kamu beri kodenya bisa membacanya.
Menuliskan .env di .gitignore (file yang memuat daftar nama file yang tidak boleh dicatat Git) membuat nilainya tidak masuk ke riwayat, tetapi
begitu nilainya sudah pernah dicatat, nilai itu tetap ada di riwayat lama, jadi kamu membuat ulang nilai itu sendiri.
Nilai yang sudah masuk ke repository publik bisa dibaca siapa pun di dunia.
- script.js — kode yang dikirim ke browser
- Bagian akhir URL yang kamu panggil
- Pesan error yang muncul di layar
- server.js — kode yang dicatat di Git
- .env yang pernah dicatat — tetap ada di riwayat
- Environment variable di server — API key dan password ditaruh di sini
Satu-satunya yang ada di lingkaran paling dalam adalah environment variable di server.
Kamu tidak menuliskannya di tempat-tempat pada dua lingkaran luar, maupun di log (catatan aktivitas yang disimpan server), yang kadang dibawa keluar.
my-app yang berjalan di dalam kotak sebelah kanan memuat nilainya dari environment variable.
Nilai itu tidak pernah masuk ke dua kotak di sebelah kiri, jadi jumlah orang yang bisa membacanya tidak bertambah.
Tempat menyimpannya ditentukan oleh berapa banyak orang yang bisa membacanya
Tempat kamu boleh menyimpan nilai rahasia ditentukan oleh berapa banyak orang yang bisa membaca tempat itu.
Siapa pun bisa membaca file yang dikirim ke browser, dan file yang dicatat di Git sampai ke semua orang yang kamu beri kodenya, jadi kamu tidak menulisnya di keduanya dan menaruhnya di environment variable pada server.
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Apa yang sebenarnya dilakukan cara penulisan placeholder, yang mencegah SQL injection?
Soal 3Manakah tempat yang benar untuk menyimpan API key sebuah layanan eksternal?