Interaction With Server - Browser Security

Verba volant, scripta manent·2021년 2월 7일
0

서버 보안은 매우 중요하다!
그래서 이번엔 보안 기술에 대해 블로깅해봤다.
그 중 꼭 알아야할 2가지 기술이 있다.

들어가기 전에 간단하게 CSRF에 대해 설명해보겠다.

CSRF란?

풀네임은 Cross-Site Request Forgery
사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제 등)를 특정 웹사이트에 요청하게 하는 공격을 뜻한다.

이러한 취약점이 발생하는 이유

HTTP Protocol은 Client-Server Model에 따라, Client Request -> Server Response 프로세스를 반복하고, Connectionless, Stateless 특성을 가지고 있기 때문에, 서버는 대개 쿠키를 사용하여 클라이언트를 식별한다.

CSRF는 이러한 HTTP Protocol의 특징을 악용하여 공격을 수행한다.
서버로부터 인증받은(로그인) 사용자가 공격자가 생성한 링크에 접속하면 사용자의 쿠키와 함께 악의적 요청이 서버에 보내지고, 서버는 받은 요청을 사용자의 요청으로 처리하게 된다.

CSRF의 공격 방법

CSRF를 수행하기 위해 우선 클라이언트가 공격 대상 웹 서버에 파라미터(입력값)를 어떻게 전달하는지 파악해야 하는데, 어떤 요청이 무슨 주소를 사용하는지, 어떤 변수를 입력해야 하는지, GET방식인지 POST방식인지를 알아내어 원하는 요청 주소를 생성한다.

그리고나서 이 링크를 공격 대상 웹 서버에서 인증받은(로그인) 사용자가 해당 링크를 클릭하게 하면 된다.
클릭하게 하는 방법은 크게 두 가지가 있다.
1. 희생자에게 피싱 메일 같은 방법으로 속여 링크를 클릭하게 만든다.
2. XSS 또는 HTML태그를 이용해 희생자를 해당 링크로 강제 이동시킨다.

게시글 같은 경우는 크게 위험은 없으나 금전적인 송금일 경우.. 그 이상의 설명은 생략하겠다.

CSRF로부터 방어하는 방법

CSRF를 방어하기 위해서는, Back-end단에서 특정 사용자가 보낸 요청에 대해 그 요청이 정말 특정 사용자가 보냈는지 검사해야 하는데, 이를 위해 일반적으로 CSRF Token이 사용된다.
요청 처리 시, 요청에 포함된 Token과 세션에 저장된 Token을 비교하여 검증한다.

=> 요청 Token과 세션에 저장된 Token을 비교하는 것!

CORS란?

풀네임은 Cross-Origin Resource Sharing, 해석하면 교차 출처 리소스 공유
추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.

a.com이 b.com처럼 서로 다른 origin(출처)을 가진 곳으로 리소스(데이터)를 요청하는 경우, 보안을 침해할 가능성이 있기 때문에 브라우저가 서버의 응답을 무시해버리는 이슈다.

CORS 기능

교차 출처 리소스 공유 표준은 웹 브라우저에서 해당 정보를 읽는 것이 허용된 출처를 서버에서 설명할 수 있는 새로운 HTTP 헤더를 추가함으로써 동작한다.
추가적으로, 서버 데이터에 부수 효과(side effect)를 일으킬 수 있는 HTTP 요청 메서드(GET을 제외한 HTTP 메서드)에 대해, CORS 명세는 브라우저가 요청을 OPTIONS 메서드로 preflight(사전 전달)하여 지원하는 메서드를 요청하고, 서버의 "허가"가 떨어지면 실제 요청을 보내도록 요구하고 있다.
또한 서버는 클라이언트에게 요청에 "인증정보"(쿠키, HTTP 인증)를 함께 보내야 한다고 알려줄 수도 있다.

CORS 실패시?

CORS 실패는 오류의 원인이지만, 보안상의 이유로 JavaScript에서는 오류의 상세 정보에 접근할 수 없으며, 알 수 있는 것은 오류가 발생했다는 사실 뿐이다. 정확히 어떤 것이 실패했는지 알아내려면 브라우저의 콘솔을 봐야 한다.

CORS 요청방법

단순 요청(Simple requests)

예비 요청 없이 단순히 본 요청만 보낸다.

아래의 조건들 전부를 충족시켜야 한다.
1 . 메서드
GET
HEAD
POST

2 . 헤더
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width

3 . Content-Type
application/x-www-form-urlencoded
multipart/form-data
text/plain

사전 전송 요청(Preflighted requests)

실제 요청을 보내기 전 미리 요청을 보내 안전 여부를 확인하는 것

OPTIONS 메서드를 통해 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청이 전송하기에 안전한지 확인한다.
Cross-site 요청은 유저 데이터에 영향을 줄 수 있기 때문에 이와같이 미리 전송(preflighted)한다.

조건
1 . PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH 중 하나의 메서드
2 . 기본적으로 세팅된 헤더만
3 . Content-Type 헤더에 application/x-www-form-urlencoded, multipart/form-data, text/plain 이외의 값만 허용

인증정보를 포함한 요청 (Credential requests)

HTTP cookies 와 HTTP Authentication 정보를 인식하며 다른 출처 간 통신에서 좀 더 보안을 강화하고 싶을 때 사용하는 방법이다.

옵션은 총 3가지의 값을 사용할 수 있으며, 각 값들이 가지는 의미는 다음과 같다.

옵션 값 설명
same-origin (기본값) 같은 출처 간 요청에만 인증 정보를 담을 수 있다
include 모든 요청에 인증 정보를 담을 수 있다
omit 모든 요청에 인증 정보를 담지 않는다

