Browser Security

프최's log·2020년 9월 24일
0

study

목록 보기
15/59

브라우저/웹사이트가 위협되는 상황?

 정기적으로 사용하는 웹사이트로 공격을 당하거나 마비되고 혹은 잘못된 정보가 게시되는 경우가 있다. 또 대규모 웹사이트에서는 개인정보가 유출되는 경우도 종종 소식을 접할 수 있다.

이러한 비승인된 접근, 사용, 데이터 파괴 등으로부터 이를 보호하기 위해 행동/실행해하는 것이 바로 '보안(Security)'이다.

우리가 사용하는 브라우저는 Javascript 라는 코드를 구동할 수 있는데, 이 Javascript를 통해 할 수 있는 것들이 존재한다. 브라우저에서 Javascript로 아래와 같은 것을 할 수 있고,

  • ajax call을 해서 api를 호출할 수 있다
  • 다이나믹하게 DOM을 제어할 수 있다
  • 인증정보를 브라우저에 저장할 수 있다.
  • 인증정보를 불러올 수 있다

이를 이용해서 위협적인 상황을 만들 수도 있다.


어떤 공격이 일어날 수 있을까?

 브라우저/웹사이트를 위협하는 것 중 대표적인 것으로는 XSS(CrossSite Scripting)CSRF(CrossSite Request Forgery) 를 들 수 있다. 여기서 두 개 모두 'Cross-Site'를 쓰는데, 서로 다른 웹사이트 사이에서 정보교환이 이뤄지는 식으로 작동한다고 이해하면 된다.
 하지만 여기서는 정보교환이라기보다 공격이라는 방식이 이뤄진다. 사이트의 취약점(vulnerabilities)을 이용해서 해커가 정보를 가로채는 등의 악의적인 행동을 취하는 것을 뜻한다. 이 두 공격 형태를 알아보자.

XSS(CrossSite Scripting)

  XSS는 script 코드 주입(injected script code)를 통해 발생하는데, 보안이 약한 웹 애플리케이션에 대한 웹 기반 공격이다. 이는 클라이언트가 서버를 신뢰하기 때문에 발생하는 이슈로 서버에서 받는 자료는 무조건 정상데이터일거야 라는 믿음이라고 보면 된다.

 이러한 신뢰를 바탕으로 XSS는 GET이나 POST를 통해 서버에 악성 스크립트를 발송하여, 또다른 클라이언트의 웹에 그것을 심어 나타나게 만든다. 간단한 예제로 특정한 팝업메세지를 무한하게 띄울 수 있는 것 이 있다.

XSS 공격

// 막힌 방법들 중 예시
//1.스크립트 태그를 이용한 공격
<script>alert('XSS');</script>
//2.링크 태그를 이용한 공격
<a href="javascript:alert('XSS')">XSS</a>
//3.이벤트 속성을 이용한 공격 등등..
<img src="#" onerror="alert('XSS')">

더 보기

XSS 방어

 이를 방어하기 위해 sanitizing 을 통해 웹사이트 공격에 대한 방어를 취할 수 있다. 코드를 실행하기 위한 지시사항이 포함된 '마크업'을 제거/비활성화 시키는 것이다. 더 쉽게 말하면, 코드 실행이 아닌 있는 그대로 문자열로써 인식하게 하는 것이다.

 아래 예제에서는 현재 주석처리된 스크립트<script>alert("hello")</script>를 XSS 공격으로 생각하면 되고, 서버에서는 그 공격을 막기 위해 &lt;script&gt;alert("hello")&lt;/script&gt 와 같이 스크립트를 문자열로 바꿔둘 수 있다. Result를 보면 알겠지만 '<''&lt'로 바꿔서 출력한다.


CSRF(XSRF) - Cross-Site Request Forgery(요청 위조)

 XSS와 반대로 서버가 클라이언트를 신뢰해서 발생하는 공격이 있는데, 이것이 CSRF이다. 서버가 클라이언트를 신뢰한다는 말이 무엇인지 설명하겠다.

 먼저 A라는 서버가 자신의 고객 'B' 을 인식하려면 어떤 기준을 두고 알아봐야 할까? 그건 '인증정보'이다. 서버에서 발행한 고유의 인증정보를 갖고 있는 'B'는 곧 A 서버의 고객이다. 그런데 해커가 이 'B'의 '인증정보'를 탈취해서 A 서버로 가져가면, A 서버는 해커를 자기 고객인 'B' 라고 인식한다. 왜? A 서버가 발행한 고유의 인증정보를 가지고 있으니까!

예시 시나리오
1. BP 은행의 고객 Alice가 로그인 함
2. Alice가 Bob에게 송금을 요청하는 api가 아래와 같다고 가정(말도 안되지만!!!)
GET http://bulletproofbank.com/transfer.do?recipient=Bob&amount=$500 HTTP/1.1
3. 공격자(Mallory)는 Alice가 자기에게 돈을 보내는 api 요청을 생성
GET http://bulletproofbank.com/transfer.do?recipient=attacker&amount=$500 HTTP/1.1
4. 낚시용 링크 전송(이메일, 쪽지, DM 등)
영화 (불지옥)반도 무료 티켓 2장 선착순!!
5.Alice가 이 링크 안에 인증정보를 입력하고 보내면 공격자(Mallory)에게 $500 이 입금된다.

