説明
ユーザー入力で選択したオブジェクトのプロパティを関数として呼び出すと、存在しないメソッドやプロトタイプのメソッドを呼び出し、実行時例外が発生する場合があります。リクエスト処理中の例外を捕捉しなければ、サービスの可用性に影響するおそれがあります。また、公開する意図のないメソッドが実行される可能性もあります。
想定される影響
- 存在しない関数の呼び出しによってリクエストハンドラーが例外を出し、可用性が低下する場合があります。
- 攻撃者が許可されていないアクション名を渡し、内部メソッドの呼び出しを誘導するおそれがあります。
- プロトタイプチェーン上のプロパティを呼び出すと、意図しない動作につながる可能性があります。
対処方法
- ユーザー入力でメソッドを直接選択せず、明示的な
switchや許可リストを使用してください。 - 動的な参照が必要な場合は、
Object.hasOwnまたはhasOwnPropertyでオブジェクト自身のプロパティか確認し、typeof value === "function"も検証してください。 - 許可していないアクションは既定で拒否してください。
例
変更前
javascript
const actions = {
play(data) {
return data;
},
};
app.get("/perform/:action", (req, res) => {
res.send(actions[req.params.action](req.query.payload));
});
変更後
javascript
const actions = Object.freeze({
play(data) {
return data;
},
});
app.get("/perform/:action", (req, res) => {
const action = actions[req.params.action];
if (!Object.hasOwn(actions, req.params.action) || typeof action !== "function") {
return res.status(400).send("Unsupported action");
}
return res.send(action(req.query.payload));
});
説明:
- 変更前: 入力をそのままオブジェクトのキーとして関数を呼び出すため、不正なキーで例外が発生したり、意図しないプロパティが選択されたりする場合があります。
- 変更後: 許可したオブジェクト自身のプロパティであり、値が関数であることを確認してから呼び出します。