Rails Orijinallik Simgesini Anlama


982

Birçok kez sahip olduğum gibi, Rails'teki Authenticity Token ile ilgili bazı sorunlar yaşıyorum.

Ama gerçekten sadece bu sorunu çözmek ve devam etmek istemiyorum. Gerçekten Orijinallik belirtecini anlamak istiyorum. Sorum şu: Bu konuda tam bir bilgi kaynağınız var mı veya burada ayrıntılı olarak açıklamak için zaman harcıyor musunuz?


7
Ayrıca bkz: "Google, (1) JSON yanıtlarına neden katılmayı tercih ediyor?" stackoverflow.com/questions/2669690/…
Chloe

Yanıtlar:


1462

Ne oluyor

Kullanıcı kaynağı oluşturmak, güncellemek veya yok etmek için bir formu görüntülediğinde, Rails uygulaması rastgele oluşturur authenticity_token, bu belirteci oturumda saklar ve formdaki gizli bir alana yerleştirir. Kullanıcı formu gönderdiğinde, Rails for'u arar authenticity_token, oturumda depolanan formla karşılaştırır ve eşleşirse isteğin devam etmesine izin verilir.

Neden olur

Orijinallik belirteci oturumda saklandığından, istemci değerini bilemez. Bu, kullanıcıların formu uygulamanın kendisinde görüntülemeden bir Rails uygulamasına göndermelerini önler. A servisini kullandığınızı, servise giriş yaptığınızı ve her şeyin yolunda olduğunu düşünün. Şimdi servis B'yi kullandığınızı ve beğendiğiniz bir resmi gördüğünüzü ve daha büyük bir boyutunu görmek için resme bastırdığınızı hayal edin. Şimdi, B hizmetinde bazı kötü kodlar varsa, A hizmetine (oturum açtığınız) bir istek gönderebilir ve bir istek göndererek hesabınızı silmeyi isteyebilir http://serviceA.com/close_account. Bu CSRF (Siteler Arası İstek Sahteciliği) olarak bilinir .

Hizmet A özgünlük belirteçleri kullanıyorsa, hizmet B'den gelen istek doğru kimlik doğrulama belirtecini içermeyeceğinden ve devam etmesine izin verilmeyeceğinden, bu saldırı vektörü artık uygulanamaz.

API dokümanları meta etiketle ilgili ayrıntıları açıklar:

CSRF koruması, protect_from_forgerybelirteci denetleyen ve beklenen ile eşleşmiyorsa oturumu sıfırlayan yöntemle açılır . Varsayılan olarak yeni Rails uygulamaları için bu yönteme çağrı oluşturulur. Belirteç parametresi authenticity_tokenvarsayılan olarak adlandırılır . csrf_meta_tagsHTML başlığına ekleyerek form oluşturan her düzene bu simgenin adı ve değeri eklenmelidir .

notlar

Unutmayın, Rails sadece idempotent yöntemleri (POST, PUT / PATCH ve DELETE) doğrulamaz. GET isteği, orijinal belirteç için denetlenmez. Neden? GET istekleri HTTP şartname devletler İdempotent ve gerektiği çünkü değil , alter oluşturabilir veya sunucuda kaynaklarını yok etmek ve isteği İdempotent olmalıdır (aynı komut birden çok kez çalıştırırsanız, aynı sonucu her zaman almak gerekir).

Ayrıca, gerçek uygulama başlangıçta tanımlandığı gibi biraz daha karmaşıktır ve daha iyi güvenlik sağlar. Rails, her formda aynı depolanmış jetonu yayınlamaz. Her seferinde farklı bir jeton üretmez ve depolamaz. Bir oturumda bir şifreleme karması oluşturur ve saklar ve her sayfa görüntülendiğinde depolananla eşleştirilebilen yeni şifreleme belirteçleri yayınlar. Bkz. Request_forgery_protection.rb .

Dersler

authenticity_tokenİdempotent olmayan yöntemlerinizi (POST, PUT / PATCH ve DELETE) korumak için kullanın . Ayrıca sunucudaki kaynakları değiştirebilecek GET isteklerine izin vermediğinizden emin olun.