프레임워크에서는 XSS,CSRF에 대한 방어책이 존재하는지 알아야하므로 Same site cookies 를 이용해서 측정해볼 수 있다.

참고사이트
사이트 간 스크립팅-위키피디아
모던자바스크립트


CORS(Cross-Origin Resouce Sharing)

위를 직역하면 교차 출처 리소스 공유라는 말로 보통 많이 나온다. 브라우저를 보호하기 위한 보안정책으로써, 선택된 리소스에 서로 다른 출처(Origin)가 접근권을 공유할 수 있는 여부를 뜻한다.

출처(Origin)의 구성

출처(Origin) = protocol(scheme) + domain(host, server name) + port(생략 가능) + path(file name) + query(?, &) + fragment(#)


3가지 접근 제어 시나리오

Simple requests(단순요청)

심플 메서드(simple method)와 심플 헤더(simple header), 이 두 가지 조건을 모두 충족하는 요청이다. 특별한 방법을 사용하지 않아도 <form>이나 <script>를 이용해 만들 수 있다. 이 경우, 브라우저는 항상 Origin이라는 헤더를 요청에 추가하고. 이 요청을 받아들이기로 동의했다면 Access-Control-Allow-Origin를 응답에 추가한다. 리소스에 대한 접근을 허용하려면, Access-Control-Allow-Origin 헤더에는 요청의 Origin 헤더에서 전송된 값이 포함되어야 합니다.

1.simple method : GET, POST, HEAD
2.simple header

'simple' 응답 헤더 목록

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

simple’ 응답 헤더 이외의 응답 헤더에 접근하려면 서버에서 Access-Control-Expose-Headers라는 헤더를 보내줘야만 합니다. Access-Control-Expose-Headers엔 자바스크립트 접근을 허용하는 non-simple 헤더 목록이 있고, 각 항목은 콤마(,)로 구분한다.

Preflight request(사전 요청)

Prefilght 요청은 먼저 OPTIONS라는 메서드를 통해, 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청이 전송하기에 안전한지 확인한다. 헤더엔 아래 두 항목이 들어가고, 본문은 비어있습니다.

  • Access-Control-Request-Method
  • Access-Control-Request-Headers
    Access-Control-Request-* 는 OPTIONS 요청시에만 필요

만약 이 요청을 받아들이게 되면, 서버는 본문이 비어있고 상태코드가 200인 응답을 아래와 같은 헤더와 함께 브라우저로 보낸다. 만약 응답이 오지 않으면 '에러'가 발생한다.

  • Access-Control-Allow-Methods – 허용된 메서드 정보
  • Access-Control-Allow-Headers – 허용된 헤더 목록
  • Access-Control-Max-Age – 퍼미션 체크 여부를 몇 초간 캐싱해 놓을지를 명시. 이렇게 퍼미션 정보를 캐싱해 놓으면 브라우저는 일정 기간 동안 preflight 요청을 생략하고 non-simple 요청을 보낸다.

Credentialed Request(자격 증명 요청)

 자격 증명 요청이란 HTTP cookies 와 HTTP Authentication 정보를 인식하는 요청이다. 기본적으로 XMLHttpRequest / Fetch 요청에서 브라우저는 자격증명을 보내지 않는다. 이를 위해 '특정 플래그'를 설정해야 한다.

 fetch 메서드에 자격 증명 정보를 전송하려면 credentials: "include"옵션을 추가해줘야 한다. 이렇게 옵션이 추가되면 url에 대응하는 쿠키가 함께 전송된다.
 만약 서버가 이것을 받아들이기로 동의했다면 Access-Control-Allow-Credentials: true 로 응답하고, 만약 동의하지 않았으면 응답은 무시되고 웹 컨텐츠는 제공되지 않는다.

단, 자격 증명 정보를 전송할 때는 Access-Control-Allow-Origin 에 * 을 수 없다. 정확한 오리진 정보만 명시되어야 어떤 오리진에서 요청이 왔는 지에 대한 정보를 서버가 신뢰할 수 있기 때문이다.

// 자격증명 정보 전송
fetch('https://javascript.info', {
  credentials: "include"
});
// 성공 응답
200 OK
Access-Control-Allow-Origin: https://javascript.info
Access-Control-Allow-Credentials: true

참조사이트
fetch와 Cross-Origin 요청
CORS - MDN
Fetch Standard
CORS는 왜 이렇게 우리를 힘들게 하는걸까?


함께 보면 좋은 참조사이트
★HTTP 트랜잭션 해부

profile
차곡차곡 쌓아가는 나의 개발 기록

0개의 댓글