이설아
Study

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

14.1 리액트에서 발생하는 크로스 사이트 스크립팅(XSS)

웹사이트 개발자가 아닌 제 3자가 웹사이트에 악성 스크립트를 삽입해 실행할 수 있는 것

  • 웹 애플리케이션에서 가장 많이 보이는 취약점 중 하나

dangerouslySetinnerHTML prop

특정 브라우저 DOM의 innerHTML을 특정한 내용으로 교체할 수 있는 방법

  • 사용자나 관리자가 입력한 내용을 브라우저에 표시하는 용도로 사용

  • dangerouslySetinnerHTML은 __html을 키를 가지고 있는 객체만 인수로 받을 수 있음

    ⇒ 인수로 넘겨받은 문자열을 DOM에 그대로 표시하는 역할

    ⇒ 인수로 받는 문자열에 제한이 없음

useRef를 활용한 직접 삽입

DOM에 직접 내용을 삽입할 수 있는 방법

  • 직접 DOM에 접근하여 innerHTML에 보안 취약점이 있는 스트립트를 삽입하면 문제가 발생

리액트에서 XSS 문제를 피하는 방법

  • HTML을 안전한 HTML 코드로 한 번 치환하여 XSS 이슈를 피하는 것

    ⇒ 해당 과정을 새니타이즈(sanitize) 혹은 이스케이프(escape)라 함

  • 이것들보다 가장 확실한 방법은 라이브러리를 사용하는 것

14.2 getServerSideProps와 서버 컴포넌트를 주의하자

  • 서버에는 일반 사용자에게 노출되면 안되는 정보들이 담겨져 있기 때문에 브라우저에 정보를 내려줄 때는 조심해야 함

  • getServerSideProps가 반환하는 값 또는 서버 컴포넌트가 클라이언트 컴포넌트에 반환하는 props는 반드시 필요한 값으로만 철저하게 제한되어야 함

    ⇒ 보안 측면의 이점뿐만 아니라 성능 측면에서도 이점을 가져다 줄 수 있음

14.3 <a> 태그의 값에 적절한 제한을 둬야 한다

  • href 내에 js 코드가 존재한다면 실행하는 패턴은 안티패턴임

14.4 HTTP 보안 헤더 설정하기

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

Strict-Transport-Security

  • 모든 사이트가 HTTPS를 통해 접급해야 함
  • HTTP로 접근하는 경우 모든 시도는 HTTPS로 변경하게 됨

X-XSS-Protection

  • 비표준 기술로, 사파리와 구형 브라우저에서만 제공되는 기능
  • 페이지에서 XSS 취약점이 발견되면 페이지 로딩을 중단하는 헤더
  • 해당 헤더를 전적으로 믿어서는 안되며, 반드시 페이지 내부에서 XSS에 대한 처리를 하는 것이 좋음

X-Frame-Options

  • frame, iframe, embed, object 내부에서 렌더링을 허용할지 나타낼 수 있음

Permissions-Policy

  • 웹사이트에서 사용할 수 있는 기능과 없는 기능을 명시적으로 선언하는 헤더
  • 다양한 브라우저의 기능이나 API를 선택적으로 활성화하거나 필요에 따라서는 비활성화할 수 있음

X-Content-Type-Option

  • Content-type 헤더에서 제공하는 MIME 유형이 브라우저에 의해 임의로 변경되지 않게 하는 헤더

    Content-type: text/css 헤더가 없는 파일은 브라우저가 임의로 CSS로 사용할 수 없음

Referrer-Policy

  • Referrer이라는 헤더에는 현재 요청을 보낸 페이지의 주소가 나타남

Content-Security-Policy

  • XSS 공격이나 데이터 삽입 공격과 같은 다양한 보안 위협을 막기 위해 설계

*-src: 다양한 src를 제어할 수 있는 지시문

form-action: 폼 양식으로 제출할 수 있는 URL 제한 가능

보안 헤더 설정하기

Next.js: HTTP 경로별로 next.consig.js에 보안 헤더 적용 가능

NGINX: 경로별로 add_header 지시자를 사용해 원하는 응답 헤더 추가 가능

