FlawOpen

flawopen.com/SQL Injection di JavaScript/Knex.js

Apakah Knex.js aman dari SQL Injection?

Panduan referensi
Jawaban singkat

Bayangkan SQL sebagai formulir tercetak: binding menaruh masukan di kolom nilai; interpolasi string menempelkannya ke instruksi. Query builder Knex dan knex.raw(sql, bindings) memisahkan nilai, tetapi nama tabel dan kolom adalah struktur SQL yang harus dipilih dari allowlist tepercaya.

?? adalah placeholder identifier raw Knex; ia mengutip identifier, bukan mengikat nilai. Batasi pilihan dengan allowlist.
AMAN — bindings dan allowlist
const query = knex.raw(
  `SELECT * FROM users WHERE id = ${userId}`
);
TIDAK AMAN — SQL dirangkai dari masukan
// Masukan digabungkan ke teks SQL.
const allowedSortColumns = new Set(["created_at", "name"]);

const rows = await knex("users")
  .where("id", userId)
  .orderBy(
    allowedSortColumns.has(requestedSort)
      ? requestedSort
      : "created_at",
    requestedDirection === "asc" ? "asc" : "desc"
  );

// Pisahkan nilai dari sintaks SQL.
knex.raw("SELECT * FROM users WHERE id = ?", [userId]);

Cara bindings Knex melindungi nilai

Metode seperti .where(), .insert(), dan .select() memisahkan nilai dari SQL yang dibuat. Untuk raw, kirim nilai sebagai bindings: knex.raw("... = ?", [value]). ? menandai nilai dan ?? identifier. Jangan interpolasikan masukan ke string SQL.

Identifier dinamis memerlukan allowlist

Binding tidak mengizinkan kolom, tabel, urutan, operator, atau fragmen SQL pilihan pengguna. ?? mengutip identifier, tetapi tidak menentukan apakah pengguna boleh memilihnya. Petakan opsi ke allowlist tetap sebelum .orderBy(); tetapkan keyword dan operator SQL di kode.

Cara mengaudit kueri raw

Cari semua pemanggilan knex.raw() dan tinjau SQL serta bindings bersama-sama. Nilai data harus memakai bindings; identifier dinamis harus berasal dari allowlist kecil. Kueri raw tidak otomatis rentan; keamanannya ditentukan cara SQL dan masukan dibuat.

rg -n 'knex\.raw\(' -g '*.js' -g '*.ts' -g '*.mjs' -g '*.cjs' .

Pertanyaan umum

Apakah knex.raw() sendiri mencegah SQL Injection?

Tidak. Gunakan bindings untuk nilai tak tepercaya, misalnya knex.raw("... = ?", [value]). Interpolasi menjadikan nilai bagian dari sumber SQL. Tinjau setiap pemanggilan raw dan masukannya.

Bolehkah saya memakai ?? dan menerima kolom apa pun pilihan pengguna?

?? adalah placeholder identifier raw Knex; ia mengutip identifier, bukan mengikat nilai. Batasi pilihan dengan allowlist.

Referensi

Lihat juga SQL Injection (CWE-89): cara kerja dan cara mencegahnya di setiap bahasa — flawopen.com MyBatis ${} vs #{}: mencegah SQL Injection MySQLi vs PDO: prepared statement yang aman Apakah NHibernate aman dari SQL Injection? Injeksi NoSQL MongoDB: filter kueri aman Apakah format string berbahaya untuk ID numerik? Apa itu kueri terparameterisasi?