説明
利用者の入力をSQL文字列に直接挿入すると、攻撃者がデータベース操作を変更できる可能性があります。Knexで動的にクエリを作る場合も、入力を値として渡さずSQLに連結すると脆弱になります。
想定される影響
- データベースや利用者の機密情報が漏えいするおそれがあります。
- データを不正に変更、削除される可能性があります。
- 認証・認可用クエリへのインジェクションでアクセス制御を回避されるおそれがあります。全体の影響範囲は接続アカウントの権限に左右されます。
対処方法
- 入力をSQLに連結せず、値としてバインドしてください。
- クエリで使う入力の型、形式、長さを検証してください。
.insert()や.where()などの値をバインドする機能を使ってください。.raw()が必要なら、以下のようにSQL文字列を固定し、バインドする値を別に渡してください。
例
変更前
javascript
app.post('/user', async (req, res) => {
const result = await knex.raw(
`INSERT INTO users (name, email) VALUES ('${req.body.name}', '${req.body.email}')`
);
res.send('User added');
});
変更後
javascript
app.post('/user', async (req, res) => {
const result = await knex.raw(
'INSERT INTO users (name, email) VALUES (?, ?)',
[req.body.name, req.body.email]
);
res.send('User added');
});
変更前は利用者の名前とメールアドレスをSQLへ直接埋め込みます。変更後は2つの?にバインドし、入力をSQL構文ではなく値として扱います。形式と長さの検証、およびリクエスト元が書き込みを行えるかの確認は別途行ってください。