GitHub - developer-book/security: 프런트엔드 개발을 위한 보안 입문
프런트엔드 개발을 위한 보안 입문. Contribute to developer-book/security development by creating an account on GitHub.
github.com
목차
- 1장 - 웹 보안의 개요
- 2장 - 실습 준비
- 3장 - HTTP
- 안전한 통신을 위한 HTTPS
1장 - 웹 보안의 개요
요구사항에는 기능 요구사항과 비기능 요구사항이 있다. 기능 요구사항은 '로그인', '예약 날짜 변경', '결제 방식 선택' 등과 같이 소프트웨어 사용의 주목적이 되는 기능이다. 비기능 요구사항은 '서버 응답 3초 이내', '트래픽과 무관하게 서버 다운되지 않기'와 같이 소프트웨어 사용의 주목적은 아니지만 필요한 요구사항이다. 보안은 비기능 요구사항의 일종이다. 따라서 요구사항에 만족한 소프트웨어를 만들기 위해서 신경 써야 하는 부분이다.
보안의 기준은 시대가 흐름에 따라 변화한다. 공격하는 방법이 다양해야 질수록 방어하는 방법도 다양해질 수밖에 없기 때문이다.
2장 - 실습 준비
실습에서 사용하는 소프트웨어는 다음과 같다.
- 브라우저
- 코드 에디터 (VSCode)
- 터미널
- Node.js (집필 시점 v18.12.1)
- npm
- Express (집필 시점 v4.18.2)
실습을 위해 Express를 설치하고 기본적인 서버 구축과 정적 파일(public 폴더)를 전달 가능하도록 작성한다.
hosts 파일을 수정해서 127.0.0.1의 호스트명을 변경할 수 있다.
- Mac: /private/etc/hosts
- Window: C:\Windows\System32\drivers\etc\hosts
security/chapter2 at main · developer-book/security
프런트엔드 개발을 위한 보안 입문. Contribute to developer-book/security development by creating an account on GitHub.
github.com
3장 - HTTP
브라우저는 HTTP 통신 프로토콜에 따라 서버와 통신한다. 그리고 서버를 특정하기 위해 URL과 DNS를 이용한다. 이 중 DNS, HTTP는 TCP/IP 방식을 사용한다.
URL (uniform resource locator)
- 스키마명(프로토콜): 통신 프로토콜을 표시한다.
- 도메인명(호스트명): 서버의 위치다.
- 포트: 서버에서 서비스를 식별하는 번호다.
- 경로: 서버에서 리소스의 위치를 표시한다.
DNS (domain name system)
인터넷에 접속한 모든 기기는 ip라는 일종의 주소를 가지고 있다. 특정 서버에 접근하려면 주소를 알아야 하기 때문이다. 하지만 주소는 숫자로 이루어졌다. 예를 들어 223.130.192.248은 어느 서버일까? 443 포트번호까지 작성하면 네이버로 연결된다. 그렇다고 우리는 223.130.192.248를 외우거나 주소창에 쳐서 접근하지 않는다. naver.com를 치고 접근한다. 그럼 naver.com를 223.130.192.248로 바뀌어진다는 것을 추론해볼 수 있다. 그 역할을 하는 것이 DNS다. DNS는 일종의 전화번호부 같은 것이다. 스마트폰으로 전화를 걸때 일반적으로 전화번호를 외워서 전화하지 않는다. 전화하고자 하는 상대방을 전화번호부에서 검색해서 전화한다. 마찬가지로 브라우저 주소창에 naver.com을 치면 DNS에 접근하여 ip주소를 알아온다음 naver.com의 ip주소로 접근한다.
TCP/IP
이제 접속할 서버의 대상을 찾았고 리소스를 주고 받는다. 주고 받는 과정에서 리소스를 어떻게 보내고 받을 것인지 고민해 볼 필요가 있다. 예를 들어 클라이언트가 서버에 3개의 요청을 보냈다고 가정해보자. 클라이언트는 서버에 3개의 요청을 순서대로 보냈기 때문에 순서대로 온다고 예상하고 있다. 그런데 서버는 요청을 빠르게 끊어내는 것이 부담이 덜 된다고 판단해서 요청의 응답 크기가 작은 순서부터 보냈다. 응답을 받은 클라이언트는 각 요청에 대한 정확한 응답이 맞는지 신뢰하기 어렵다. 그래서 통신 규약이라는 개념이 등장한다. 통신 규약은 통신할 때 '이러한 형식으로 보낼테니 이렇게 해석하시면 됩니다.' 라는 일종의 약속이다. 그럼 통신 규약에 따른 요청과 응답이 생기면 통신 규약대로 해석하면 되니 리소스에 대해 신뢰할 수 있다.
통신 프로토콜의 종류 중 하나가 HTTP다. 통신 프로토콜 사양은 IETF라고 하는 표준화 기구에서 RFC 문서로 작성해 관리한다.
TCP와 IP를 포함하는 통신 프로토콜을 총칭해 TCP/IP라고 하며 4계층으로 구성된다.
- 레이어4 - 응용 계층: 애플리케이션에서 통신한다. (HTTP, SMTP)
- 레이어3 - 전송 계층: 인터넷 계층에서 받은 데이터를 애플리케이션 계층으로 전달하거나 데이터 오류를 감지한다. (TCP, UDP)
- 레이어2 - 인터넷 계층: 어떤 컴퓨터로 데이터를 전달할지 결정한다. (IP)
- 레이어1 - 네트워크 접속 계층: 통신기기는 문자, 숫자 데이터를 그대로 전달할 수 없으므로 물리적으로 전송 가능한 전기 신호로 변환되어야한다. (Ethernet: 유선 LAN, IEEE 802.11: 무선 LAN)
전송 측은 각 레이어에서 헤더를 생성해 하위 계층의 프로토콜로 데이터를 전달하고 수신 측은 각 레이어의 헤더를 꺼내 상위 계층의 프로토콜로 데이터를 전달한다.
HTTP 메시지
HTTP 메시지는 클라이언트와 서버 사이에서 데이터가 통신하는 방식이다. 메시지 타입에는 '요청 메시지'와 '응답 메시지'가 있습니다.
두 메시지 타입은 '첫 행', '헤더', 공백줄, '본문'으로 구성되어 있습니다. '첫 행'에서는 요청인지 응답인지, 요청이라면 어떤 요청인지, 응답이라면 응답 결과는 어떤건지 등 어떤 메세지인지에 대해 알 수 있는 부분이다. '헤더'에서는 메시지에 대해 설명을 포함한 메타데이터이다. 그리고 공백줄을 기준으로 본문을 구분짓게 했다. '본문'에서는 서버나 클라이언트에 보낼 데이터의 내용이 담겨져 있습니다.
HTTP 메서드, 상태코드, HTTP 헤더
위 내용은 잘 정리되고 자세히 작성된 MDN의 문서로 갈음한다.
쿠키를 사용한 상태 관리
HTTP는 원래 문서 전송을 위해 개발된 프로토콜이므로 서버가 클라이언트가 누구인지 알 필요가 없었다. 그러나 웹이 보급되고 어떤 클라이언트인지 따른 데이터 전송을 HTTP로 하려는 요구가 생겨남에 따라 서버는 클라이언트가 누군지 알 필요가 생겼다. 이에 따라 서버와 브라우저(클라이언트) 안의 쿠키라는 파일에 보관하는 방식이 생겼다.
자세한 내용은 MDN 쿠키 문서를 참고하자.
안전한 통신을 위한 HTTPS
HTTP는 단순 문서 전송을 위해 만들어진 통신 규약이므로 그 당시에는 보안이 고려대상이 아니었다. 그러나 시대의 흐름이 변하면서 웹과 HTTP는 다양한 데이터를 다루게되어 보안이 중요해졌다.
HTTP의 약점은 크게 3가지 있다.
- 통신 데이터 도청이 가능한 점
- 통신 상대의 진위 여부 확인이 어려운 점
- 동신 과정에서 데이터 수정 여부가 확인이 안 되는 점
HTTP 약점을 해결하는 TLS
HTTP의 3가지 약점을 해결하려면 HTTPS를 사용해 통신해야 한다. HTTPS는 TLS라고 하는 통신 프로토콜을 사용해 HTTP 데이터를 암호화해서 통신하는 구조다. HTTP 데이터 통신을 하기 전에 TLS handshake라고 하는 일련의 암호 통신 과정을 거친다.
TLS에 관한 자세한 내용은 MDN 문서를 참고하고 HTTP 약점 3가지에 대해 어떻게 해결하고 있는지 살펴보자.
- 통신 데이터 암호화
- TLS는 데이터를 암호화하고 복호화하는 기능을 제공하여 데이터 도청을 차단한다. 암호화와 복호화에 필요한 키(비밀키)는 클라언트와 서버의 통신을 통해 안전하게 공유되며, 키를 가지고 있을 대만 암호문을 복호화할 수 있다. 그리고 비밀 키는 TLS의 통신마다 생성되는 일시적인 것이며, 통신이 종료되면 폐기되므로 서버가 공격당해도 비밀 키는 유출되지 않는다.
- 통신 상대 검증
- TLS는 전자 인증서로 통신 상대를 확인하며, 전자 인증서는 신뢰 가능한 기관인 CA(certificate authority)에서 발행한다. 서버에서 전송된 인증서는 브라우저(클라이언트)가 검증하고 다시 브라우저와 OS에 있는 인증서와 대조한다. CA에서 발행되지 않은 인증서가 사용되면 브라우저는 경고를 표시한다.
- 통신 데이터 변경 체크
- TLS는 데이터 변조를 체크하는 기능도 제공한다. 데이터의 내용을 볼 수 없더라도 공격자는 암호문을 변조할 가능성이 있다. 따라서 안전하게 데이터를 주고받으려면 데이터에 변조가 없는 것을 확인해야 한다. 이를 위해 TLS는 '인증 태그'라는 검증용 데이터를 사용한다. 인증 태그는 데이터의 암호화와 동시에 작성되어 상대에게 전송되며, 수신자는 복호화와 동시에 인증 태그를 사용해 암호문의 변조를 체크한다.
Mixed Content의 위험성
HTTP를 사용한 웹 애플리케이션에서 HTTP 통신을 사용하는 리소스가 혼재되어 있는 상태를 Mixed Content라고 한다. 웹 애플리케이션이 HTTPS를 도입했다고 하더라도 사용하는 자바스크립트와 이미지 등의 하부 리소스가 HTTP 통신을 사용하면 안전하다고 말할 수 없다.
HTTP로 받은 자바스크립트 파일을 HTTPS의 웹 애플리케이션에서 호출하는 상황을 생각해보자. 자바스크립트 파일을 가져오는 통신은 암호화되어 있지 않으므로 공격자는 자바스크립트 파일 내부를 도청하거나 수정할 수 있게 된다.
이와 같은 무제를 피하려면 Mixed Content가 없도록 해야 한다. Mixed Content는 Passive mixed content와 Active mixed content의 두 종료의 패턴이 있으며 각각 웹 애플리케이션에 미치는 영향은 다르다. Passive mixed content는 이미지와 영상, 음성 파일과 같은 리소스가 Mixed Content를 발생시키는 패턴이다. 이와 같은 리소스가 변경되면 잘못된 정보가 표시될 수 있지만 브라우저에서 실행되는 코드는 포함하지 않으므로 영향이 적다고 볼 수 있다.
반대로 Active mixed content는 자바스크립트와 CSS 등 브라우저에서 실행되는 코드에 대한 Mixed Content 패턴이다. 이 코드가 변경되면 보안 공격과 같은 문제가 발생할 위험이 높아진다.
구글 크롬, 파이어폭스, 사파리 등 대부분 브라우저는 다른 사이트에서 전송되는 Active mixed content의 하부 리소스 접근이 이미 차단되어 있다. HTTP로 전송되는 자바스크립트와 CSS는 변경되지 않더라도 차단이 되어 웹 애플리케이션이 제대로 동작하지 않을 때도 있다.
자세한 내용은 MDN 문서를 참고하자.
HSTS를 사용해 HTTPS 통신 강제하기
HTTPS를 사용하는 웹 애플리케이션이라도 HTTP 접속을 허용할 때가 있다. 예전에는 HTTP 통신 밖에 없었으므로 http://로 시작하는 URL로 시작하는 URL로 다른 웹 애플리케이션에서 링크를 거는 것과 같은 방식이 많았다. 웹 애플리케이션에서 HTTPS를 사용하고 HTTP 통신을 멈추면 http://로 시작하는 URL에서의 접속은 불가능해진다. 이 문제를 피하기 위해 HTTPS를 사용하는 웹 애플리케이션도 HTTP 전송을 계속 허가하는 경우가 있다.
이와 같은 애플리케이션이라도 HSTS(HTTP strict transport security) 구조를 적용하면 사용자가 HTTPS통신을 사용하도록 강제할 수 있다., HSTS를 유효화하려면 응답 헤더에 Strict-Transport-Security 헤더를 추가한다. 브라우저는 Strict-Transport-Security 헤더를 받으면 이후의 웹 애플리케이션 요청은 HTTPS를 사용한다.
자세한 내용은 MDN 문서를 참고하자.
'Developer > Study' 카테고리의 다른 글
동기, 비동기 그리고 Blocking, Non-Blocking 3편 | 작성해볼까? (0) | 2025.03.30 |
---|---|
동기, 비동기 그리고 Blocking, Non-Blocking 2편 | 조합해볼까? (0) | 2025.03.02 |
동기, 비동기 그리고 Blocking, Non-Blocking 1편 | 비교해볼까? (0) | 2025.02.02 |
fireEvent와 userEvent 구현체 살펴보기 (0) | 2024.01.21 |
리액트의 렌더링이란? (0) | 2023.02.28 |
Javascript Module System (0) | 2023.01.23 |
[JavaScript] Hoisting 이란? (0) | 2022.01.27 |
댓글