장경은
Study

[14장] 웹사이트 보안을 위한 리액트와 웹페이지 보안 이슈

리액트에서 발생하는 XSS

  • 크로스 사이트 스크립팅(Cross-Site Scripting, XSS)이란 웹 애플리케이션에서 가장 많이 보이는 취약점 중 하나로, 웹사이트 개발자가 아닌 제3자가 웹사이트에 악성 스크립트를 삽입해 실행할 수 있는 취약점을 의미한다.
  • 리액트에서 XSS를 이슈를 피하는 가장 확실한 방법은 제3자가 삽입할 수 있는 HTML을 안전한 HTML 코드로 한 번 치환하는 것이다.
  • 이러한 과정을 새니타이즈(sanitize) 또는 이스케이프(escape)라고 한다.
  • npm 라이브러리를 사용하여 구현할 수 있다.
  • 서버는 클라이언트에서 사용자가 입력한 데이터는 일단 의심한다라는 자세로 클라이언트의 POST 요청에 있는 HTML을 이스케이프하는 것이 제일 안전하다.

a태그의 값에 적절한 제한을 둬야한다.

  • XSS에서 소개한 사례와 비슷하게, href에 사용자가 입력한 주소를 넣을 수 있다면 이 또한 보안 이슈로 이어질 수 있다.
  • 따라서 href로 들어갈 수 있는 값을 제한해야 한다. 그리고 피싱 사이트로 이동하는 것을 막기 위해 가능하다면 origin도 확인해 처리하는 것이 좋다.

HTTP 보안 헤더 설정하기

  • HTTP 보안 헤더란 브라우저가 렌더링하는 내용과 관련된 보안 취약점을 미연에 방지하기 위해 브라우저와 함께 작동하는 헤더를 의미한다.

Strict-Transport-Security

  • HTTP의 Strict-Transport-Security 응답 헤더는 모든 사이트가 HTTPS를 통해 접근해야 하며, 만약 HTTP로 접근하는 경우 이러한 모든 시도는 HTTPS로 변경되게 한다.
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains

X-XSS-Protection

  • X-XSS-Protection은 비표준 기술로, 현재 사파리와 구형 브라우저에서만 제공되는 기능이다.
  • 이 헤더는 페이지에서 XSS 취약점이 발견되면 페이지 로딩을 중단하는 헤더다.

X-Frame-Options

  • X-Frame-Options는 페이지를 frame, iframe, embed, object 내부에서 렌더링을 허용할지를 나타낼 수 있다.
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
  • DENY: 만약 위와 같은 프레임 관련 코드가 있다면 무조건 막는다.
  • SAMEORIGIN: 같은 origin에 대해서만 프레임을 허용한다.

Permissons-Policy

  • Permissions-Policy는 웹사이트에서 사용할 수 있는 기능과 사용할 수 없는 기능을 명시적으로 선언하는 헤더다
# 모든 geolocation 사용을 막는다.
Permissions-Policy: geolocation=()

# geolocation을 페이지 자신과 몇 가지 페이지에 대해서만 허용한다.
Permissions-Policy: geolocation=(self "https://a.yceffort.kr" "https://b.yceffort.kr")

# 카메라는 모든 곳에서 허용한다.
Permissions-Policy: camera=*;

