Helmet 미들웨어 보안 기능 비활성화 (frameguard/xFrameOptions/CSP)

Insecure Security Headers (Helmet Misconfiguration)

설명

Helmet은 Express 앱에 보안 HTTP 헤더를 쉽게 설정하는 미들웨어입니다. Helmet 버전에 따라 프레임 보호 옵션은 과거 frameguard, 최신 버전의 xFrameOptions처럼 이름이 다를 수 있습니다. 이 옵션을 false로 설정하면 해당 헤더를 제공하지 않습니다. 다른 계층에서 동등한 정책을 제공하지 않으면 클릭재킹이나 스크립트 삽입에 대한 방어가 약해질 수 있습니다. CSP를 끄는 것만으로 XSS가 발생하는 것은 아닙니다.

잠재적 영향

  • 프레임 삽입 제한이 없으면 공격자가 페이지를 iframe에 넣어 사용자가 의도하지 않은 동작을 클릭하도록 유도할 수 있습니다.
  • 유효한 CSP가 없으면 스크립트 삽입 취약점이 있을 때 악성 스크립트의 로드와 실행을 제한하는 방어가 줄어듭니다.

해결 방법

  • 가능하면 app.use(helmet())의 기본 보호를 유지하세요. 애플리케이션이나 프록시가 실제로 반환하는 헤더를 확인하세요.
  • Helmet 버전에 맞는 X-Frame-Options 또는 CSP의 frame-ancestors로 프레임 삽입을 허용할 출처를 제한하세요. 두 기능의 보호 범위가 겹치므로 최종 응답의 정책을 함께 확인하세요.
  • CSP를 필요한 출처로 제한하세요. 광범위한 *, 'unsafe-inline', 'unsafe-eval' 대신 필요한 경우 nonce나 해시 기반 정책을 사용하세요.
  • 외부 프레임이나 스크립트가 필요한 페이지에만 예외를 적용하세요.

예시

변경 전

javascript
const express = require("express");
const helmet = require("helmet");
const app = express();

// 변경 전: 이 미들웨어에서 프레임 보호 헤더와 CSP를 모두 비활성화
app.use(helmet({
  xFrameOptions: false,
  contentSecurityPolicy: false,
}));

app.get("/pay", (req, res) => {
  res.send('<button id="pay">결제하기</button>');
});

app.listen(3000);

변경 후

javascript
const express = require("express");
const helmet = require("helmet");
const app = express();

// 안전: Helmet 활성화 + 엄격한 CSP와 프레임 보호 설정
app.use(
  helmet({
    // Helmet 구버전에서는 frameguard: { action: "sameorigin" } 사용
    xFrameOptions: { action: "sameorigin" },
    contentSecurityPolicy: {
      useDefaults: true,
      directives: {
        "default-src": ["'self'"],
        "script-src": ["'self'"], // inline/외부 임의 스크립트 금지
        "object-src": ["'none'"],
        "frame-ancestors": ["'self'"], // 임베드 허용 출처 제한
      },
    },
  })
);

app.get("/pay", (req, res) => {
  res.send('<button id="pay">결제하기</button>');
});

app.listen(3000);

설명:

  • 변경 전: 하나의 Helmet 설정에서 X-Frame-Options와 CSP를 모두 끕니다. 다른 계층에서 이를 제공하지 않으면 응답에 두 보호 헤더가 없습니다.
  • 변경 후: 같은 출처의 프레임과 스크립트만 허용하는 정책을 설정합니다. 실제 서비스의 요구 사항과 Helmet 버전에 맞게 조정하세요.

참조