CSRF 토큰이란 무엇입니까? 그 중요성은 무엇이며 어떻게 작동합니까?
저는 응용 프로그램을 작성 중이며 (Django, 그렇게 발생합니다) 실제로 "CSRF 토큰"이 무엇인지, 그리고 데이터를 어떻게 보호하는지에 대한 아이디어를 원합니다. CSRF 토큰을 사용하지 않으면 게시 데이터가 안전하지 않습니까?
간단한 단어로 된 CSRF (Cross-Site Request Forgery)
- 현재 온라인 뱅킹에 로그인했다고 가정합니다.
www.mybank.com
- 에서 송금
mybank.com
하면 (개념 상) 양식이 요청 된다고 가정합니다http://www.mybank.com/transfer?to=<SomeAccountnumber>;amount=<SomeAmount>
. (귀하의 계정 번호는 로그인에 의해 암시되기 때문에 필요하지 않습니다.) www.cute-cat-pictures.org
악성 사이트임을 모르고을 방문 합니다.- 해당 사이트의 소유자가 위 요청의 형식을 알고 (쉬운!) 로그인 한 것으로 올바르게 추측하면
mybank.com
(운이 필요합니다!), 페이지에 다음과 같은 요청을 포함 할 수 있습니다http://www.mybank.com/transfer?to=123456;amount=10000
(123456
케이맨 제도 계정 번호는 어디에 있습니까? ) 그리고10000
당신이 이전에 생각했던되는 양입니다 기쁜 ) 소유하기는. - 당신 이 검색 할
www.cute-cat-pictures.org
수 있도록 페이지를 사용자의 브라우저가 해당 요청을 만들 것입니다. - 귀하의 은행은이 요청의 출처를 인식 할 수 없습니다 : 귀하의 웹 브라우저가 귀하의
www.mybank.com
쿠키와 함께 요청을 보내며 완벽하게 합법적으로 보일 것입니다. 돈이 간다!
이것은 CSRF 토큰이없는 세상 입니다.
이제 더 나은 하나 와 CSRF는 토큰 :
- 전송 요청은 세 번째 인수 인으로 확장됩니다
http://www.mybank.com/transfer?to=123456;amount=10000;token=31415926535897932384626433832795028841971
. - 이 토큰은
mybank.com
귀하에게 제공 할 때 자체 웹 페이지에 포함 되는 거대하고 추측하기 불가능한 임의의 숫자입니다 . 그것은이다 다른 그들이 누구에 모든 페이지를 제공 할 때마다. - 공격자는 토큰을 추측 할 수없고 웹 브라우저가이를 포기하도록 설득 할 수 없습니다 (브라우저가 올바르게 작동하는 경우 ...). 따라서 공격자는 유효한 요청을 만들 수 없습니다 . 잘못된 토큰 (또는 토큰 없음)은에서 거부합니다
www.mybank.com
.
결과 : 10000
화폐 단위를 유지합니다 . 그 중 일부를 Wikipedia에 기부하는 것이 좋습니다.
(귀하의 마일리지가 다를 수 있습니다.)
읽을만한 가치가있는 의견에서 편집하십시오.
www.cute-cat-pictures.org
일반적으로 스크립트 www.mybank.com
는 HTTP 액세스 제어로 인해 anti-CSRF 토큰에 액세스 할 수 없습니다. 이 메모는 Access-Control-Allow-Origin: *
다른 웹 사이트의 API를 사용할 수 없기 때문에 그것이 무엇인지 알지 못하고 모든 웹 사이트 응답에 대해 부당하게 헤더 를 보내는 일부 사람들에게 중요합니다 .
예, 게시 데이터는 안전합니다. 그러나 그 데이터의 출처는 아닙니다. 이렇게하면 누군가가 JS 사용자를 속여서 공격자의 웹 페이지를 탐색하면서 사이트에 로그인하도록 할 수 있습니다.
이를 방지하기 위해 django는 쿠키와 양식 데이터 모두에서 임의의 키를 보냅니다. 그런 다음 사용자가 POST를 수행하면 두 키가 동일한 지 확인합니다. 사용자를 속이는 경우 제 3 자 웹 사이트가 사이트의 쿠키를 가져올 수 없으므로 인증 오류가 발생합니다.
사이트는 양식 페이지를 만들 때 고유 한 토큰을 생성합니다. 이 토큰은 서버에 데이터를 다시 게시 / 가져 오는 데 필요합니다.
토큰은 사이트에서 생성되고 양식이있는 페이지가 생성 될 때만 제공되므로 일부 다른 사이트는 양식을 모방 할 수 없습니다. 토큰이 없어 사이트에 게시 할 수 없습니다.
Cloud Under 블로그에는 CSRF 토큰에 대한 좋은 설명이 있습니다.
a.com에서 호스팅되는 단순화 된 Twitter와 같은 웹 사이트가 있다고 상상해보십시오. 로그인 한 사용자는 POST 요청으로 서버에 전송되고 제출 버튼을 누를 때 게시되는 양식에 일부 텍스트 (트윗)를 입력 할 수 있습니다. 서버에서 사용자는 고유 한 세션 ID를 포함하는 쿠키로 식별되므로 서버는 트윗을 게시 한 사람을 알고 있습니다.
양식은 다음과 같이 간단 할 수 있습니다.
<form action="http://a.com/tweet" method="POST"> <input type="text" name="tweet"> <input type="submit"> </form>
이제 악의적 인 사람이이 양식을 자신의 악성 웹 사이트에 복사하여 붙여 넣는다 고 가정 해 보겠습니다. b.com이라고 가정 해 보겠습니다. 양식은 여전히 작동합니다. 사용자가 귀하의 Twitter에 로그인되어있는 한 (즉, a.com에 대해 유효한 세션 쿠키가 있음) POST 요청은
http://a.com/tweet
사용자가 제출 버튼을 클릭 할 때 평소와 같이 전송 되고 처리됩니다.지금까지 사용자가 양식이 정확히 무엇을하는지 알고있는 한 큰 문제는 아니지만, 나쁜 사람이 다음과 같이 양식을 수정하면 어떻게 될까요?
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="tweet" value="Buy great products at http://b.com/#iambad"> <input type="submit" value="Click to win!"> </form>
이제 사용자 중 한 명이 악당의 웹 사이트에 접속하여 "이기려면 클릭하세요!" 버튼을 클릭하면 양식이 웹 사이트에 제출되고 사용자는 쿠키의 세션 ID로 올바르게 식별되며 숨겨진 트윗이 게시됩니다.
If our bad guy was even worse, he would make the innocent user submit this form as soon they open his web page using JavaScript, maybe even completely hidden away in an invisible iframe. This basically is cross-site request forgery.
A form can easily be submitted from everywhere to everywhere. Generally that’s a common feature, but there are many more cases where it’s important to only allow a form being submitted from the domain where it belongs to.
Things are even worse if your web application doesn’t distinguish between POST and GET requests (e.g. in PHP by using $_REQUEST instead of $_POST). Don’t do that! Data altering requests could be submitted as easy as
<img src="http://a.com/tweet?tweet=This+is+really+bad">
, embedded in a malicious website or even an email.How do I make sure a form can only be submitted from my own website? This is where the CSRF token comes in. A CSRF token is a random, hard-to-guess string. On a page with a form you want to protect, the server would generate a random string, the CSRF token, add it to the form as a hidden field and also remember it somehow, either by storing it in the session or by setting a cookie containing the value. Now the form would look like this:
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn"> <input type="text" name="tweet"> <input type="submit"> </form>
When the user submits the form, the server simply has to compare the value of the posted field csrf-token (the name doesn’t matter) with the CSRF token remembered by the server. If both strings are equal, the server may continue to process the form. Otherwise the server should immediately stop processing the form and respond with an error.
Why does this work? There are several reasons why the bad guy from our example above is unable to obtain the CSRF token:
Copying the static source code from our page to a different website would be useless, because the value of the hidden field changes with each user. Without the bad guy’s website knowing the current user’s CSRF token your server would always reject the POST request.
Because the bad guy’s malicious page is loaded by your user’s browser from a different domain (b.com instead of a.com), the bad guy has no chance to code a JavaScript, that loads the content and therefore our user’s current CSRF token from your website. That is because web browsers don’t allow cross-domain AJAX requests by default.
The bad guy is also unable to access the cookie set by your server, because the domains wouldn’t match.
When should I protect against cross-site request forgery? If you can ensure that you don’t mix up GET, POST and other request methods as described above, a good start would be to protect all POST requests by default.
You don’t have to protect PUT and DELETE requests, because as explained above, a standard HTML form cannot be submitted by a browser using those methods.
JavaScript on the other hand can indeed make other types of requests, e.g. using jQuery’s $.ajax() function, but remember, for AJAX requests to work the domains must match (as long as you don’t explicitly configure your web server otherwise).
This means, often you do not even have to add a CSRF token to AJAX requests, even if they are POST requests, but you will have to make sure that you only bypass the CSRF check in your web application if the POST request is actually an AJAX request. You can do that by looking for the presence of a header like X-Requested-With, which AJAX requests usually include. You could also set another custom header and check for its presence on the server side. That’s safe, because a browser would not add custom headers to a regular HTML form submission (see above), so no chance for Mr Bad Guy to simulate this behaviour with a form.
If you’re in doubt about AJAX requests, because for some reason you cannot check for a header like X-Requested-With, simply pass the generated CSRF token to your JavaScript and add the token to the AJAX request. There are several ways of doing this; either add it to the payload just like a regular HTML form would, or add a custom header to the AJAX request. As long as your server knows where to look for it in an incoming request and is able to compare it to the original value it remembers from the session or cookie, you’re sorted.
The root of it all is to make sure that the requests are coming from the actual users of the site. A csrf token is generated for the forms and Must be tied to the user's sessions. It is used to send requests to the server, in which the token validates them. This is one way of protecting against csrf, another would be checking the referrer header.
'Development Tip' 카테고리의 다른 글
Eclipse / Java 코드 완성이 작동하지 않음 (0) | 2020.10.03 |
---|---|
NS 접두사는 무엇을 의미합니까? (0) | 2020.10.03 |
23,148,855,308,184,500은 마법의 숫자입니까, 아니면 순전히 기회입니까? (0) | 2020.10.03 |
JSON의 여러 줄 문자열 (0) | 2020.10.03 |
Windows Forms 응용 프로그램에서 응용 프로그램 설정을 저장하는 방법은 무엇입니까? (0) | 2020.10.03 |