flawopen.com/SQLインジェクション/Javascript
番号札だけを受け取るはずの窓口に、悪意のある命令文を紛れ込ませることで、システム全体の名簿を盗み見させてしまう手口です。
ユーザー入力をそのままSQL文字列に結合すると、意図しないSQL構文が実行されます。Node.jsでは日常的に使われるテンプレートリテラルが最大の原因です。
英大手通信TalkTalk社はSQLインジェクションによる15万件以上の顧客情報漏洩で約40万ポンドの制裁金を科されました。
出典: 英国情報コミッショナー局 (ICO), 2016年。// userId comes straight from request query
async function getUser(pool, userId) {
const query = `SELECT * FROM users
WHERE id = ${userId}`;
const [rows] = await pool.query(query);
return rows[0];
}
// value is passed separately, never inlined
async function getUser(pool, userId) {
const [rows] = await pool.query(
'SELECT * FROM users WHERE id = ?',
[userId]
);
return rows[0];
}
プレースホルダーを用いることで、DBエンジンが構文木を確定させた後にパラメータ値だけを安全にバインドします。
mysql2は「?」を使用しますが、PostgreSQL用のpgは「$1, $2」を使用します。
エンコーディングの違いによるバイパスが存在するため、パラメータ化クエリのみが確実な対策です。
grep -rn "query(\`.*\${" --include="*.js" --include="*.ts" .
npx eslint --rule 'no-template-curly-in-string: error' .
p/javascript ruleset in CI to catch unparameterized database queries automatically.標準APIは安全ですが、$queryRawUnsafeや生のSQL実行メソッドでは自前でバインドする必要があります。