DÜZENLEME: @erturne tarafından GET isteklerinin idempotent olmasıyla ilgili yorumu kontrol edin . Bunu burada yaptığımdan daha iyi açıklıyor.


25
@Faisal, bir saldırganın Hizmet A için formun 'gizli' öğesini okuması / yakalaması ve kullanıcı tarafından başlatılan oturuma erişmiş olmaları koşuluyla kullanıcı için oluşturulan bu benzersiz simgeyi alması mümkün mü? Hizmet A için?
marcamillion

11
@marcamillion: Birisi oturumunuzu A servisinden kaçırırsa, orijinal jetonu sizi korumaz. Korsanının bir istek gönderebilecek ve devam etmesine izin verilecektir.
Faysal

12
@zabba: Bir form uygun belirteç olmadan gönderilirse Rails bir ActionController :: InvalidAuthenticityToken istisnası oluşturur. İstisnayı kurtarma ve istisnadan istediğiniz işlemi yapabilirsiniz.
Faysal

5
re "Ayrıca sunucudaki kaynakları değiştirebilecek GET istekleri yapmadığınızdan emin olun." - bu, yalnızca POST'ları almayı amaçlayan denetleyici işlemlerine GET isteklerine izin verebilecek rotalarda match () kullanılmamasını içerir
Steven Soroka

102
"... ve istek idempotent olmalıdır (aynı komutu birden çok kez çalıştırırsanız, her seferinde aynı sonucu almalısınız)." Burada ince bir açıklama var. Güvenli, yan etkisi olmadığı anlamına gelir. Idempotent, bir servisin kaç kez çağrıldığına bakılmaksızın aynı yan etki anlamına gelir. Tüm güvenli hizmetler doğal olarak idempotenttir çünkü hiçbir yan etkisi yoktur. Geçerli bir zaman kaynağına GET çağrısı yapmak her seferinde farklı bir sonuç döndürür, ancak güvenlidir (ve bu nedenle idempotent).
erturne

137

Orijinallik belirteci, formunuzun web sitenizden gönderildiğini bilmeniz için tasarlanmıştır. Üzerinde yalnızca makinenizin bildiği benzersiz bir tanımlayıcı ile çalıştığı makineden üretilir, böylece siteler arası istek sahtekârlığı saldırılarının önlenmesine yardımcı olur.

AJAX komut dosyası erişiminizi reddeden raylarla zorluk çekiyorsanız,

<%= form_authenticity_token %>

formunuzu oluştururken doğru jetonu oluşturmak için.

Bununla ilgili daha fazla bilgiyi dokümantasyonda okuyabilirsiniz .


88

CSRF nedir?

Orijinallik Simgesi, Siteler Arası İstek Sahteciliğine (CSRF) karşı bir önlemdir. CSRF nedir, soruyorsunuz?

Bu, bir saldırganın oturum belirteçlerini bile bilmeden potansiyel olarak oturumları ele geçirmesinin bir yoludur.

Senaryo :

  • Bankanızın sitesini ziyaret edin, giriş yapın.
  • Ardından saldırganın sitesini ziyaret edin (ör. Güvenilir olmayan bir kuruluşun sponsorlu reklamı).
  • Saldırganın sayfası bankanın "Para Transferi" formuyla aynı alanlara sahip formlar içerir.
  • Saldırgan hesap bilgilerinizi bilir ve hesabınızdan saldırganın hesabına para aktarmak için önceden doldurulmuş form alanlarına sahiptir.
  • Saldırganın sayfası, bankanıza form gönderen Javascript içerir.
  • Form gönderildiğinde, tarayıcı, oturum belirteci de dahil olmak üzere banka sitesi için çerezlerinizi içerir.
  • Banka parayı saldırganın hesabına aktarır.
  • Form görünmez bir iframe içinde olabilir, bu yüzden saldırının gerçekleştiğini asla bilemezsiniz.
  • Buna Siteler Arası İstek Sahteciliği (CSRF) denir.

