状況
ログインした会員が自分の請求書を見る API のレビュー。requireLogin はログインしているかだけを確かめる。
最も優先すべき指摘は?
app.get('/api/invoices/:id', requireLogin, async (req, res) => { const invoice = await db.get('SELECT * FROM invoices WHERE id = ?', req.params.id); res.json(invoice);});正答
- 存在しない id のときに、404 を返す処理が入っていない
- SELECT * ではなく、必要な列だけを選んで返すべき
- 請求書の持ち主か確かめておらず、id を変えれば他人の分も読める
- id は数値なので、プレースホルダではなく数値に変換して埋め込むべき
解説
requireLogin は「ログインしているか」しか見ておらず、取り出した請求書がその会員のものかを確かめていない。URL の id を 1 つずつ変えれば、他の会員の請求書が次々に読める(認可漏れ、IDOR)。WHERE に会員 ID の条件を足す(id = ? AND user_id = ?)など、サーバー側で持ち主かどうかを必ず確かめる。404 を返さないのは使い勝手の問題で、列の絞り込みは余計な情報を返さない改善だが、他人のデータが丸ごと見える問題に比べれば優先度は低い。数値に変換して埋め込むより、プレースホルダのままのほうが安全。
参考: cheatsheetseries.owasp.org
この問題を含む セキュリティ のテストを制限時間つきで解く
セキュリティクイズへ