Stateless (= Sessionless) 인증을 사용할 때 CSRF 토큰이 필요합니까?


125

애플리케이션이 상태 비 저장 인증 (HMAC과 같은 것을 사용)에 의존 할 때 CSRF 보호를 사용해야합니까?

예:

  • 단일 페이지 앱이 있습니다 (그렇지 않으면 각 링크에 토큰을 추가해야합니다 : <a href="...?token=xyz">...</a>.

  • 사용자는 POST /auth. 인증이 성공하면 서버는 일부 토큰을 반환합니다.

  • 토큰은 단일 페이지 앱 내의 일부 변수에 JavaScript를 통해 저장됩니다.

  • 이 토큰은와 같은 제한된 URL에 액세스하는 데 사용됩니다 /admin.

  • 토큰은 항상 HTTP 헤더 내에서 전송됩니다.

  • Http 세션과 쿠키가 없습니다.

내가 이해하는 한, 브라우저가 토큰을 저장하지 않기 때문에 크로스 사이트 공격을 사용할 가능성이 없어야합니다 (?!). 따라서 자동으로 서버로 보낼 수 없습니다 (쿠키를 사용할 때 발생하는 일입니다.) 세션).

내가 뭔가를 놓치고 있습니까?


6
기본 인증에주의하세요. 대부분의 브라우저는 나머지 세션 동안 기본 인증 헤더를 자동으로 보냅니다. 이로 인해 기본 인증이 쿠키 인증만큼 CSRF에 취약해질 수 있습니다.
phylae

답변:


159

인증에 쿠키를 사용 하지 않는 CSRF +에 대한 정보를 찾았습니다 .

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "쿠키에 의존하지 않기 때문에 교차 사이트 요청으로부터 보호 할 필요가 없습니다."

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    "쿠키 방식으로 내려 가면 사이트 간 요청을 피하기 위해 CSRF를 수행해야합니다. 당신이 보게 될 JWT를 사용할 때 잊어 버려. "
    (JWT = 상태 비 저장 앱을위한 토큰 기반 인증 인 Json 웹 토큰)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    "CSRF 취약성 위험없이 인증을 수행하는 가장 쉬운 방법은 단순히 쿠키를 사용하여 사용자를 식별하지 않는 것입니다. "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "CSRF의 가장 큰 문제는 쿠키가 이러한 유형의 공격에 대한 방어를 전혀 제공하지 않는다는 것입니다. 쿠키 인증을 사용하는 경우 CSRF로부터 보호하기 위해 추가 조치를 취해야합니다. 취할 수있는 가장 기본적인 예방 조치는 애플리케이션이 GET 요청에 대한 응답으로 어떠한 부작용도 수행하지 않도록하는 것입니다. "

인증을 위해 쿠키를 사용하지 않는 경우 CSRF 보호가 필요하지 않다는 더 많은 페이지가 있습니다. 물론 다른 모든 것에 쿠키를 사용할 수 있지만 내부에 이와 같은 것을 저장 하지 마십시오session_id .


사용자를 기억해야하는 경우 다음 두 가지 옵션이 있습니다.

  1. localStorage: 브라우저 내 키-값 저장소입니다. 저장된 데이터는 사용자가 브라우저 창을 닫은 후에도 사용할 수 있습니다. 모든 사이트가 자체 저장 공간을 확보하기 때문에 다른 웹 사이트에서 데이터에 액세스 할 수 없습니다.

  2. sessionStorage: 또한 브라우저 내 데이터 저장소입니다. 차이점은 사용자가 브라우저 창을 닫으면 데이터가 삭제된다는 것입니다. 그러나 웹앱이 여러 페이지로 구성된 경우 여전히 유용합니다. 따라서 다음을 수행 할 수 있습니다.

    • 사용자가 로그인하면 토큰을 sessionStorage
    • 사용자가 링크를 클릭하면 새 페이지가로드됩니다 (= 실제 링크, 자바 스크립트 콘텐츠 대체 없음).
    • 여전히 토큰에 액세스 할 수 있습니다. sessionStorage
    • 로그 아웃하려면 수동으로 토큰을 삭제 sessionStorage하거나 사용자가 브라우저 창을 닫을 때까지 기다리면 저장된 모든 데이터가 지워집니다.