CSRF çözümü :

  • Sunucu, sunucunun kendisinden gelen formları işaretleyebilir
  • Her form, gizli alan olarak ek bir kimlik doğrulama belirteci içermelidir.
  • Belirteç öngörülemez olmalıdır (saldırgan bunu tahmin edemez).
  • Sunucu, sayfalarındaki formlarda geçerli jeton sağlar.
  • Sunucu form gönderildiğinde jetonu denetler, uygun jeton olmadan formları reddeder.
  • Örnek belirteç: sunucu gizli anahtarıyla şifrelenmiş oturum tanımlayıcısı.
  • Raylar otomatik olarak bu tür jetonlar oluşturur: her formdaki authenticity_token giriş alanına bakın.

1
İşte aynı açıklamanın daha az kesin ama aynı zamanda daha az soyut bir versiyonu: stackoverflow.com/a/33829607/2810305
Lutz Prechelt

Emin değilim, ancak modern tarayıcılar başka bir etki alanına idempotent istekleri (POST / PUT / DELETE) göndermeye izin veriyor mu? Sanırım, tarayıcı kendisinde böyle şeylere karşı koruma olmalı
divideByZero

45

Önlenebilecek minimum saldırı örneği: CSRF

Web sitemde evil.comsizi aşağıdaki formu göndermeye ikna ediyorum:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

Bankanıza oturum çerezleri aracılığıyla giriş yaparsanız, çerezler gönderilir ve siz bile bilmeden havale yapılır.

CSRF jetonu devreye giriyordu:

  • formu döndüren GET yanıtıyla, Rails çok uzun bir rasgele gizli parametre gönderir
  • tarayıcı POST isteğinde bulunduğunda, parametreyi birlikte gönderir ve sunucu yalnızca eşleşirse kabul eder

Otantik bir tarayıcıdaki form şöyle görünür:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

Bu nedenle, authenticity_tokenparametrem göndermediği için saldırım başarısız olur ve büyük bir rasgele sayı olduğu için tahmin edebilmem mümkün değil.

Bu önleme tekniğine Synchronizer Token Pattern denir .

Aynı Menşe Politikası

Ancak, saldırgan JavaScript ile iki istekte bulunursa, biri jetonu okumak ve ikincisi aktarımı yapmak için?

Sadece eşleyici belirteç modeli bunu önlemek için yeterli değildir!

Https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569# adresinde açıkladığım gibi, aynı Köken Politikası kurtarmaya geliyor. 72569

Rails jetonları nasıl gönderir?

Şunun kapsamı: Raylar: csrf_meta_tag Nasıl Çalışır?

Temelde:

  • form_tagGET formu değilse, HTML yardımcıları forma gizli bir alan eklemeyi sever

  • AJAX, jquery-ujs tarafından otomatik olarak ele alınır , bu da jetonu metabaşlığınıza eklenen öğelerden okur.csrf_meta_tags (varsayılan şablonda bulunur) ve yapılan herhangi bir isteğe ekler.

    uJS ayrıca eski önbelleğe alınmış parçalardaki formlarda jetonu güncellemeye çalışır.

Diğer önleme yaklaşımları


Teşekkürler, ancak önce CSRF jetonunu okuyamamak için aynı köken politikasına güvenme konusundaki fikriniz kusurlu görünüyor. Yani önce farklı bir kökene POST yapabileceğinizi ancak ondan okuyamayacağınızı söylüyorsunuz, garip görünüyor ama sanırım bu doğru, ancak sayfaya bir görüntü ile bir resim veya komut dosyası enjekte edebilir ve yanıtı ayrıştırmak için bir işleyici bağlayabilirsiniz ve anladınız mı?
bjm88

@ bjm88 nereye komut dosyası enjekte? Sitenizde veya saldırıya uğramış sitede mi? Saldırıya uğramış site varsa, komut dosyası enjeksiyonuna izin vermek iyi bilinen bir güvenlik açığıdır ve web sitesini etkili bir şekilde piyonlar. Her web sitesi giriş sanitasyonu yoluyla onunla savaşmalıdır. Görüntüler için saldırı için nasıl kullanılabileceklerini görmüyorum. Saldırı sitesinde: tarayıcınızı okumaya izin verecek şekilde değiştirebilir ve böylece otomatik olarak kendinizi piyona koyabilirsiniz :-) ancak iyi tarayıcılar varsayılan olarak önler, bir deneyin.
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功

