ASP.NET MVC uygulamasında siteler arası Istek forgery (CSRF) saldırılarını önleme

, Mike te son

Siteler arası Istek sahteciliği (CSRF), kötü niyetli bir sitenin kullanıcının şu anda oturum açtığı bir güvenlik açığı olan siteye istek gönderdiği bir saldırıya neden olur

CSRF saldırılarına bir örnek aşağıda verilmiştir:

  1. Kullanıcı, Forms kimlik doğrulaması kullanarak www.example.com oturum açar.

  2. Sunucu, kullanıcının kimliğini doğrular. Sunucudan gelen yanıt bir kimlik doğrulama tanımlama bilgisi içerir.

  3. Oturum açmadan, Kullanıcı kötü amaçlı bir Web sitesi ziyaret ettiğinde. Bu kötü amaçlı site aşağıdaki HTML biçimini içerir:

    <h1>You Are a Winner!</h1>
      <form action="http://example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
      <input type="submit" value="Click Me"/>
    </form>
    

    Form eyleminin kötü amaçlı siteye değil, güvenlik açığı bulunan siteye gönderdiğine dikkat edin. Bu, CSRF 'nin "siteler arası" parçasıdır.

  4. Kullanıcı Gönder düğmesine tıklar. Tarayıcı, istekle kimlik doğrulama tanımlama bilgisini içerir.

  5. İstek, kullanıcının kimlik doğrulama bağlamıyla sunucuda çalışır ve kimliği doğrulanmış bir kullanıcının yapmasına izin verilen her şeyi yapabilir.

Bu örnekte kullanıcının form düğmesine tıklamasa da kötü amaçlı sayfa yalnızca formu otomatik olarak gönderen bir betiği kolayca çalıştırabilir. Üstelik, SSL kullanmak CSRF saldırılarına engel değildir çünkü kötü amaçlı site "https://" isteği gönderebilir.

Genellikle, tarayıcılar tüm ilgili tanımlama bilgilerini hedef Web sitesine gönderdikleri için kimlik bilgilerini kullanan Web sitelerine karşı CSRF saldırıları mümkündür. Ancak, CSRF saldırıları, tanımlama bilgilerini kötüye ile sınırlı değildir. Örneğin, temel ve Özet kimlik doğrulaması da savunmasız olacaktır. Bir Kullanıcı temel veya Özet kimlik doğrulamasıyla oturum açtıktan sonra. tarayıcı, oturum sona erene kadar kimlik bilgilerini otomatik olarak gönderir.

Korunma belirteçleri

ASP.NET MVC, CSRF saldırılarını önlemeye yardımcı olmak için, istek doğrulama belirteçleriolarak da adlandırılan, güvenlik yumuşatma belirteçlerini kullanır.

  1. İstemci, form içeren bir HTML sayfası ister.
  2. Sunucu, yanıtta iki belirteç içerir. Bir belirteç tanımlama bilgisi olarak gönderilir. Diğeri gizli form alanına yerleştirilir. Belirteçler rastgele oluşturulur, böylece bir saldırgan değerleri tahmin edemez.
  3. İstemci formu gönderdiğinde, her iki belirteci sunucuya geri göndermelidir. İstemci tanımlama bilgisi belirtecini tanımlama bilgisi olarak gönderir ve form belirtecini form verileri içine gönderir. (Kullanıcı formu gönderdiğinde bir tarayıcı istemcisi bunu otomatik olarak yapar.)
  4. Bir istek her iki belirteci de içermiyorsa, sunucu isteğe izin vermez.

Gizli form belirtecine sahip HTML biçimine bir örnek aşağıda verilmiştir:

<form action="/Home/Test" method="post">
    <input name="__RequestVerificationToken" type="hidden"   
           value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" />    
    <input type="submit" value="Submit" />
</form>

Kötü amaçlı sayfa, aynı kaynak ilkeleri nedeniyle kullanıcının belirteçlerini okuyamadığı için, karşı koruma belirteçleri çalışır. (Aynı kaynak ilkeleri iki farklı sitede barındırılan belgelerin birbirlerinin içeriğine erişmesini önler. Bu nedenle, kötü amaçlı sayfa example.com 'e istek gönderebilir, ancak yanıtı okuyamıyor.)

CSRF saldırılarını engellemek için, tarayıcının Kullanıcı oturum açtıktan sonra kimlik bilgilerini sessizce gönderdiği kimlik doğrulama protokolleriyle karşı koruma belirteçleri kullanın. Bu, Forms kimlik doğrulaması ve temel ve Özet kimlik doğrulaması gibi protokollerin yanı sıra tanımlama bilgisi tabanlı kimlik doğrulama protokollerini içerir.

Güvenli olmayan Yöntemler (POST, PUT, DELETE) için koruma yumuşatma gerekli olmalıdır. Ayrıca, güvenli yöntemlerin (GET, HEAD) hiç yan etkisi olmadığından emin olun. Üstelik, CORS veya JSONP gibi etki alanları arası desteğini etkinleştirirseniz, GET gibi güvenli yöntemler de CSRF saldırılarına açıktır ve bu da saldırganın potansiyel olarak hassas verileri okumasına olanak tanır.

ASP.NET MVC 'de Anti-forgery belirteçleri

Bir Razor sayfasına korsanlığa karşı koruma belirteçleri eklemek için HtmlHelper. AntiForgeryToken yardımcı yöntemini kullanın:

@using (Html.BeginForm("Manage", "Account")) {
    @Html.AntiForgeryToken()
}

Bu yöntem gizli form alanını ekler ve tanımlama bilgisi belirtecini de ayarlar.

Anti-CSRF ve AJAX

Bir AJAX isteği HTML form verileri değil JSON verisi gönderebildiğinden, form belirteci, AJAX istekleri için bir sorun olabilir. Tek bir çözüm, belirteçleri özel bir HTTP üst bilgisinde göndermektir. Aşağıdaki kod belirteçleri oluşturmak için Razor söz dizimi kullanır ve ardından belirteçleri bir AJAX isteğine ekler. Belirteçler, Antiforgery. GetTokensçağırarak sunucuda oluşturulur.

<script>
    @functions{
        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }

    $.ajax("api/values", {
        type: "post",
        contentType: "application/json",
        data: {  }, // JSON data goes here
        dataType: "json",
        headers: {
            'RequestVerificationToken': '@TokenHeaderValue()'
        }
    });
</script>

İsteği tamamladığınızda, belirteçleri istek başlığından ayıklayın. Ardından, belirteçleri doğrulamak için Antiforgery. Validate metodunu çağırın. Belirteçler geçerli değilse Validate yöntemi bir özel durum oluşturur.

void ValidateRequestHeader(HttpRequestMessage request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders;
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }
    }
    AntiForgery.Validate(cookieToken, formToken);
}