JS 소스 정책 및 CSRF 자세히 보기

개요


본고는 주로 세 가지 키워드와 관련된다.
  • 동원 정책(Same-origin policy, 약칭 SOP)
  • 크로스사이트 요청 위조(Cross-site request forgery, 약칭 CSRF)
  • 크로스 오리진 리소스 공유(Cross-Origin Resource Sharing, 약칭 CORS)
  • 소스 정책 SOP


    동원


    먼저 동원이 무엇인지 설명한다. 프로토콜, 도메인 이름, 포트는 모두 같고 동원이다.
    url
    동원
    https://niconico.com
    기준
    https://niconico.com/spirit
    o
    https://sub.niconico.com/spirit
    x
    http://niconico.com/spirit
    x
    https://niconico.com:8080/spirit
    x

    제한


    도메인 간 문제가 발생하는 이유는 바로 SOP의 여러 가지 제한 때문입니다.그런데 구체적으로 뭘 제한했죠?
    만약 SOP가'비동원 자원의 획득을 제한한다'고 말한다면, 이것은 옳지 않다. 가장 간단한 예는 그림, css, js 파일 등 자원을 인용할 때 크로스오버를 허용하는 것이다.
    만약 당신이 SOP가'크로스 요청 금지'라고 말한다면, 이것도 옳지 않다. 본질적으로 SOP는 크로스 요청을 금지하는 것이 아니라 요청 후에 요청의 응답을 가로막는 것이다.이렇게 하면 뒤에 나오는 CSRF를 불러일으킬 수 있습니다.
    사실 SOP는 단일한 정의가 아니라 상황에 따라 해석이 다르다.
  • 쿠키, DOM, JavaScript의 이름 영역을 제한합니다
  • iframe, 사진 등 각종 자원의 내용 조작을 제한한다
  • aax 요청을 제한하는 것은 정확하게 말하면 조작을 제한하는 aax 응답 결과이고 본질적으로 앞의 것은 같다
  • 다음은 실제 응용 프로그램에서 만날 수 있는 세 가지 예입니다.
  • aax를 사용하여 다른 크로스 도메인 API를 요청하는 가장 흔히 볼 수 있는 상황, 전방 초보자의 악몽
  • iframe는 부모 페이지와 교류하여 출현률이 비교적 낮고 해결 방법도 잘 알고 있다
  • 크로스오버 이미지(예를 들어 에서 유래한 것)를 조작하면 canvas에서 그림을 조작할 때 이 문제가 발생합니다
  • SOP가 없는 경우:
  • 브라우저가 몇 개의tab를 열면 데이터가 유출된다
  • 당신은 iframe로 은행 사이트를 열면 사이트의 내용을 마음대로 읽을 수 있고 사용자가 입력한 내용을 얻을 수 있습니다
  • 더욱 제멋대로 CSRF를 진행한다
  • 크로스 오버


    SOP는 보안을 가져오는 동시에 어느 정도의 번거로움을 가져올 수 있다. 왜냐하면 때로는 크로스오버의 수요가 있기 때문이다.크로스오버를 하는 방안은 편폭이 제한되고 인터넷에도 관련 글이 많기 때문에 여기서 크로스오버를 해결하는 방안을 전개하지 않고 몇 가지 키워드만 제시한다.
    aax
  • jsONP 사용
  • 백엔드에서 CORS 구성
  • 백엔드 역방향 에이전트
  • iframe의 경우
  • 위치 사용.hash나 윈도우.name 정보 교류
  • postMessage 사용
  • 크로스 스테이션에서 CSRF 위조 요청


    약술하다


    CSRF(Cross-site request forgery)는 크로스 스테이션에서 위조를 요청하는 흔한 공격 방식이다.A 사이트가 정상적으로 로그인한 후에 쿠키가 정상적으로 저장되고 다른 사이트 B가 어떤 방식으로 A 사이트 인터페이스를 호출하여 조작하는 것을 말한다. A의 인터페이스는 요청할 때 자동으로 쿠키를 가져온다.
    위에서 말한 바와 같이 SOP는 htmltag를 통해 자원을 불러올 수 있고 SOP는 인터페이스 요청을 막지 않고 요청 결과를 차단한다. CSRF는 이 두 가지 이득을 차지한다.
    그래서 SOP는 CSRF를 방지하는 방법이 될 수 없습니다.
    GET 요청에 대해 에 직접 넣으면 쥐도 새도 모르게 크로스 인터페이스를 요청할 수 있습니다.
    POST 요청의 경우 form을 사용하여 제출하는 경우가 많습니다.
    
    <form action="<nowiki>http://bank.com/transfer.do</nowiki>" method="POST">
      <input type="hidden" name="acct" value="MARIA" />
      <input type="hidden" name="amount" value="100000" />
      <input type="submit" value="View my pictures" />
    </form>
    결국 이 두 가지 방법이 크로스오버를 하지 않는 것은 요청이 html로 제어되기 때문에 js로 직접 조작하여 얻은 결과를 얻을 수 없습니다.

    SOP 및 ajax


    aax 요청에 대해 데이터를 얻은 후에 당신은 제멋대로 js 조작을 할 수 있습니다.이때 동원 정책은 응답을 막지만 요청을 한다.응답 차단을 실행하는 것은 백엔드 프로그램이 아니라 브라우저이기 때문이다.사실 당신의 요청은 서버에 보냈고 결과를 되돌려 주었지만, 보안 정책 때문에 브라우저에서 js 작업을 계속할 수 없습니다. 그래서 익숙한 blocked by CORS 정책: No'Access-Control-Allow-Origin'header is present on the requested resource...
    그래서 다시 한 번 강조하지만 동원 전략은 CSRF를 방지하는 방법이 될 수 없다.
    그러나 CSRF를 방지할 수 있는 예외는 여전히 있습니다. 브라우저가 모든 요청을 성공적으로 보내는 것은 아닙니다. 상술한 상황은 간단한 요청에 한정됩니다. 관련 지식은 아래의CORS 1절에서 상세하게 설명합니다.

    CSRF 대책


    SOP가 CSRF에 의해 이득을 보았는데, 그것은 정말 옳은 곳이 하나도 없는 것입니까?
    아니요.SOP가 쿠키의 명칭 구역을 제한한 것을 기억하십니까? 요청이 자동으로 쿠키를 가져오지만 공격자는 어쨌든 쿠키의 내용 자체를 가져올 수 없습니다.
    그래서 CSRF에 이런 생각을 해야 한다. 동시에 하나의 토큰을 쿠키에 쓰고 요청을 할 때query, body 또는 헤더를 통해 이 토큰을 가져가야 한다.요청이 서버에 도착하면 이 token을 확인하십시오. 만약 정확하다면 쿠키의 본역에서 보내는 요청을 볼 수 있을 것입니다. CSRF는 이 점을 할 수 없습니다.(이 방법은 앞뒤로 분리하는 데 사용되며, 뒷면 렌더링은dom에 직접 쓸 수 있습니다)
    예제 코드는 다음과 같습니다.
    
    var csrftoken = Cookies.get('csrfToken')
    
    function csrfSafeMethod(method) {
      // these HTTP methods do not require CSRF protection
      return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method)
    }
    $.ajaxSetup({
      beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
          xhr.setRequestHeader('x-csrf-token', csrftoken)
        }
      },
    })

    도메인 간 자원 공유 CORS


    크로스 도메인은 브라우저 제한이지만 서버가 CORS 관련 설정을 설정하면 서버로 돌아가는 정보 헤더에 Access-Control-Allow-Origin을 추가하고 브라우저가 이 필드의 값이 현재 원본과 일치하는 것을 보면 크로스 도메인 제한을 해제합니다.
    HTTP/1.1 200 OK
    Date: Sun, 24 Apr 2016 12:43:39 GMT
    Server: Apache
    Access-Control-Allow-Origin: http://www.acceptmeplease.com
    Keep-Alive: timeout=2, max=100
    Connection: Keep-Alive
    Content-Type: application/xml
    Content-Length: 423
    CORS의 경우 요청은 두 가지로 나뉩니다.

    간단한 요청

  • 요청 방법은 GET, POST 또는 HEAD를 사용합니다
  • Content-Type은 application/x-www-form-urlencoded, multipart/form-data 또는 text/plain으로 설정됩니다
  • 위의 두 조건에 부합되는 것은 모두 CORS의 간단한 요청이다.간단한 요청은 서버에 직접 전송되어 CSRF를 생성합니다.

    사전 검사 요청


    간단한 요청 조건에 맞지 않는 요청은 미리 확인 요청(Preflight Request)을 보내야 합니다.브라우저는 실제 요청 전에 OPTION 메서드의 요청을 보내서 서버에 현재 소스가 CORS 목표에 부합하는지 묻고 통과된 후에 정식 요청을 보냅니다.
    예를 들어 application/json을 사용하여 전달된 POST 요청은 간단하지 않은 요청으로 사전 검사에서 차단됩니다.
    PUT 메서드를 사용하여 요청하는 경우에도 사전 확인 요청이 전송됩니다.
    위에서 언급한 CSRF를 방지할 수 있는 예외는 바로 사전 검사 요청을 가리킨다.도메인 전체에서 사전 검사를 요청해도 실제 요청이 전송되지 않으므로 CSRF가 성공하지 못합니다.

    CORS 및 쿠키


    같은 도메인과 달리 도메인 전체에 사용되는 CORS 요청은 기본적으로 쿠키와 HTTP 인증 정보를 보내지 않으며, 앞뒤로 설정에서 요청을 설정할 때 쿠키를 가져가야 합니다.
    이것이 바로 CORS 요청을 할 때 axios가 withCredentials:true를 설정해야 하는 이유입니다.
    다음은 노드입니다.js의 백그라운드 koa 프레임워크의 CORS 설정:
    
    /**
     * CORS middleware
     *
     * @param {Object} [options]
     *  - {String|Function(ctx)} origin `Access-Control-Allow-Origin`, default is request Origin header
     *  - {String|Array} allowMethods `Access-Control-Allow-Methods`, default is 'GET,HEAD,PUT,POST,DELETE,PATCH'
     *  - {String|Array} exposeHeaders `Access-Control-Expose-Headers`
     *  - {String|Array} allowHeaders `Access-Control-Allow-Headers`
     *  - {String|Number} maxAge `Access-Control-Max-Age` in seconds
     *  - {Boolean} credentials `Access-Control-Allow-Credentials`
     *  - {Boolean} keepHeadersOnError Add set headers to `err.header` if an error is thrown
     * @return {Function} cors middleware
     * @api public
     */
    다음은 JS 동원 전략과 CSRF에 대한 상세한 내용입니다. JS 동원 전략과 CSRF에 대한 더 많은 자료는 저희의 다른 관련 글을 주목해 주십시오!

    좋은 웹페이지 즐겨찾기