43

Orijinallik belirteci, Siteler Arası İstek Sahteciliği saldırılarını (CSRF) önlemek için kullanılır. Orijinallik belirtecini anlamak için önce CSRF saldırılarını anlamalısınız.

CSRF

Diyelim ki yazar sizsiniz bank.com. Sitenizde, bir GET isteğiyle farklı bir hesaba para aktarmak için kullanılan bir formunuz var:

resim açıklamasını buraya girin

Bir bilgisayar korsanı sunucuya HTTP isteği gönderebilir GET /transfer?amount=$1000000&account-to=999999, değil mi?

resim açıklamasını buraya girin

Yanlış. Bilgisayar korsanlarının saldırısı çalışmaz. Sunucu temel olarak düşünecek mi?

Ha? Bu adam kim bir transfer başlatmaya çalışıyor. Hesabın sahibi değil, kesinlikle.

Sunucu bunu nasıl biliyor? Çünkü session_idistekte bulunanın kimliğini doğrulayan bir çerez yok .

Kullanıcı adınız ve şifrenizle oturum açtığınızda, sunucu session_idtarayıcınıza bir çerez yerleştirir. Bu şekilde, her isteği kullanıcı adınız ve şifrenizle doğrulamanız gerekmez. Tarayıcınız session_idçerezi gönderdiğinde , sunucu şunları bilir:

Oh, bu John Doe. 2.5 dakika önce başarıyla giriş yaptı. Gitmek güzel.

Bir hacker şöyle düşünebilir:

Hmm. Normal bir HTTP isteği işe yaramaz, ancak elimi bu session_idçerezden alabilirsem altın olurdum.

Kullanıcı tarayıcısında, alan bank.comadı için bir grup çerez ayarlanmıştır . Kullanıcı alan adına her istekte bulunduğunda bank.com, tüm çerezler gönderilir. session_idÇerez dahil .

Dolayısıyla, bir hacker sizi hesabına para transfer eden GET talebinde bulunabilseydi, başarılı olurdu. Sizi nasıl kandırdı? Siteler Arası Talep Sahteciliği.

Aslında oldukça basit. Bilgisayar korsanı web sitesini ziyaret etmenizi sağlayabilir. Web sitesinde aşağıdaki resim etiketine sahip olabilir:

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

Kullanıcıların tarayıcısı bu resim etiketine rastladığında, bu URL'ye bir GET isteği gönderir. Ve istek tarayıcısından geldiğinden, onunla ilişkili tüm çerezleri gönderir bank.com. Kullanıcı yakın zamanda oturum açtıysa bank.com... session_idçerez ayarlanacak ve sunucu kullanıcının 999999 hesabına 1.000.000 dolar aktarmak istediğini düşünecektir!

resim açıklamasını buraya girin

Tehlikeli siteleri ziyaret etmeyin ve iyi olacaksınız.

Bu yeterli değil. Birisi bu resmi Facebook'a gönderir ve duvarınızda görünürse? Ya bir XSS saldırısıyla ziyaret ettiğiniz bir siteye enjekte edilirse?

O kadar da kötü değil. Yalnızca GET istekleri savunmasızdır.

Doğru değil. POST isteği gönderen bir form dinamik olarak oluşturulabilir. İşte Rails Guide of Security'den örnek :

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

Orijinallik Simgesi

Bunu yaptığınızda ApplicationController:

protect_from_forgery with: :exception

Bu:

<%= form_tag do %>
  Form contents
<% end %>

Bu derlendi:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

Özellikle, aşağıdakiler üretilir:

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

CSRF saldırılarına karşı korunmak için, Rails bir istekle birlikte gönderilen özgünlük belirtecini görmezse, isteği güvenli kabul etmez.

Saldırganın bu tokenin ne olduğunu nasıl bilmesi gerekir? Form her oluşturulduğunda rastgele farklı bir değer oluşturulur:

