~/VibeHandbook
PDF Gratis

Bab 18 · 02

Injection: ketika input menjadi kode

Injection adalah bug serius tertua dan masih paling umum. Ini terjadi ketika data dari pengguna diperlakukan sebagai instruksi alih-alih data. Dua jenis yang penting untuk sebagian besar aplikasi.

injection — SQL (Structured Query Language) adalah bahasa yang digunakan aplikasi untuk meminta data dari basis data — terjadi ketika input pengguna menyusup ke dalam query basis data. Pola klasik yang rentan:

// VULNERABLE: the user's input is glued straight into the query
app.get("/user", (req, res) => {
  const name = req.query.name;
  db.query(`SELECT * FROM users WHERE name = '${name}'`);
});
// If someone passes  name = '; DROP TABLE users; --
// your query becomes a command to delete the table.

Perbaikannya adalah parameterized query (juga disebut prepared statement). Kamu mengirim query dan data secara terpisah, sehingga basis data tidak pernah salah mengira yang satu sebagai yang lain:

// SAFE: the value is passed as a parameter, never as code
app.get("/user", (req, res) => {
  const name = req.query.name;
  db.query("SELECT * FROM users WHERE name = ?", [name]);
});

Aturannya: jangan pernah membangun query dengan penggabungan string. Kalau kamu melihat backtick atau + yang merangkai SQL di sekitar sebuah variabel dalam sebuah diff, berhenti dan minta versi parameterized-nya.

Kedua jalur ini memasukkan input pengguna yang sama ke basis data, tapi hanya satu yang mencegah basis data salah mengira input itu sebagai perintah:

  user input:  '; DROP TABLE users; --
        │
        ├─────────────────────────┬───────────────────────────┐
        ▼                         ▼                            
  ✗ CONCATENATED            ✓ PARAMETERIZED                    
  "...WHERE name=             "...WHERE name = ?", [input]      
     '" + input + "'"          (query and data sent separately)
        │                         │
        ▼                         ▼
  ┌───────────────┐         ┌───────────────┐
  │   DATABASE    │         │   DATABASE    │
  │ reads input   │         │ treats input  │
  │ AS COMMANDS   │         │ as DATA only  │
  │  → table gone │         │  → safe lookup │
  └───────────────┘         └───────────────┘
       BREACH                    SAFE

XSS (cross-site scripting) adalah gagasan yang sama di dalam browser. Kalau kamu mengambil input pengguna dan menaruhnya ke halaman sebagai HTML mentah (HyperText Markup Language, kode yang memberi tahu browser apa yang harus ditampilkan), penyerang bisa menyisipkan tag <script> yang berjalan di browser pengguna lain kamu — mencuri sesi mereka, misalnya. Perbaikannya adalah escaping: render konten pengguna sebagai teks, bukan HTML. modern seperti React melakukan escape secara default, yang bagus, sampai AI menggunakan jalan pintas seperti dangerouslySetInnerHTML atau innerHTML untuk "membuatnya berfungsi." Itu melewati perlindungan tersebut. Anggap panggilan semacam itu dalam sebuah diff sebagai sesuatu yang harus dipertanyakan.

Prinsip pemersatu di balik setiap bug injection: jaga agar data dan kode tetap terpisah. Kapan pun input pengguna masuk ke sebuah query, perintah, template, atau HTML, sesuatu harus melakukan escape atau parameterize terhadapnya.

Mau versi offline?

Unduh seluruh buku sebagai PDF atau EPUB — gratis.