# pip 기능을 막고, geolocation은 자신과 특정 페이지만 허용하며,
# 카메라는 모든 곳에서 허용한다.
Permissions-Policy: picture-in-picture=(), geolocation=(self https://yceffort.kr), camera=*;

X-Content-Type-Options

  • X-Content-Type-Options란 Content-type 헤더에서 제공하는 MIME 유형이 브라우저에 의해 임의로 변경되지 않게 하는 헤더다.
  • 즉, Content-type: text/css 헤더가 없는 파일은 브라우저가 임의로 CSS로 사용할 수 없으며, Content-type: text/javascript나 Content-type: application/javascript 헤더가 없는 파일은 자바스크립트로 해석할 수 없다.

Referrer-Policy

  • HTTP 요청에는 Referer라는 헤더가 존재하는데, 이 헤더에는 현재 요청을 보낸 페이지의 주소가 나타난다.
  • 만약 링크를 통해 들어왔다면 해당 링크를 포함하고 있는 페이지 주소가, 다른 도메인에 요청을 보낸다면 해당 리소스를 사용하는 페이지의 주소가 포함된다.
  • 이 헤더는 사용자가 어디서 와서 방문 중인지 인식할 수 있는 헤더지만, 반대로 사용자 입장에서는 원치 않는 정보가 노출될 위험도 존재한다.
  • Referrer-Policy 헤더는 이 Referer 헤더에서 사용할 수 있는 데이터를 나타낸다.
  • Referrer-Policy는 응답 헤더 뿐만 아니라 meta 태그나 a 태그에도 사용할 수 있다.

Content-Security-Policy

  • 콘텐츠 보안 정책(Content-Security-Policy, 이하 CSP)은 XSS 공격이나 데이터 삽입 공격과 같은 다양한 보안 위협을 막기 위해 설계됐다.

보안 헤더 설정하기

  • Next.js에서는 애플리케이션 보안을 위해 HTTP 경로별로 보안 헤더를 적용할 수 있다. 이 설정은 next.config.js에서 다음과 같이 추가할 수 있다.
const securityHeaders = [
    {
        key: 'key',
        value: 'value'
    }
];
 
module.exports = {
    async headers() {
        return [
            {
                // 모든 주소에 설정한다.
                source: '/:path*',
                headers: securityHeaders
            }
        ];
    }
};

보안 헤더 확인하기

취약점이 있는 패키지의 사용을 피하자

  • 깃허브의 Dependabot이 발견한 취약점은 필요하다면 빠르게 업데이트해 조치해야 한다.
  • 그리고 이러한 업데이트가 웹사이트의 기능에 문제가 생기지 않도록 적절한 테스트 코드도 준비해야 한다.

OWASP TOP 10

  • OWASP은 Open Worldwide (Web) Application Security Project라는 오픈소스 웹 애플리케이션 보안 프로젝트를 의미한다.
  • 주로 웹에서 발생할 수 있는 정보 노출, 악성 스크립트, 보안 취약점 등을 연구하며, 주기적으로 10대 웹 애플리케이션 취약점을 공개하는데 이를 OWASP Top 10이라고 한다.

정리

  • IT 업계의 보안 문제로 시끄러운 요즘, 개발하고 있는 서비스, 현재 운영하고 있는 서비스에 관계없이 항상 보안 이슈에 귀기울이며 만반의 준비를 갖춰야만 사용자에게 신뢰받는 서비스를 만들 수 있을 것이다.

[15장] 마치며

리액트 프로젝트를 시작할 때 고려해야 할 사항

  • 유지보수 중인 서비스라면 리액트 버전을 최소 17.0.2로 올려두자.
  • 인터넷 익스플로러 11 지원을 목표한다면 각별히 더 주의를 기한다.
  • 서버사이드 렌더링 애플리케이션을 우선적으로 고려한다.
    • 기본 HTML에 온전히 자바스크립트로 렌더링과 라우팅을 수행하는 싱글 페이지 애플리케이션은 대부분의 경우 라이트하우스와 WebPageTest, 구글 개발자 도구에서 좋은 결과를 얻기 어렵다.
  • 상태 관리 라이브러리는 꼭 필요할 때만 사용한다.
    • 반드시 상태 관리 라이브러리가 필요한지 꼭 한번 생각해보자.
    • 상태 관리 라이브러리가 필요한지 여부란, 다시 말하자면 애플리케이션에서 관리해야 할 상태가 많은지 여부를 말한다.
    • 마치 문서 편집기 같이 관리해야 할 상태가 많고, 여러 상태를 합성해서 또 새로운 상태를 파생하는 등 상태에 대한 여러 가지 필요성이 많은 애플리케이션이라면 상태 관리를 사용하는 것이 좋다.
  • 리액트 의존성 라이브러리 설치를 조심한다.

언젠가 사라질 수도 있는 리액트

  • 리액트는 가장 널리 쓰이는 프런트엔드 라이브러리는 맞지만 그렇다고 가장 완벽한 라이브러리라고 단정 짓기는 어렵다. 여전히 리액트를 반대하는 사람들은 많으며, 리액트의 대안을 주장하는 사람들도 있다.
  • 단시일 내에 리액트가 역사의 뒤안길로 사라진다고 주장하는 것은 아니지만 미래는 예측할 수 없으므로 개발자는 유연한 자세를 지녀야 한다. 우리는 리액트 개발자가 아니라 웹 개발자라고 자신을 소개할 수 있어야 한다.
  • 무슨 프레임워크나 라이브러리를 사용하든 한 가지 변하지 않는 사실은 HTML과 CSS, 자바스크립트가 웹페이지를 구성하는 기초 기술이라는 사실이다.
  • 중요한 것은 모든 웹 개발이 HTML, CSS, 자바스크립트라는 토대 위에 세워졌음을 깨닫는 것이다.
  • 리액트를 넘어 다양한 자바스크립트 세계를 맛본다면 리액트에 의존적이지 않은 더욱 유연한 개발자가 될 수 있을 것이다.