[javascript] Express.js에서의 XSS 필터링 방법

Express.js는 Node.js를 기반으로 한 웹 애플리케이션 프레임워크로, 쉽고 간편하게 웹 애플리케이션을 개발할 수 있습니다. 하지만, 보안 취약점 중 하나인 XSS(Cross-Site Scripting) 공격에 취약할 수 있습니다. 이러한 XSS 공격을 막기 위해 Express.js에서는 몇 가지 방법을 제공합니다.

1. Helmet 미들웨어 사용

Helmet은 Express.js에서 제공하는 보안 관련 미들웨어 패키지입니다. 이 패키지를 사용하면 다양한 보안 기능을 쉽게 적용할 수 있습니다. 특히, XSS 필터링을 위해 helmet.contentSecurityPolicy를 설정하면 됩니다.

const express = require('express');
const helmet = require('helmet');

const app = express();
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'"],
    styleSrc: ["'self'"]
    // 필요한 경우 추가적인 설정을 할 수 있습니다.
  }
}));

// 이하 라우터 및 미들웨어 설정

위의 예제 코드에서는 defaultSrc, scriptSrc, styleSrc 등에서만 'self'를 허용하도록 설정하였습니다. 이러한 설정을 통해 개발자가 의도한 것 이외의 외부 스크립트나 스타일 등이 삽입되는 것을 방지할 수 있습니다.

2. 입력 값 검증 및 이스케이핑

XSS 공격은 주로 사용자의 입력 값을 악용하여 발생하므로, 입력 값의 검증과 이스케이핑을 통해 방어할 수 있습니다. Express.js에서는 express-validator와 같은 라이브러리를 사용하여 입력 값의 검증을 간편하게 처리할 수 있습니다.

const express = require('express');
const { check, validationResult } = require('express-validator');

const app = express();

app.post('/signup', [
  check('username').isLength({ min: 5 }),
  check('password').isLength({ min: 8 }),
], (req, res) => {
  // 입력 값 검증
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  // 입력 값 이스케이핑 등 처리
  // ...

  // 이하 로직 처리
  // ...
});

// 이하 라우터 및 미들웨어 설정

위의 예제 코드에서는 /signup 엔드포인트에서 usernamepassword의 길이를 검증하는 예시를 보여줍니다. 검증 결과에 따라 적절한 응답을 반환하고, 입력 값 이스케이핑 등의 처리를 추가로 할 수 있습니다.

3. 템플릿 엔진 사용 시 Escape 기능 활용

Express.js에서 템플릿 엔진을 사용하여 동적 콘텐츠를 생성하는 경우에는 Escape 기능을 활용하여 XSS 공격을 방어할 수 있습니다. 템플릿 엔진마다 Escape 기능에 대한 문법이 다를 수 있으므로, 해당 템플릿 엔진의 공식 문서를 참조하는 것이 좋습니다.

예를 들어, Handlebars 템플릿 엔진에서는 이스케이프를 위해 }과 같은 3중 중괄호 구문을 사용할 수 있습니다.

const express = require('express');
const exphbs = require('express-handlebars');

const app = express();

app.engine('handlebars', exphbs({
  // 템플릿 엔진 설정
  helpers: {
    safeString: (value) => {
      return new Handlebars.SafeString(value);
    }
  }
}));
app.set('view engine', 'handlebars');

app.get('/', (req, res) => {
  const username = '<script>alert("XSS 공격")</script>';

  res.render('home', { username });
});

// 이하 라우터 및 미들웨어 설정

위의 예제 코드에서는 Handlebars 템플릿 엔진을 사용하여 / 경로에 접속하면 home 템플릿을 렌더링합니다. username 변수에는 <script>alert("XSS 공격")</script>와 같은 값이 포함되어 있으나, Handlebars의 Escape 기능을 통해 이스케이핑되어 XSS 공격이 방어됩니다.

위에서 소개한 방법들은 XSS 공격에 대한 대응을 위한 몇 가지 예시일 뿐입니다. 실제 서비스에 적용할 때는 추가적인 보안 검토와 필요한 설정을 고려해야 합니다.