정리하기 파일
14장. 웹사이트 보안을 위한 리액트와 웹페이지 보안 이슈
14.1 리액트에서 발생하는 크로스 사이트 스크립팅(XSS)
- 웹사이트 개발자가 아닌 제3자가 웹사이트에 악성 스크립트를 삽입해 실행할 수 있는 취약점을 의미.
14.1.1 dangerousySetInnerHTML prop
- 특정 브라우저 DOM의 innerHTML을 특정한 내용으로 교체할 수 있는 방법.
14.1.2 useRef를 활용한 직접 삽입
- DOM에 직접 내용을 삽입할 수 있는 방법으로 useRef가 있다. useRef를 활용하여 직접 DOM에 접근할 수 있으므로 이 DOM에 앞서와 비슷한 방식으로 innerHTML에 보안 취약점이 있는 스크립트를 삽입하면 dangerousySetInnerHTML prop과 동일한 문제가 발생한다.
14.1.3 리액트에서 XSS 문제를 피하는 방법
- 가장 확실한 방법은 제3자가 삽입할 수 있는 HTML을 안전한 HTML 코드로 한 번 치환하는 것.
- 이러한 과정을 새니타이즈(sanitize) 또는 이스케이프(escape)라고 하는데, 새티나이즈를 직접 구현해 사용하는 등 다양한 방법이 있지만 가장 확실한 방법은 npm에 있는 라이브러리를 사용하는 것이다.
- DOMpurity
- sanitize-html
- js-xss
14.2 getServerSideProps와 서버 컴포넌트를 주의하자
- 서버에는 일반 사용자에게 노출되면 안 되는 정보들이 담겨 있기 때문에 클라이언트, 즉 브라우저에 정보를 내려줄 때는 조심해야 한다.
14.3 <a>
태그의 값에 적절한 제한을 둬야 한다.
<a>
태그는 반드시 페이지 이동이 있을 때만 사용하는 것이 좋다. 페이지 이동이 없이 어떠한 핸들러만 작동시키고 싶다면 a 보다는 button 태그를 사용하는 것이 좋다.
14.4 HTTP 보안 헤더 설정하기
- HTTP 보안 헤더란 브라우저가 렌더링하는 내용과 관련된 보안 취약점을 미연에 방지하기 위해 브라우저와 함께 작동하는 헤더를 의미한다.
14.4.1 Strict-Transport-Security
- Strict-Transport-Security 응답 헤더는 모든 사이트가 HTTPS를 통해 접근해야 하며, 만약 HTTP로 접근하는 경우 이러한 모든 시도는 HTTPS로 변경되게 한다.
14.4.2 X-XSS-Protection
- X-XSS-Protection은 비표준 기술로, 현재 사파리와 구형 브라우저에서만 제공되는 기능이다.
- 이 헤더는 페이지에서 XSS 취약점이 발견되면 페이지 로딩을 중단하는 헤더다.
14.4.3 X-Frame-Options
- X-Frame-Options는 페이지를 frame, iframe, embed, object 내부에서 렌더링을 허용할지를 나타낼 수 있다.
- X-Frame-Options는 자신의 페이지를 위와 같은 방식으로 삽입되는 것을 막아주는 헤더이다.
- X-Frame-Options
- DENY : 만약 위와 같은 프레임 관련 코드가 있다면 무조건 막는다.
- SAMEORIGIN : 같은 origin에 대해서만 프레임을 허용한다.
14.4.4 Permissions-Policy
- Permissions-Policy는 웹사이트에서 사용할 수 있는 기능과 사용할 수 없는 기능을 명시적으로 선언하는 헤더이다.
14.4.5 X-Content-Type-Options
- 이 헤더를 이해하려면 먼저 MIME이 무엇인지 알아야 한다.
- MIME
- Multipurpose Internet Mail Extensions의 약자로 Content-type의 값으로 사용된다.
- 여기서 X-Content-Type-Options란 Content-type 헤더에서 재공하는 MIME 유형이 브라우저에 의해 임의로 변경되지 않게 하는 헤더다.
14.4.6 Referrer-Policy
- HTTP 요청에는 Referer라는 헤더가 존재하는데, 이 헤더에는 현재 요청을 보낸 페이지의 주소가 나타난다.
- Referrer-Policy 헤더는 이 Referer 헤더에서 사용할 수 있는 데이터를 나타낸다.
- Referer에 대해 이야기할 때는 출처(origin)을 빼놓을 수 없다.
- https://yceffort.kr이라는 (opens in a new tab) 주소의 출처를 구성하고 있는 요소들은 다음과 같다.
- scheme : HTTPS 프로토콜을 의미한다.
- hostname : yceffort.kr이라는 호스트명을 의미한다.
- port : 443 포트를 의미한다.
14.4.7 Content-Security-Policy
- 콘텐츠 보안 정책(Content-Security-Policy, 이하 CSP) 은 XSS 공격이나 데이터 삽입 공격과 같은 다양한 보안 위협을 막기 위해 설계됐다.
- -src
- font-src, img-src, script-src 등 다양한 src를 제어할 수 있는 지시문이다.
- form-action
- form-action은 폼 양식으로 제출할 수 있는 URL을 제한할 수 있다.
14.4.8 보안 헤더 설정하기
-
Next.js
- next.config.js에서 다음과 같이 추가할 수 있다.
const securityHeaders = [ { key: "key", value: "value", }, ]; module.exports = { async headers() { return [ { // 모든 주소에 설정한다. source: "/:path*", headers: securityHeaders, }, ]; }, };
-
NGINX
- 정적인 파일을 제공하는 NGINX의 경우 다음과 같이 경로별로 add_header 지시자를 사용해 원하는 응답 헤더를 추가할 수 있다.
location / { #... add_header X-XSS-Protection "1; mode=block"; add_header Content-Security-Policy "default-src 'self'; script-src 'self'; child-src e...m; style-src 'self' example.com; font-src 'self';"; #... }
14.4.9 보안 헤더 확인하기
- 현재 서비스 중인 웹사이트의 보안 헤더를 확인할 수 있는 가장 빠른 방법은 보안 헤더의 현황을 알려주는
https://securityheaders.com/
을 방문하는 것이다.
14.5 취약점이 있는 패키지의 사용을 피하자
https://security.snyk.io/
를 방문해 사용하는 패키지 이름으로 검색해 보면 현재 라이브러리의 취약점을 한눈에 파악할 수 있으므로 패키지 보안 이슈를 추적하는 데 많은 도움이 된다.
14.6 OWASP Top 10
- OWASP은 Open Worldwide (Web) Application Security Project라는 오픈소스 웹 애플리케이션 보안 프로젝트를 의미한다.
- 주로 웹에서 발생할 수 있는 정보 노출, 악성 스크립트, 보안 취약점 등을 연구하며 주기적으로 10대 웹 애플리케이션 취약점을 공개하는데 이를 OWASP Top 10이라고 한다.
- 2021년 OWASP Top 10
- A01: 2021-Broken Access Control
- A02: 2021-Cryptographic Failures
- A03: 2021-Injection
- A04: 2021-Insecure Design
- A05: 2021-Security Misconfiguration
- A06: 2021-Vulnerable and Outdated Components
- A07: 2021-Identification and Authentication Failures
- A08: 2021-Software and Data Integrity Failures
- A09: 2021-Security Logging and Monitoring Failures
- A10: 2021-Server-Side Request Forgery
14.7 정리
- 버그가 없는 완벽한 소프트웨어는 없다. 모든 소프트웨어에는 버그가 있으며, 이 버그가 때로는 보안 취약점으로 이어진다.
- 보안 이슈는 단순히 개발만 잘해서 해결되는 문제가 아니다.
- 소프트웨어를 설계하고, 코드를 작성하고, 서비스를 제공하며 유지보수하는 단계에 이르기까지 웹 서비스의 생명주기 전체에 걸쳐서 발생할 수 있으며, 때로는 개발자 본인이 작성한 코드밖에서도 일어날 수 있다.
15장. 마치며
15.1 리액트 프로젝트를 시작할 때 고려해야 할 사항
15.1.1 유지보수 중인 서비스라면 리액트 버전을 최소 16.8.6에서 최대 17.0.2로 올려두자
- 16.8에서 훅이 소개됐고, 훅 덕분에 함수형 컴포넌트의 개념이 정립됐다.
- 따라서 향후 원활한 지원을 위해 버전을 16.8.6 이상으로 맞추는 것이 좋다.
- 또한 17 버전은 리액트 팀에서 공언한 대로 새로운 기능 출시 및 호환성이 깨지는 변경 사항을 최소한으로 맞춘 업데이트이므로 가능하다면 17버전으로 가는 것도 좋다.
기존에 클래스형으로 작성한 컴포넌트를 함수형으로 리팩터링할 필요가 있을까?
- ‘굳이 그럴 필요는 없다’
- 리액트 팀에서는 클래스형 컴포넌트를 사라지게 할 계획은 없다고 밝혔다. 그러므로 굳이 클래스형 컴포넌트를 함수형으로 서둘러 전환하지 않아도 된다.
15.1.2 인터넷 익스플로러 11 지원을 목표한다면 각별히 더 주의를 기한다.
- 일반적인 경우라면 크게 상관없지만 인터넷 익스플로러 11 등 레거시 브라우저를 지원해야 하는 경우에는 npm install 에 앞서서 반드시 주의를 기울여야 한다.
- 다음은 인터넷 익스플로러 11 을 지원하지 않는 대표적인 라이브러리다.
- 리액트 : 리액트는 18 버전부터 인터넷 익스플로러 11을 지원하지 않기로 했다.
- Next.js : Next.js는 13 버전부터 공식적으로 인터넷 익스플로러 11을 지원하지 않기로 했다.
- query-string : 주소의 쿼리 문자열을 다루는 대표적인 라이브러리인 query-string도 6.x 버전부터 인터넷 익스플로러 11을 지원하지 않는다.
15.1.3 서버사이드 렌더링 애플리케이션을 우선적으로 고려한다.
- 관리자와 같이 제한적인 사용자에게 빠르게 웹페이지를 제공해야 하는 경우, 혹은 이벤트 페이지와 같이 콘텐츠와 인터랙션이 매우 제한적인 소규모 웹페이지를 만드는 경우, 혹은 서버를 준비해야 할 상황이 여의치 않은 경우에만
싱글 페이지 애플리케이션
을 만들 것을 추천한다. - 많은 사용자를 감당해야 하고, 혹은 그럴 계획이 있다면, 그리고 서버를 준비할 수 있는 충분한 여유가 된다면 시작부터
서버 사이드 렌더링
을 고려하는 것이 좋다.
15.1.4 상태 관리 라이브러리는 꼭 필요할 때만 사용한다.
- 관리해야 할 상태가 적은, 비교적 정적인 애플리케이션이라면 상태 관리 라이브러리가 굳이 필요하지 않을 수도 있다. 오히려 상태가 적은 애플리케이션에 상태 관리 라이브러리를 추가하는 것은 되려 부자연스러운 프로젝트 구조를 야기할 수 있으며, 쓸데없이 번들링 크기만 키우는 꼴이 될 수 있다.
15.1.5 리액트 의존성 라이브러리 설치를 조심한다.
- 어떠한 기능 구현을 위해 라이브러리를 설치할 때, 특히 리액트에 의존적인 라이브러리를 설치하려고 하는 경우가 있을 것이다. 이런 라이브러리의 대부분은 react-** 같은 이름을 가지고 있으며, 대부분 다음과 같이 리액트에 대한 의존성을 가지고 있다.
{
"peerDependencies" : {
"react" : "^16.8.6 || ^17.0.0",
"react-dom" : "^16.8.6 || ^17.0.0",
}
}
- 이때 반드시 이 peerDependencies가 설치하고자 하는 프로젝트의 리액트 버전과 맞는지 확인해야 한다.
15.2 언젠가 사라질 수도 있는 리액트
15.2.1 리액트는 그래서 정말 완벽한 라이브러리인가?
- 클래스형 컴포넌트에서 함수형 컴포넌트로 넘어오면서 느껴지는 혼란
- 너무 방대한 자유가 주는 혼란
15.2.2 오픈소스 생태계의 명과 암
- 페이스북 라이선스 이슈
- 오픈소스는 무료로 계속 제공될 수 있는가? colors.js, faker.js 그리고 바벨
15.2.3 제이쿼리, AngularJS, 리액트, 그리고 다음은 무엇인가?
15.2.4 웹 개발자로서 가져야 할 유연한 자세
- 무슨 프레임워크나 라이브러리를 사용하든 한 가지 변하지 않는 사실은 HTML과 CSS, 자바스크립트가 웹페이지를 구성하는 기초 기술이라는 사실이다.