説明
利用者の入力をSQLに直接連結すると、攻撃者がクエリの構造を変え、意図しないデータベース操作を実行できる可能性があります。クエリの用途によっては、認証の回避、情報漏えい、データの削除につながります。
想定される影響
- 不正な入力で認証用クエリを回避されるおそれがあります。
- 権限のない利用者に機密情報を閲覧される可能性があります。
- データベースのレコードを不正に追加、変更、削除されるおそれがあります。
対処方法
- 値をSQLに連結せず、クエリパラメーターとしてバインドしてください。
- 数値やメールアドレスなど、想定する型と形式に従って入力を検証してください。
- ORMやクエリビルダーでも値をバインドするAPIを使ってください。テーブル名や列名は値パラメーターで表せないため、固定の許可リストから選んでください。
例
接続とクエリの部分だけを抜粋しています。CommonJSでは非同期関数内に置き、エラー処理と接続の後処理を追加してください。
変更前
javascript
const { Client } = require('pg')
const client = new Client()
await client.connect()
let query = 'SELECT * FROM users WHERE id = ' + userInput;
const res = await client.query(query);
await client.end();
変更後
javascript
const { Client } = require('pg')
const client = new Client()
await client.connect()
const res = await client.query('SELECT * FROM users WHERE id = $1', [userInput]);
await client.end();
変更前はuserInputをSQLに連結するため、クエリを変更される可能性があります。変更後は$1に入力をバインドし、SQL構文ではなく値として扱います。