resim açıklamasını buraya girin

Siteler Arası Komut Dosyası Oluşturma (XSS) saldırısı - işte böyle. Ancak bu, farklı bir gün için farklı bir güvenlik açığıdır.


39

Authenticity TokenRaylar için yöntemdir önlemek xsrf (CSRF veya XSRF) saldırıları '' .

Basitçe ifade etmek gerekirse, web uygulamanıza gelen PUT / POST / DELETE (içeriği değiştirebilecek yöntemler) isteklerinin, oluşturulan bir çereze erişimi olan üçüncü bir taraftan (saldırgan) değil, müşterinin tarayıcısından yapıldığından emin olur. müşteri tarafında.


34

çünkü Authenticity Tokençok önemli ve Rails 3.0 ve sonraki sürümlerinde

 <%= token_tag nil %>

yaratmak

<input name="authenticity_token" type="hidden" value="token_value">

herhangi bir yer


Bu bana yardımcı oldu. Aslında XSSgiriş sayfasında, hain amaçlarla değil, önceden doldurulmuş kullanıcı adıyla yeni bir oturum oluşturmaya çalışıyordum. Artık kullanabileceğimi biliyorum value="token_value".
Michael - Clay Shirky

27

Aynı istemciden birden fazla, eşzamanlı isteğiniz varsa Authenticity Token mekanizmasının yarış koşullarına neden olabileceğine dikkat edin. Bu durumda, sunucunuz yalnızca bir tane olması gerektiğinde birden fazla özgünlük belirteci oluşturabilir ve bir formda önceki belirteci alan istemci, oturum çerezi belirtecinin üzerine yazıldığı için bir sonraki isteğinde başarısız olur. Bu sorun hakkında bir yazı var ve burada tamamen önemsiz bir çözüm yok: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


11

authenticity_tokenGereken Yöntemler

authenticity_token post, put ve delete gibi idempotent yöntemlerde gereklidir, çünkü Idempotent yöntemleri verilere etki eder.

Neden Gereklidir

Kötü eylemlerden kaçınmak gerekir. authenticity_token oturumda depolanır, web sayfalarında kaynak oluşturmak veya güncellemek için bir form oluşturulduğunda gizli alanda bir kimlik doğrulama jetonu saklanır ve form sunucuda gönderilir. Eylemi gerçekleştirmeden önce gönderilen Authenticity_token kullanıcı authenticity_tokenoturumda depolanan ile çapraz kontrol edilir . authenticity_tokenAynı ise , işlem devam eder, aksi takdirde eylem gerçekleştirmez.


3
Aslında, tam tersi değil mi? GET idempotenttir çünkü çağrısı sistemin durumunu değiştirmemelidir, burada PUT POST ve DELETE fiilleri sistem durumunu değiştirdikleri için idempotent fiiller DEĞİLDİR. IE: idempotent yöntemleri DEĞİL durumunda authenticity_token gereklidir.
Jean-Théo

2
@ Jean-Daube, uma: idempotent, iki kez yapılırsa, eylemin sadece bir kez gerçekleştiği anlamına gelir. GET, PUT ve DELETE olan İdempotent: w3.org/Protocols/rfc2616/rfc2616-sec9.html Burada anahtar özellik Idempotency değil, eğer "Güvenli yöntemi" olarak adlandırılan ya da olmasın yöntem değişiklikleri veya olmasın veri.
Ciro Santilli 法轮功 病毒: 六四 事件 法轮功

6

Authentication_token nedir?

Bu, kullanıcının başka bir uygulama veya siteden değil, uygulama sayfasından bir işlem istediğinden veya gerçekleştirdiğinden emin olmak için raylar uygulaması tarafından kullanılan rastgele bir dizedir.

Authentication_token neden gereklidir?

Uygulamanızı veya sitenizi siteler arası istek sahteciliğinden korumak için.

Bir forma bir authentication_token nasıl eklenir?

Form_for etiketi kullanarak bir form oluşturuyorsanız, otomatik olarak bir authentication_token eklenir <%= csrf_meta_tag %>.

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.