(둘 다 여기를보세요 : http://www.w3schools.com/html/html5_webstorage.asp )


토큰 인증에 대한 공식 표준이 있습니까?

JWT (Json Web Token) : 아직 초안이라고 생각하지만 이미 많은 사람들이 사용하고 있으며 개념은 간단하고 안전 해 보입니다. (IETF : http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
사용 가능한 많은 프레임 워크를위한 라이브러리도 있습니다. 그것을 위해 구글!


37
CSRF에 대한 훌륭한 요약! 토큰을 localStorage 또는 sessionStorage에 저장하는 것은 XSS 공격에 취약하며 페이지의 스크립트로 데이터를 볼 수 있습니다. 따라서 CDN에서 제공되는 손상된 스크립트가 있거나 사용자 중 하나에 악성 코드가있는 경우 JS 라이브러리는 해당 저장소에서 토큰을 훔칠 수 있습니다. 참조 : stormpath.com/blog/… 가장 안전한 접근 방식은 쿠키에 JWT + CSRF 토큰을 저장 한 다음 CSRF 토큰이 포함 된 계산 된 JWT를 요청 헤더에 배치하는 것입니다.
Aaron Gray

"당신이 취할 수있는 가장 기본적인 예방 조치는 애플리케이션이 GET 요청에 대한 응답으로 어떠한 부작용도 수행하지 않도록하는 것입니다." CSRF 공격이 POST 요청을 위조 할 수 있습니까?
Costa

서버 측 애플리케이션에 따라 가능할 수 있습니다. 같은 것을 사용하는 웹 프레임 워크가 있습니다 http://.../someRestResource?method=POST. 따라서 기본적으로 GET요청이지만 서버 애플리케이션 은 HTTP 헤더 대신 매개 변수 POST를 사용하도록 구성 되었기 때문에 요청 으로 해석합니다 method. ...일반적인 웹 브라우저와 관련하여 Same-Origin-Policy를 적용하고 GET외부 서버에 대한 요청 만 실행 합니다. 비록 실행할 수있을 POST요청을 하면 웹 브라우저는 해당 웹 표준 (버그, 악성 코드)를 적용하지 않습니다.
Benjamin M

1
에 추가 Server Side App: 일반 브라우저에서는이를 허용하지 않기 때문에 요청 본문을 보낼 수 없습니다. 그러나 서버 앱이을 method=POST허용 body={someJson}하는 경우 기본 요청 본문을 재정의 할 수도 있습니다 . 그것은 정말 나쁜 API 디자인이고 매우 위험합니다. 서버 앱이 허용 http://...?method=POST&body={someJson}한다면 그곳에서 무엇을했고 왜 그랬는지, 그리고 그것이 필요한지 정말로 지나치게 생각해야합니다. ( 필요 하지 않은 경우의 99,9999 % ). 또한 브라우저는 이러한 방식으로 몇 킬로바이트 만 전송할 수 있습니다.
Benjamin M

@BenjaminM은 동일한 출처 정책이 자바 스크립트 코드가 결과에 액세스하는 것을 막기 만하므로 요청이 "차단"되는 동안 실제로 서버에 도달합니다. jsbin.com/mewaxikuqo/edit?html,js,output 저는 이것을 firefox에서만 테스트했습니다. 하지만 개발 도구를 열고 "교차 출처 요청 차단"이 발생하더라도 원격 서버에서 실제로 전체 요청을 볼 수 있습니다. 그렇기 때문에 모든 POST 요청에 대해 토큰 또는 사용자 지정 헤더 (가능하면 둘 다)가 있어야합니다.
Yoni Jah

59

TL; DR

쿠키없이 JWT를 사용하면 CSRF 토큰이 필요하지 않습니다.하지만! JWT를 session / localStorage에 저장하면 사이트에 XSS 취약성이있는 경우 JWT와 사용자의 신원이 노출됩니다 (일반적으로). csrfTokenJWT에 키 를 추가하고 securehttp-only속성이 설정된 쿠키에 JWT를 저장하는 것이 좋습니다 .

자세한 내용은 https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage에 대한 좋은 설명과 함께이 기사를 읽으십시오.

xsrfToken JWT 클레임을 포함하여이 CSRF 보호를 상태 비 저장으로 만들 수 있습니다.

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "tom@andromeda.com", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

따라서 csrfToken을 localStorage / sessionStorage 및 JWT 자체 (http 전용 및 보안 쿠키에 저장 됨)에 저장해야합니다. 그런 다음 csrf 보호를 위해 JWT의 csrf 토큰이 제출 된 csrf-token 헤더와 일치하는지 확인합니다.


2
사용자의 API 인증 중에 하나의 csrf 토큰 사용을 면제해야합니까?
user805981

3
a) http 전용이 아닌 쿠키를 사용하거나 b) CSRF 토큰을 로컬 저장소에 저장하는 CSRF 완화는 XSS에 취약하다는 점을 지적 할 가치가 있습니다 (다른 사람들도 소스 링크의 주석에서 언급했듯이). 이는 제시된 접근 방식이 XSS를 사용하는 공격자로부터 JWT 비밀을 유지하는 데 도움이 될 수 있지만, 공격자는 유효한 JWT를 제공 할 수 있기 때문에 여전히 API에서 악의적 인 요청을 실행할 수 있습니다 (쿠키를 통해 브라우저 감사합니다). 및 CSRF 토큰 (로컬 저장소 / 쿠키에서 삽입 된 JS를 통해 읽음).
요하네스 루돌프

1
실제로 CSRF 토큰조차도이 수준의 XSS에서 사용자를 보호 할 수 없습니다. 공격자가 localStorage에 액세스 할 수 있다고 가정하기 때문입니다. 현재 액세스 할 수있는 유일한 방법은 스크립트 수준 액세스 권한을 갖는 것입니다. .
itsnotvalid

1
@JohannesRudolph가 말한 것이 아닌가요? CSRF 토큰을 웹 저장소 / http 전용이 아닌 쿠키에 저장하자마자 JS를 통해 액세스 할 수 있기 때문에 XSS 공격의 범위가 증가합니다.
adam-beck

1
여기에 완전한 전문가는 아니지만 처음에 그랬던 것처럼 여전히 XSS에 노출되어 있다면 추가하는 것이 더 나은 부분 확실하지 않습니다 . 아마도 공격자가 CSRF 토큰을 확보하는 것은 약간 (?) 더 복잡 할 수 있지만 결국 JWT 토큰을 실제로 알지 못하더라도 여전히 사용자를 대신하여 요청을 수행 할 수 있습니다. 그 맞습니까? 감사합니다
superjos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.