설명
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 버전에 맞게 조정하세요.