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 masukSyarat yang ditetapkan sebelumnyaYang dilakukan server
Kolom nama: BudiSampai 50 karakter → sesuaiLanjut disimpan
Penilaian bintang: 7Angka 1 sampai 5 → tidak sesuaiDitolak tanpa disimpan
Isi: dibiarkan kosongSatu karakter atau lebih → tidak sesuaiDitolak 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.

Angka 7 yang sama menempuh salah satu dari dua jalur, tergantung cara pengirimannya
Kirim 7 sebagaipenilaian bintangKirim langsungdari formMatikan pemeriksaanlalu kirimDihentikan olehpemeriksaanSampai ke servertanpa pemeriksaanDitolak olehvalidasi server
Satu nilai di sebelah kiri menempuh jalur atas atau bawah tergantung cara pengirimannya. Jalur bawah tidak melewati pemeriksaan di layar, jadi tanpa validasi di server nilainya tersimpan apa adanya.

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.

Isi dari satu string yang diteruskan ke database
Satu string yang diterima database
Bagian yang ditulis developer
  • SELECT * FROM reviews WHERE name =
  • Perintah untuk mengambil baris yang name-nya cocok dari tabel reviews
  • Bentuk ini sudah ditulis di dalam kode sebelumnya
Bagian yang datang dari kolom nama
  • Budi — nama biasa
  • ' OR '1'='1 — teks yang mengandung simbol
  • Apa yang diketik pengguna masuk ke posisi ini apa adanya
Bingkai terluar adalah satu string yang diteruskan dari server ke database. Setelah diteruskan, dua bagian di dalamnya tidak bisa dibedakan lagi.

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 namaPerintah yang terbentuk dari sambungan ituYang dikembalikan database
Budiname = 'Budi'Hanya ulasan milik Budi
Budi'name = 'Budi''Perintahnya rusak dan menghasilkan error
' OR '1'='1name = '' 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).

Input yang sama terpecah menjadi dua, tergantung cara penulisan di server
Di kolom nama:' OR '1'='1Disambung keperintahnyaPerintah dan nilaiditeruskan terpisahMembaca satu stringsebagai perintahHanya mencari nilaiitu sebagai namaSemua ulasandikembalikanHasilnya 0 baris
Satu input di sebelah kiri menempuh jalur atas atau bawah tergantung cara penulisannya. Ketika perintah dan nilai diteruskan terpisah, teks yang mengandung simbol pun diperlakukan sebagai nama.

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).

Input yang sama mendapat dua nama, tergantung ke mana ia bercampur
Teks yang diketikpenggunaBercampur keperintah SQLDatabase membacasebagai perintahTeruskan perintahdan nilai terpisahBercampur keHTML halamanBrowser penggunalain membacanyaEscaping tepatsebelum tampil
Di sebelah kiri adalah teks yang diketik pengguna. Jalur atas adalah ketika teks itu bercampur ke perintah SQL, jalur bawah ketika bercampur ke HTML halaman. Yang membacanya berbeda, jadi penanganannya pun berbeda.

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 HTMLCara penulisan setelah digantiKarakter yang terlihat di layar
<&lt;<
>&gt;>
&&amp;&
"&quot;"
'&#x27;'

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.

Sejauh mana file my-app menyebar
Folder kerja di komputer kamu
Tidak dicatat di Git (hanya tinggal di komputer kamu)
  • .env — nilai API key dan password
  • File konfigurasi yang hanya dipakai di komputer kamu
Dicatat di Git (sampai ke semua orang yang kamu beri kodenya)
  • server.js — kode yang berjalan di server
  • .gitignore — daftar file yang tidak dicatat
  • .env.example — contoh yang hanya berisi namanya
Dikirim ke browser (bisa dibaca semua orang yang membuka URL-nya)
  • index.html — layar ulasan
  • script.js — kode yang berjalan di halaman
Bingkai terluar adalah folder kerja di komputer kamu. Semakin ke dalam letak bingkai sebuah file, semakin banyak orang yang bisa membacanya, jadi kamu tidak menulis nilai rahasia di bingkai bagian dalam.

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.

Sejauh mana file yang dicatat di Git menyebar di GitHub
Catat hanyakodenyaRepository publikdi GitHubSiapa pun di duniabisa membacanya.env ikuttercatatSeluruh filetinggal di riwayatTetap terbacadi riwayatTulis di.gitignoreTidak pernahmasuk riwayatHanya tinggal dikomputer kamu
Baris atas adalah kode yang ditaruh di repository publik, baris tengah adalah ketika .env ikut tercatat, dan baris bawah adalah ketika .env ditulis di .gitignore. Dari kiri ke kanan, tempat menaruhnya menentukan siapa yang bisa membacanya.

Nilai yang sudah masuk ke repository publik bisa dibaca siapa pun di dunia.

Tempat API key disimpan, dan lingkaran orang yang bisa membacanya
Bisa dibaca semua orang yang membuka URL-nya
  • script.js — kode yang dikirim ke browser
  • Bagian akhir URL yang kamu panggil
  • Pesan error yang muncul di layar
Bisa dibaca semua orang yang kamu beri kodenya
  • server.js — kode yang dicatat di Git
  • .env yang pernah dicatat — tetap ada di riwayat
Hanya bisa dibaca orang yang bisa mengoperasikan server
  • Environment variable di server — API key dan password ditaruh di sini
Semakin ke luar lingkarannya, semakin banyak orang yang bisa membacanya. Satu-satunya tempat kamu boleh menaruh nilainya adalah yang ada di lingkaran paling dalam.

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.

QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Mengapa memvalidasi di server juga, padahal nilai formnya sudah diperiksa di layar?

Soal 2Apa yang sebenarnya dilakukan cara penulisan placeholder, yang mencegah SQL injection?

Soal 3Manakah tempat yang benar untuk menyimpan API key sebuah layanan eksternal?