[javascript] Express.js에서의 XSS 공격 방어 방법

XSS (Cross-Site Scripting)는 웹 애플리케이션의 취약점으로, 공격자가 악의적인 스크립트를 삽입하여 사용자의 브라우저에서 실행되게 하는 공격입니다. Express.js는 Node.js 기반의 웹 애플리케이션 프레임워크이며, XSS 공격에 대한 강력한 방어 기능을 제공합니다. 이 글에서는 Express.js에서 XSS 공격을 방어하기 위한 몇 가지 방법을 살펴보겠습니다.

1. 입력 데이터 검증 및 정제

사용자로부터 입력 받은 데이터를 검증하여 악의적인 스크립트가 포함되어 있는지 확인해야 합니다. Express.js의 내장 기능인 express-validator를 사용하면 간편하게 입력 데이터의 유효성을 검사할 수 있습니다. 이를 통해 입력 데이터에 대한 필터링, 이스케이프 처리 등의 작업을 수행할 수 있습니다.

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

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

    // 로그인 처리
    // ...
});

2. 출력 데이터 이스케이프 처리

서버에서 클라이언트로 보내는 모든 출력 데이터는 이스케이프 처리를 해야 합니다. Express.js에서는 ejs, pug와 같은 템플릿 엔진을 사용하여 HTML을 렌더링하는 경우, 자동으로 출력 데이터를 이스케이프 처리해줍니다. 하지만 직접 HTML 문자열을 생성하는 경우에는 이스케이프 처리를 수동으로 해주어야 합니다.

app.get('/user/:id', (req, res) => {
    const userId = req.params.id;

    // 출력 데이터 이스케이프 처리
    const safeUserId = escapeHtml(userId);

    res.send(`<h1>User ID: ${safeUserId}</h1>`);
});

3. 쿠키 보안 설정

Express.js에서 쿠키를 사용하는 경우, 쿠키 값에 악의적인 스크립트가 삽입되지 않도록 주의해야 합니다. httpOnlysecure 옵션을 활성화하여 쿠키를 안전하게 설정할 수 있습니다. 이렇게 설정하면 클라이언트에서 쿠키에 접근하기 위해 자바스크립트를 사용할 수 없습니다.

app.use(cookieParser());

app.get('/set-cookie', (req, res) => {
    // 악의적인 스크립트가 삽입될 수 있는 쿠키 값 설정
    const maliciousCookieValue = `<script>alert('XSS');</script>`;

    // 쿠키 보안 설정
    res.cookie('myCookie', maliciousCookieValue, { httpOnly: true, secure: true }).send('Cookie Set');
});

app.get('/get-cookie', (req, res) => {
    // 쿠키 값 읽기
    const myCookie = req.cookies.myCookie;

    res.send(`Cookie Value: ${myCookie}`);
});

4. 컨텐츠 보안 헤더 설정

마지막으로, Express.js에서 컨텐츠 보안 헤더를 설정하여 XSS 공격을 방어할 수 있습니다. helmet 패키지를 사용하면 간단하게 컨텐츠 보안 헤더를 설정할 수 있습니다.

const helmet = require('helmet');

app.use(helmet());

위의 코드는 다양한 보안 헤더를 기본적으로 활성화합니다. XSS 공격 방어를 위해서는 X-XSS-Protection 헤더를 설정해야 합니다.

app.use(helmet({
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            scriptSrc: ["'self'"],
            styleSrc: ["'self'"],
            fontSrc: ["'self'"],
            imgSrc: ["'self'"],
            objectSrc: ["'none'"],
            baseUri: ["'self'"],
            formAction: ["'self'"],
            frameAncestors: ["'self'"],
            frameSrc: ["'self'"],
            upgradeInsecureRequests: true
        }
    },
    xssFilter: true
}));

위의 설정은 기본적인 보안 헤더를 설정함과 동시에, 컨텐츠 보안 정책(CSP)을 강화하여 스크립트 실행 및 외부 리소스 로딩을 제한합니다.

결론

Express.js에서 XSS 공격을 방어하기 위해 입력 데이터 검증, 출력 데이터 이스케이프 처리, 쿠키 보안 설정, 컨텐츠 보안 헤더 설정 등의 방법을 살펴보았습니다. 이러한 방어 메커니즘을 적절하게 사용하여 Express.js 애플리케이션의 보안을 강화할 수 있습니다.


참고 문서: