원격 프로퍼티 주입

Remote Property Injection

설명

신뢰할 수 없는 입력으로 객체 프로퍼티를 선택하면 애플리케이션 상태나 보안 관련 옵션을 덮어쓸 수 있습니다. 프로토타입에 미치는 영향은 대상 객체와 대입 값에 따라 달라집니다.

잠재적 영향

  • 권한이나 동작을 결정하는 필드가 덮어써지면 잘못된 보안 판단이나 데이터 처리가 발생할 수 있습니다.
  • 대상 객체와 값에 따라 프로토타입 동작이 변경되거나 기존 메서드가 덮어써질 수 있습니다.
  • 변경된 필드를 사용하는 후속 코드에서 예외나 검증 우회가 발생할 수 있습니다.

해결 방법

  • 대상 객체의 용도에 맞게 서버가 관리하는 고정 허용 목록으로 수정 가능한 프로퍼티를 제한하세요.
  • 임의의 키가 필요한 별도 키·값 저장소에는 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 공개 목록에 포함됩니다. 분류가 프로토타입 전체의 오염이나 후속 공격 성공까지 증명하는 것은 아닙니다.

참조