Durumsuz (= Oturumsuz) Kimlik Doğrulaması kullanılırken CSRF Belirteci gerekli mi?


125

Uygulama durum bilgisi içermeyen kimlik doğrulamaya dayandığında (HMAC gibi bir şey kullanarak) CSRF Koruması kullanmak gerekli midir?

Misal:

  • Biz tek bir sayfa uygulaması var (aksi takdirde biz her linke belirteci eklemek zorunda: <a href="...?token=xyz">...</a>.

  • Kullanıcı kullanarak kimliğini doğrular POST /auth. Başarılı bir kimlik doğrulamasında sunucu bazı belirteçler döndürür.

  • Jeton, tek sayfalı uygulama içindeki bazı değişkenlerde JavaScript aracılığıyla depolanacaktır.

  • Bu simge, gibi kısıtlanmış URL'lere erişmek için kullanılacaktır /admin.

  • Belirteç her zaman HTTP Başlıkları içinde iletilecektir.

  • Http Oturumu YOK ve Çerez YOK.

Anladığım kadarıyla, siteler arası saldırıları kullanma imkanı olmamalı (?!), çünkü tarayıcı jetonu saklamayacaktır ve bu nedenle sunucuya otomatik olarak gönderemez (Çerezler kullanılırken böyle olur / Oturum, toplantı, celse).

Bir şey mi kaçırıyorum?


6
Temel Kimlik Doğrulama konusunda dikkatli olun. Çoğu tarayıcı, oturumun geri kalanı için otomatik olarak temel kimlik doğrulama başlıklarını gönderir. Bu, temel kimlik doğrulamasını, çerez kimlik doğrulaması olarak CSRF'ye karşı savunmasız hale getirebilir.
phylae

Yanıtlar:


159

Kimlik doğrulama için hiçbir tanımlama bilgisi kullanmayan CSRF + hakkında bazı bilgiler buldum :

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "çerezlere güvenmediğiniz için, siteler arası isteklere karşı koruma sağlamanız gerekmez"

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    "Çerezler yoluna gidersek, siteler arası istekleri önlemek için gerçekten CSRF yapmanız gerekir. Bu, yapabileceğimiz bir şeydir Göreceğiniz gibi JWT'yi kullanırken unutun. "
    (JWT = Json Web Token, durum bilgisi olmayan uygulamalar için Token tabanlı bir kimlik doğrulama)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    "CSRF güvenlik açıklarını riske atmadan kimlik doğrulama yapmanın en kolay yolu, kullanıcıyı tanımlamak için tanımlama bilgilerini kullanmaktan kaçınmaktır "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "CSRF ile ilgili en büyük sorun, çerezlerin bu tür saldırılara karşı kesinlikle hiçbir savunma sağlamamasıdır. Çerez kimlik doğrulaması kullanıyorsanız Ayrıca CSRF'ye karşı koruma sağlamak için ek önlemler almalısınız. Alabileceğiniz en temel önlem, uygulamanızın GET isteklerine yanıt olarak hiçbir zaman herhangi bir yan etki yapmadığından emin olmaktır. "

Kimlik doğrulama için tanımlama bilgileri kullanmıyorsanız, herhangi bir CSRF korumasına ihtiyacınız olmadığını belirten çok daha fazla sayfa var. Elbette, diğer her şey için çerezleri kullanmaya devam edebilirsiniz, ancak bunun gibi şeyleri saklamaktan kaçınınsession_id .


Kullanıcıyı hatırlamanız gerekiyorsa 2 seçenek vardır:

  1. localStorage: Tarayıcı içi bir anahtar / değer deposu. Saklanan veriler, kullanıcı tarayıcı penceresini kapattıktan sonra bile kullanılabilir olacaktır. Verilere diğer web siteleri tarafından erişilemez, çünkü her site kendi depolama alanına sahiptir.

  2. sessionStorage: Ayrıca bir tarayıcı içi veri deposu. Aradaki fark şudur: Kullanıcı tarayıcı penceresini kapattığında veriler silinir. Ancak, web uygulamanız birden çok sayfadan oluşuyorsa, yine de yararlıdır. Böylece şunları yapabilirsiniz:

    • Kullanıcı oturum açar, ardından jetonu depolarsınız sessionStorage
    • Kullanıcı yeni bir sayfa yükleyen bir bağlantıyı tıklar (= gerçek bir bağlantı ve javascript içeriği değiştirmez)
    • Jetona şu adresten hala erişebilirsiniz: sessionStorage
    • Oturumu sessionStoragekapatmak için jetonu el ile silebilir veya kullanıcının tarayıcı penceresini kapatmasını bekleyebilir, böylece depolanan tüm verileri temizleyebilirsiniz.

(her ikisi için buraya bir göz atın: http://www.w3schools.com/html/html5_webstorage.asp )


Simge kimlik doğrulaması için herhangi bir resmi standart var mı?

JWT (Json Web Token): Hala bir taslak olduğunu düşünüyorum, ancak zaten birçok kişi tarafından kullanılıyor ve konsept basit ve güvenli görünüyor. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
Ayrıca birçok çerçeve için kütüphaneler de mevcuttur. Sadece bunun için google!


37
CSRF hakkında harika bir özet! Belirteçlerinizi localStorage veya sessionStorage'da depolamanın XSS saldırılarına karşı savunmasız olduğunu ve verilerin sayfadaki komut dosyaları tarafından görüntülenebileceğini - bu nedenle, bir CDN'den sunulan güvenliği ihlal edilmiş bir komut dosyanız varsa veya sisteminizden birinde kötü amaçlı kod varsa JS kitaplıkları, jetonu bu depolama yerlerinden çalabilirler. Bakınız: stormpath.com/blog/… Bence en güvenli yaklaşım, çerezde bir JWT + CSRF belirteci depolamak ve ardından hesaplanan JWT'nizi CSRF belirteciyle birlikte istek başlığına yerleştirmektir.
Aaron Grey

"Alabileceğiniz en temel önlem, uygulamanızın GET isteklerine yanıt olarak hiçbir zaman herhangi bir yan etki yapmadığından emin olmaktır." Bir CSRF saldırısının bir POST isteğini uydurması mümkün müdür?
Costa

Sunucu Tarafı Uygulamasına bağlı olarak mümkün OLABİLİR. Gibi bir şey kullanan Web Çerçeveleri var http://.../someRestResource?method=POST. Dolayısıyla bu temelde bir GETistek, ancak Sunucu Uygulaması bunu bir POSTistek olarak yorumlar çünkü methodHTTP başlığı yerine parametreyi kullanacak şekilde yapılandırılmıştır . ...Yaygın web tarayıcıları ile ilgili olarak, Aynı Kaynak Politikasını uygularlar ve yalnızca GETyabancı sunuculara istekleri yürütürler . O olsa olabilir yürütmek mümkün POSTistekleri halinde web tarayıcı bu web standartlarını (böcek, kötü amaçlı yazılım) geçerli değildir.
Benjamin M

1
Ek olarak Server Side App: İstek Gövdesi göndermek hala mümkün değildir, çünkü genel tarayıcılar buna izin vermeyecektir. Bununla birlikte, Sunucu Uygulaması izin method=POSTverirse body={someJson}, varsayılan istek gövdesinin geçersiz kılınmasına da izin verebilir . Bu gerçekten kötü API tasarımı ve son derece riskli. Bununla birlikte, Sunucu Uygulamanız izin http://...?method=POST&body={someJson}veriyorsa, orada ne yaptığınızı, neden yaptığınızı ve gerekli olup olmadığını gerçekten düşünmelisiniz. (Vakaların% 99,9999'unda gerekli olmadığını söyleyebilirim ). Ek olarak, tarayıcılar bu şekilde yalnızca birkaç kilobayt gönderebilir.
Benjamin M

@BenjaminM, Same Origin Policy'nin yalnızca javaScript kodunun sonuca erişmesini engellediğini ve dolayısıyla istek "engellendiğinde" sunucuya ulaştığını fark eder - jsbin.com/mewaxikuqo/edit?html,js,output Bunu yalnızca firefox'ta test ettim, ancak geliştirme araçlarını açabilir ve "Çapraz Kaynak İsteği Engellendi" olsa bile, uzak sunucunun aslında tüm isteği gördüğünü görebilirsiniz. bu nedenle tüm POST istekleriniz için belirteçlere veya özel başlıklara (ve mümkünse her ikisine de) sahip olmanız gerekir
Yoni Jah

59

TL; DR

Bir JWT, Çerezler olmadan kullanılırsa, CSRF jetonuna olan ihtiyacı ortadan kaldırır - AMA! JWT'yi session / localStorage'da depolayarak, sitenizde bir XSS güvenlik açığı varsa (oldukça yaygın) JWT'nizi ve kullanıcının kimliğini açığa çıkarın. csrfTokenJWT'ye bir anahtar eklemek ve JWT'yi secureve http-onlyöznitelikleri ayarlanmış bir çerezde saklamak daha iyidir .

Daha fazla bilgi için bu makaleyi iyi bir açıklamayla okuyun https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Bir xsrfToken JWT talebi ekleyerek bu CSRF korumasını vatansız yapabilirsiniz:

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

Bu nedenle, csrfToken'ı localStorage / sessionStorage'da ve JWT'nin kendisinde (yalnızca http ve güvenli bir tanımlama bilgisinde saklanır) depolamanız gerekir. Sonra csrf koruması için, JWT'deki csrf belirtecinin gönderilen csrf belirteci başlığıyla eşleştiğini doğrulayın.


2
Kullanıcının API kimlik doğrulaması sırasında csrf belirteci kullanımını muaf tutmak gerekir mi?
user805981

3
(Başkalarının kaynak bağlantısındaki yorumlarda da bahsettiği gibi), CSRF belirtecini yerel depolamada depolayan a) yalnızca http olmayan çerezleri veya b) CSRF belirtecini depolayan herhangi bir CSRF azaltma işleminin XSS'ye karşı savunmasız olduğunu belirtmek gerekir. Bu, sunulan yaklaşımın JWT'yi XSS kullanan bir saldırgandan gizli tutmasına yardımcı olabileceği anlamına gelir, ancak bir saldırgan yine de API'nizde kötü amaçlı bir istek yürütebilir çünkü geçerli bir JWT sağlayabilir (çerez aracılığıyla, teşekkür ederim tarayıcı) ve CSRF belirteci (yerel depolamadan / çerezden enjekte edilen JS aracılığıyla okunur).
Johannes Rudolph

1
Aslında bir CSRF belirteci bile sizi bu XSS düzeyinde koruyamaz, çünkü saldırganın localStorage'a erişebileceğini varsayarsınız, şu anda erişmenin tek yolu komut dosyası düzeyinde erişime sahip olmaktır ve yine de CSRF belirtecine göz atabilirler. .
08

1
@JohannesRudolph'un söylediği bu değil miydi? CSRF Belirtecini Web Depolamasında / yalnızca http olmayan çerezde sakladığınız anda, bir XSS saldırısının ayak izini artırmış olursunuz çünkü bunlara JS aracılığıyla erişilebilir.
adam-beck

1
Burada tam bir uzman değil, ancak hala başlangıçta olduğu gibi XSS'ye maruz kalıyorsanız , eklemek daha iyi olan kısımdan emin değilim ... gerçekten tutar. Muhtemelen bir saldırganın CSRF belirtecini ele geçirmesi biraz (?) Daha karmaşıktır, ancak sonunda JWT belirtecini bilmese bile sizin adınıza bir istek gerçekleştirebilir. Bu doğru mu? Teşekkürler
superjos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.