(이 중 include 옵션을 선택할 경우의 추가조건)
1 . Access-Control-Allow-Origin에는 *를 사용할 수 없으며, 명시적인 URL이어야한다.
2 . 응답 헤더에는 반드시 Access-Control-Allow-Credentials: true가 존재해야한다.

CORS 해결방법

Access-Control-Allow-Origin 세팅하기

그냥 정석대로 서버에서 Access-Control-Allow-Origin 헤더에 알맞은 값을 세팅해주는 것이다.

Webpack Dev Server로 리버스 프록싱하기

웹팩과 webpack-dev-server를 사용하여 자신의 머신에 개발 환경을 구축하게 되는데, 이 라이브러리가 제공하는 프록시 기능을 사용하면 아주 편하게 CORS 정책을 우회할 수 있다.

Request Header

요청 헤더 목록

Origin

cross-site 접근 요청 또는 preflight request의 출처

Access-Control-Request-Method

preflight요청을 할 때 실제 요청에서 어떤 메서드를 사용할 것인지 서버에게 알리기 위해 사용한다.

Access-Control-Request-Headers

preflight요청을 할 때 실제 요청에서 어떤 header를 사용할 것인지 서버에게 알리기 위해 사용한다.

Response Header

응답 헤더 목록

Access-Control-Allow-Origin

브라우저가 해당 origin이 자원에 접근할 수 있도록 허용한다.
또는 *은 credentials이 없는 요청에 한해서 모든 origin에서 접근이 가능하도록 허용한다.

Access-Control-Expose-Headers

브라우저가 액세스할 수있는 서버 화이트리스트 헤더를 허용한다.

Access-Control-Max-Age

얼마나 오랫동안 preflight요청이 캐싱 될 수 있는지를 나타낸다.

Access-Control-Allow-Credentials

Credentials가 true 일 때 요청에 대한 응답이 노출될 수 있는지를 나타내며, preflight요청에 대한 응답의 일부로 사용되는 경우 실제 자격 증명을 사용하여 실제 요청을 수행 할 수 있는지를 나타낸다.
간단한 GET 요청은 preflight되지 않으므로 자격 증명이 있는 리소스를 요청하면 헤더가 리소스와 함께 반환되지 않으면 브라우저에서 응답을 무시하고 웹 콘텐츠로 반환하지 않는다.

Access-Control-Allow-Methods

preflight요청에 대한 대한 응답으로 허용되는 메서드들을 나타낸다.

Access-Control-Allow-Headers

preflight요청에 대한 대한 응답으로 실제 요청 시 사용할 수 있는 HTTP 헤더를 나타낸다.

XSS란?

풀네임은 Cross(X)-Site-Scripting, 해석하면 사이트 간 스크립팅
공격자에 의해 작성된 악성 스크립트가 게시판 등을 통해서 다른 사용자에게 전달되는 보안 취약점을 뜻한다.

XSS의 발생이유

일반적으로, 웹 브라우저는 HTML 코드를 읽어 파싱(Parsing)한 후 렌더링하는 과정을 거친다.
이때 사용자의 입력값이 페이지 내부에 존재하고, HTML tag 형태를 가진다면 파싱하는 과정에서 사용자의 입력값 또한 HTML로 인식하여 생긴다.

XSS 공격방법종류

Stored XSS

가장 흔하게 쓰이는 공격 방식이며, 공격자는 게시글에 악성 스크립트를 삽입 후 서버에 업로드하고, 희생자가 게시글을 클릭할 때 문자열로 저장된 악성 스크립트가 희생자의 브라우저에서 실행 가능한 스크립트로 변환되면서 실행이 되는 특징을 가지고 있다.

Stored XSS 공격 방법

  1. 악성 스크립트를 작성하여 게시글 내용에 입력하고 올린다.
    (예시 : <script>alert(document.cookie)</script>)
  2. 희생자가 그 게시글을 열면, 희생자 브라우저에서 작성한 스크립트가 실행된다.

Reflected XSS

HTTP GET 방식을 이용하여 웹 어플리케이션의 지정된 변수를 사용하여 공격을 하는 방식.
공격자는 스크립트 삽입 시 동작이 되는지 파악한 후, <script>alert(document.cookie)</script> 스크립트를 URL 자체에 삽입한다.
그렇기 때문에 피해자가 링크에 접속하는 순간 XSS 공격이 일어난다는 점에서 Stored XSS 방식과 차이가 있다.

Reflected XSS 공격 방법

  1. HTTP GET 요청으로 입력된 파라미터를 출력해주는 서버를 제작하거나 찾는다.
  2. 악성 스크립트를 작성하여 파라미터에 넣어 URL을 생성한다.
    (예시 : syc.com/chat?msg=<script>alert(document.cookie)</script>)
  3. 만들어진 URL을 희생자에게 보내 클릭을 유도한다.
  4. 희생자가 해당 URL을 클릭하면, 희생자 브라우저에서 작성한 스크립트가 실행된다.

XSS 방어방법

화이트 리스트

보안에 위협이 가지 않는 허용된 문자들을 이용하게 하는 방식

HTML Santizer 라이브러리 사용

입력값을 검사하여 지정한 태그 외에 다른 태그를 모두 제거해주는 화이트 리스트 방식 필터링을 사용한다.

HTML entity 치환

특수문자를 HTML entity로 변환하여 렌더링 과정에서 <,>,(,) 등을 HTML tag로 인식하지 못하게 한다.

profile
말은 사라지지만 기록은 남는다

0개의 댓글