外部入力によるプロパティの不正な変更

外部入力によるプロパティの不正な変更

説明

信頼できない入力でオブジェクトのプロパティを選ばせると、アプリケーションの状態やセキュリティ関連の設定を上書きされるおそれがあります。プロトタイプへの影響は、対象のオブジェクトと代入する値によって異なります。

想定される影響

  • 権限や動作を決めるフィールドが上書きされ、セキュリティ判断やデータ処理に誤りが生じるおそれがあります。
  • 対象と値によっては、プロトタイプの動作が変わったり、既存のメソッドが上書きされたりする可能性があります。
  • 変更されたフィールドを使う後続の処理で、例外や検証の回避が生じる場合があります。

対処方法

  • 対象オブジェクトの用途に合わせて、サーバーが管理する固定の許可リストで変更可能なプロパティを制限してください。
  • 任意のキーが必要な専用の保存先には Map を使い、アプリケーションの設定とは分けてください。
  • 辞書型のオブジェクトでは Object.create(null) で継承プロパティを避けられます。ただし、機密性の高いフィールドの変更を許可するものではありません。
  • キーに一貫して "$" を付けると、組み込みのプロパティ名との衝突を避けられます。読み取り時も同じ規則を適用してください。
  • 許可した各プロパティの用途に合わせて値を検証してください。文字のフィルタリングだけでは、変更可能なフィールドを制限できません。

例

変更前

javascript
const express = require("express");
const app = express();
const settings = { theme: "light", locale: "ko", administrator: false };

app.get("/settings", (req, res) => {
  const key = req.query.key;
  // 攻撃者がadministratorなどの設定も選べます。
  settings[key] = req.query.value;
  res.send("updated");
});

変更後

javascript
const express = require("express");
const app = express();
const settings = { theme: "light", locale: "ko", administrator: false };
const ALLOWED_KEYS = ["theme", "locale"];

app.get("/settings", (req, res) => {
  const key = req.query.key;
  const value = req.query.value;
  if (typeof key !== "string" || !ALLOWED_KEYS.includes(key)) {
    return res.status(400).send("invalid key");
  }
  if ((key === "theme" && value !== "light" && value !== "dark") ||
      (key === "locale" && value !== "ko" && value !== "en")) {
    return res.status(400).send("invalid value for key");
  }
  settings[key] = value;
  res.send("updated");
});

説明:

  • 変更前: 外部入力で変更するフィールドを選ぶため、想定外の設定も変更できます。この例は、共有プロトタイプ全体を書き換えるコードではありません。
  • 変更後: サーバー側の許可リストでキーを制限し、そのフィールドに適した値だけを許可します。リクエストで渡された許可リストや、後から変更されたリストを安全性の根拠にはできません。

OWASPの分類

動的に選んだオブジェクトの属性を不適切に変更する問題は、CWE-915に該当します。このCWEは、OWASP Web Top 10のA08:2025とA08:2021の公開リストに含まれます。分類だけで、プロトタイプ全体の汚染や後続の攻撃の成功が確認されたことにはなりません。

参考資料