보안 헤더 확인하기

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

  • package-lock.json의 모든 의존성을 파악하는 것은 불가능

    ⇒ 깃허브의 Dependabot이 발견한 취약점을 빠르게 업데이터 조치해야함

    ⇒ 업데이트가 웹사이트의 기능에 문제가 생기지 않도록 적절한 테스트 코드도 준비해야 함

  • 리액트, Next.js 등 사용중인 상태 관리 라이브러리와 같이 프로젝트를 구성하는 핵심적인 패키지는 보저닝과 패치 수정 등은 항상 예의 주시 해야 함

14.6 OWASP Top 10

  • Open WroldWide Application Security Project의 약자

  • 오픈소스 웹 애플리케이션 보안 프로젝트를 의미

  • 웹에서 발생할 수 있는 정보 노출, 악성 스크립트, 보안 취약점 등을 연구하며 주기적으로 10대 웹 애플리케이션 취약점을 공개

    ⇒ 이를 OWASP Top 10이라 함

  • 주요 보안 취약점을 요약해줄 뿐더러 어떻게 조치해야 하는지도 알려줌

15. 마치며

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

유지보수 중인 서비스라면 리액트 버전을 최소 16.8.6에서 최대 17.0.2로 올려두자

  • 대부분의 리액트 리케이션 생태계, 라이브러리가 모두 훅을 지원한다는 가정하에 작성되어있기에 향후 원활한 지원을 위해 16.8.6 이상으로 맞추는 것이 좋음

인터넷 익스플로러 11 지원을 목표로 한다면 각별히 더 주의를 기한다

  • 인터넷 익스플로러 11 등 레거시 브라우저를 지원해야 하는 경우에는 npm install에 주의를 기울여야 함

서버 사이드 렌더링 애플리케이션을 우선적으로 고려한다

  • 제한적인 사용자에게 빠르게 웹 페이지를 제송해야 하는 경우, 서버를 준비해야 할 상황이 여의치 않은 경우 등에만 SPA로 만드는 것을 추천
  • 그 외에는 SSR을 고려하는 것이 좋음

상태 관리 라이브러리는 꼭 필요할 때만 사용한다

  • 리액트로 개발하기 전, 반드시 필요한지 생각해보기 ⇒ 애플리케이션에서 관리해야 할 상태가 많은지의 여부 ⇒ 관리할 상태가 많고, 여러 상태를 합성하고 파생하는 등의 필요성이 있다면 사용

  • 관리할 상태가 적은, 비교적 정적인 애플리케이션이라면 굳이 필요하지 않음

    ⇒ 추가하게 되면 부자연스러운 프로젝트 구조를 야기하며, 쓸데없이 번들링 크기만 키움

리액트 의존성 라이브러리 설치를 조심한다

  • 설치하려는 라이브러리의 peerDependencies가 리액트 버전과 맞는지 확인

    ⇒ 특히 리액트 18을 지원하지 않는데, 자체적으로 상태를 관리하는 라이브러리는 더욱 조심

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

리액트는 그래서 정말 완벽한 라이브러리인가?

  • 단정짓기는 어려움
  • 리액트를 반대하는 사람들은 많으며, 대안을 주장하는 사람들도 존재
    1. 클래스형 컴포넌트에서 함수형 컴포넌트로 넘어오면서 느껴지는 혼란
    2. 너무 방대한 자유가 주는 혼란

오픈소스 생태계의 명과 암

  • 페이스북 라이선스 이슈

    ⇒ 자신이 오픈소스로 만든 소프트웨어에 대한 권리를 한순간에 잃어버릴 수도 있음

  • 오픈소스는 무료로 계속 제공될 수 있는가? colors.js, faker.js, 그리고 바벨

    ⇒ 바벨이 오픈소스를 포기한다면 큰 파장을 불러옴

    ⇒ 프론트엔드 개발자들은 오픈소스의 중요성을 잊으면 안됨

제이쿼리, AngularJS, 리액트, 그리고 다음은 무엇인가?

  • 많은 프레임워크가 등장하고, 리액트는 그 중 많이 쓰이는 프레임워크이지만, 다른 프레임워크가 떠오를 수도 있기에 유연한 자세를 지녀야 함

웹 개발자로서 가져야 할 유연한 자세

  • 어떤 프레임워크를 사용하든 HTML, CSS, JS는 웹 페이지를 구성하는 기초 기술

    ⇒ 클로저의 개념과 원리, 활용은 리액트의 전유물이 아니며, 비동기 작업도 마찬가지로 처리하는 방법에 있어 약간의 차이가 있을 뿐, 마이크로 태스 크를 활용해 브라우저에서 작업을 처리한다는 사실에는 변함이 없음