ทำความเข้าใจกับโทเค็นของแท้ Rails


982

ฉันพบปัญหาบางอย่างเกี่ยวกับโทเค็นของแท้ใน Rails เนื่องจากตอนนี้ฉันมีหลายครั้งแล้ว

แต่ฉันไม่ต้องการแก้ปัญหานี้และทำต่อไป ฉันอยากจะเข้าใจโทเค็นของแท้ คำถามของฉันคือคุณมีแหล่งข้อมูลที่สมบูรณ์ในเรื่องนี้หรือคุณจะใช้เวลาอธิบายรายละเอียดที่นี่?


7
ดูเพิ่มเติมที่: "ทำไม Google Prepend ในขณะที่ (1) ตอบสนองต่อ JSON ของพวกเขา" stackoverflow.com/questions/2669690/…
Chloe

คำตอบ:


1462

เกิดอะไรขึ้น

เมื่อผู้ใช้ดูฟอร์มเพื่อสร้างอัปเดตหรือทำลายทรัพยากรแอพ Rails จะสร้างแบบสุ่มจัดauthenticity_tokenเก็บโทเค็นนี้ในเซสชันและวางไว้ในเขตข้อมูลที่ซ่อนอยู่ในแบบฟอร์ม เมื่อผู้ใช้ส่งแบบฟอร์ม Rails จะค้นหาauthenticity_tokenเปรียบเทียบกับแบบฟอร์มที่เก็บไว้ในเซสชันและหากพวกเขาตรงกับคำขอจะได้รับอนุญาตให้ดำเนินการต่อ

ทำไมมันเกิดขึ้น

เนื่องจากโทเค็นของแท้ถูกเก็บไว้ในเซสชันไคลเอนต์จึงไม่สามารถรู้คุณค่าของมัน สิ่งนี้ป้องกันไม่ให้ผู้คนส่งแบบฟอร์มไปยังแอพ Rails โดยไม่ต้องดูฟอร์มภายในแอพนั้น ลองนึกภาพว่าคุณกำลังใช้บริการ A คุณลงชื่อเข้าใช้บริการและทุกอย่างก็โอเค ทีนี้ลองนึกภาพว่าคุณไปใช้บริการ B แล้วคุณเห็นภาพที่คุณชอบและกดที่ภาพเพื่อดูขนาดที่ใหญ่ขึ้น ตอนนี้ถ้าบางรหัสชั่วอยู่ที่นั่นที่บริการ B, มันอาจจะส่งคำขอไปยังบริการ (ซึ่งคุณเข้าสู่ระบบ) http://serviceA.com/close_accountและขอให้ลบบัญชีของคุณโดยการส่งคำขอไปยัง นี่คือสิ่งที่เป็นที่รู้จักกันCSRF (Cross Site ปลอมขอ)

หากบริการ A กำลังใช้โทเค็นของแท้เวกเตอร์การโจมตีนี้จะไม่สามารถใช้งานได้อีกต่อไปเนื่องจากคำขอจากบริการ B จะไม่มีโทเค็นของแท้ที่ถูกต้องและจะไม่ได้รับอนุญาตให้ดำเนินการต่อ

เอกสาร APIอธิบายรายละเอียดเกี่ยวกับเมตาแท็ก:

การป้องกัน CSRF เปิดใช้งานด้วยprotect_from_forgeryวิธีการซึ่งจะตรวจสอบโทเค็นและรีเซ็ตเซสชันหากไม่ตรงกับสิ่งที่คาดหวัง การเรียกใช้วิธีนี้ถูกสร้างขึ้นสำหรับแอพพลิเคชั่น Rails ใหม่ตามค่าเริ่มต้น พารามิเตอร์โทเค็นถูกตั้งชื่อauthenticity_tokenตามค่าเริ่มต้น ต้องเพิ่มชื่อและค่าของโทเค็นนี้ในทุกเลย์เอาต์ที่แสดงแบบฟอร์มโดยรวมcsrf_meta_tagsไว้ในส่วนหัว HTML

หมายเหตุ

โปรดจำไว้ว่า Rails จะตรวจสอบไม่ใช่วิธี idempotent (POST, PUT / PATCH และ DELETE) คำขอ GET ไม่ได้รับการตรวจสอบโทเค็นของแท้ ทำไม? เนื่องจากข้อมูลจำเพาะ HTTP ระบุว่าคำขอ GET นั้นเป็น idempotent และไม่ควรสร้างแก้ไขหรือทำลายทรัพยากรที่เซิร์ฟเวอร์และคำขอนั้นควรเป็น idempotent (หากคุณเรียกใช้คำสั่งเดียวกันหลายครั้งคุณควรได้ผลลัพธ์เดียวกันทุกครั้ง)

การใช้งานจริงนั้นซับซ้อนกว่าเล็กน้อยตามที่กำหนดไว้ในตอนต้นทำให้มั่นใจในความปลอดภัยที่ดีขึ้น Rails ไม่ได้ออกโทเค็นที่จัดเก็บไว้เหมือนกันกับทุกรูปแบบ ไม่สร้างและเก็บโทเค็นที่แตกต่างกันทุกครั้ง มันสร้างและเก็บแฮชการเข้ารหัสในเซสชันและออกโทเค็นการเข้ารหัสใหม่ซึ่งสามารถจับคู่กับที่เก็บไว้ทุกครั้งที่มีการแสดงหน้าเว็บ ดูrequest_forgery_protection.rb

บทเรียน

ใช้authenticity_tokenเพื่อปกป้องวิธีการไม่ใช้ idempotent ของคุณ (POST, PUT / PATCH และ DELETE) ตรวจสอบให้แน่ใจด้วยว่าไม่อนุญาตคำขอ GET ใด ๆ ที่อาจแก้ไขทรัพยากรบนเซิร์ฟเวอร์


แก้ไข:ตรวจสอบความคิดเห็นโดย @erturneเกี่ยวกับคำขอ GET เป็น idempotent เขาอธิบายในวิธีที่ดีกว่าที่ฉันทำที่นี่


25
@Faisal เป็นไปได้ไหมที่ผู้โจมตีสามารถอ่าน / จับองค์ประกอบ 'ที่ซ่อนอยู่' ของฟอร์มสำหรับ Service A และรับโทเค็นที่ไม่ซ้ำกันที่สร้างขึ้นสำหรับผู้ใช้ - เนื่องจากพวกเขาได้รับการเข้าถึงเซสชันที่ผู้ใช้เริ่มต้น สำหรับบริการ A?
marcamillion

11
@marcamillion: ถ้ามีคนแย่งชิงเซสชันของคุณที่บริการ A โทเค็นของแท้จะไม่ปกป้องคุณ นักจี้ที่จะสามารถส่งคำขอและจะได้รับอนุญาตให้ดำเนินการต่อไป
Faisal

12
@zabba: Rails ทำให้เกิดข้อยกเว้น ActionController :: InvalidAuthenticityToken หากมีการส่งแบบฟอร์มโดยไม่มีโทเค็นที่เหมาะสม คุณสามารถช่วยเหลือจากข้อยกเว้นและดำเนินการตามที่คุณต้องการ
Faisal

5
"ตรวจสอบให้แน่ใจว่าไม่ได้ทำการร้องขอ GET ใด ๆ ที่อาจแก้ไขทรัพยากรบนเซิร์ฟเวอร์ได้" - สิ่งนี้รวมถึงการไม่ใช้การจับคู่ () ในเส้นทางที่อาจอนุญาตให้ GET ร้องขอเพื่อควบคุมการกระทำที่ต้องการรับเฉพาะ POSTs
Steven Soroka

102
"... และคำขอควรเป็น idempotent (หากคุณเรียกใช้คำสั่งเดียวกันหลายครั้งคุณควรได้ผลลัพธ์เดียวกันทุกครั้ง)" เพียงแค่ความกระจ่างชัดที่นี่ ปลอดภัยหมายถึงไม่มีผลข้างเคียง Idempotent หมายถึงผลข้างเคียงเดียวกันไม่ว่าจะมีการให้บริการกี่ครั้งก็ตาม บริการที่ปลอดภัยทั้งหมดเป็น idempotent โดยเนื้อแท้เพราะไม่มีผลข้างเคียง การเรียก GET บนทรัพยากรเวลาปัจจุบันหลาย ๆ ครั้งจะให้ผลลัพธ์ที่แตกต่างกันในแต่ละครั้ง แต่ก็ปลอดภัย (และเป็น idempotent)
erturne

137

โทเค็นของแท้ได้รับการออกแบบเพื่อให้คุณรู้ว่าฟอร์มของคุณกำลังถูกส่งจากเว็บไซต์ของคุณ มันถูกสร้างขึ้นจากเครื่องที่ทำงานด้วยตัวระบุเฉพาะที่มีเพียงเครื่องของคุณเท่านั้นที่สามารถรู้ได้จึงช่วยป้องกันการโจมตีปลอมแปลงคำขอข้ามไซต์

หากคุณมีปัญหากับรางที่ปฏิเสธการเข้าถึงสคริปต์ AJAX ของคุณคุณสามารถใช้

<%= form_authenticity_token %>

เพื่อสร้างโทเค็นที่ถูกต้องเมื่อคุณสร้างแบบฟอร์มของคุณ

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ในเอกสาร


88

CSRF คืออะไร

โทเค็นของแท้เป็นวิธีการตอบโต้การปลอมแปลงคำขอข้ามไซต์ (CSRF) CSRF คืออะไรคุณถาม

เป็นวิธีที่ผู้โจมตีสามารถจี้เซสชันโดยไม่ต้องรู้โทเค็นเซสชัน

สถานการณ์สมมติ :

  • เยี่ยมชมเว็บไซต์ของธนาคารของคุณเข้าสู่ระบบ
  • จากนั้นไปที่ไซต์ของผู้โจมตี (เช่นโฆษณาที่ได้รับการสนับสนุนจากองค์กรที่ไม่น่าเชื่อถือ)
  • หน้าของผู้โจมตีรวมถึงแบบฟอร์มที่มีฟิลด์เดียวกับแบบฟอร์ม "โอนเงิน" ของธนาคาร
  • Attacker รู้ข้อมูลบัญชีของคุณและมีฟิลด์แบบฟอร์มที่กรอกไว้ล่วงหน้าเพื่อโอนเงินจากบัญชีของคุณไปยังบัญชีของผู้โจมตี
  • หน้าผู้โจมตีมีจาวาสคริปต์ที่ส่งแบบฟอร์มไปยังธนาคารของคุณ
  • เมื่อมีการส่งแบบฟอร์มเบราว์เซอร์จะมีคุกกี้ของคุณสำหรับเว็บไซต์ของธนาคารรวมถึงโทเค็นเซสชัน
  • ธนาคารโอนเงินไปยังบัญชีของผู้โจมตี
  • แบบฟอร์มสามารถอยู่ใน iframe ที่มองไม่เห็นดังนั้นคุณไม่เคยรู้เลยว่ามีการโจมตีเกิดขึ้น
  • สิ่งนี้เรียกว่าการปลอมแปลงคำขอข้ามไซต์ (CSRF)

โซลูชั่น CSRF :

  • เซิร์ฟเวอร์สามารถทำเครื่องหมายแบบฟอร์มที่มาจากเซิร์ฟเวอร์เอง
  • ทุกแบบฟอร์มต้องมีโทเค็นการตรวจสอบความถูกต้องเพิ่มเติมเป็นเขตข้อมูลที่ซ่อนอยู่
  • โทเค็นจะต้องคาดเดาไม่ได้ (ผู้โจมตีไม่สามารถเดาได้)
  • เซิร์ฟเวอร์ให้โทเค็นที่ถูกต้องในรูปแบบในหน้าของมัน
  • เซิร์ฟเวอร์จะตรวจสอบโทเค็นเมื่อแบบฟอร์มที่โพสต์ปฏิเสธฟอร์มโดยไม่มีโทเค็นที่เหมาะสม
  • ตัวอย่างโทเค็น: ตัวระบุเซสชันที่เข้ารหัสด้วยรหัสลับเซิร์ฟเวอร์
  • Rails สร้างโทเค็นดังกล่าวโดยอัตโนมัติ: ดูช่องป้อนข้อมูล authenticity_token ในทุกรูปแบบ

1
นี่คือรุ่นของคำอธิบายเดียวกันนี้ที่มีความแม่นยำน้อยกว่า แต่ก็มีความเป็นนามธรรมน้อยกว่า: stackoverflow.com/a/33829607/2810305
Lutz Prechelt

ฉันไม่แน่ใจ แต่เบราว์เซอร์ที่ทันสมัยอนุญาตให้ส่งคำขอ idempotent ไม่ใช่ (POST / PUT / DELETE) ไปยังโดเมนอื่นได้หรือไม่ ฉันเดาว่าจะต้องมีการป้องกันสิ่งต่าง ๆ ในเบราว์เซอร์ด้วย
divideByZero

45

ตัวอย่างการโจมตีน้อยที่สุดที่จะป้องกันได้: CSRF

บนเว็บไซต์ของevil.comฉันฉันโน้มน้าวให้คุณส่งแบบฟอร์มต่อไปนี้:

<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>

หากคุณลงชื่อเข้าใช้ธนาคารของคุณผ่านคุกกี้เซสชันแล้วคุกกี้จะถูกส่งไปและการโอนเงินจะเกิดขึ้นโดยที่คุณไม่รู้ตัว

นั่นคือโทเค็น CSRF ที่เข้ามาเล่น:

  • ด้วยการตอบสนองของ GET ที่ส่งคืนฟอร์ม Rails ส่งพารามิเตอร์ที่ซ่อนแบบสุ่มที่ยาวมาก
  • เมื่อเบราว์เซอร์ทำการร้องขอ POST มันจะส่งพารามิเตอร์ไปตามและเซิร์ฟเวอร์จะยอมรับเฉพาะเมื่อมันตรงกัน

ดังนั้นฟอร์มบนเบราว์เซอร์ของแท้จะมีลักษณะดังนี้:

<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>

ดังนั้นการโจมตีของฉันจะล้มเหลวเนื่องจากไม่ได้ส่งauthenticity_tokenพารามิเตอร์และไม่มีทางที่ฉันจะเดาได้เพราะมันเป็นตัวเลขสุ่มขนาดใหญ่

เทคนิคการป้องกันนี้เรียกว่ารูปแบบสัญญาณซิงโครไนซ์

นโยบายกำเนิดเดียวกัน

แต่ถ้าผู้โจมตีทำการร้องขอสองครั้งด้วย JavaScript หนึ่งอันเพื่ออ่านโทเค็นและอีกอันที่สองเพื่อทำการถ่ายโอน

รูปแบบโทเค็นของ synchronizer เพียงอย่างเดียวไม่เพียงพอที่จะป้องกันสิ่งนั้น!

นี่คือที่มาของนโยบายกำเนิดเดียวกันเพื่อช่วยชีวิตตามที่ฉันได้อธิบายไว้ที่: /security/8264/why-is-the-the-same-origin-poligin-so-important/72569# 72569

Rails ส่งโทเค็นอย่างไร

ครอบคลุมใน: Rails: csrf_meta_tag ทำงานอย่างไร

โดยทั่วไป:

  • ผู้ช่วยเหลือ HTML เช่นform_tagเพิ่มเขตข้อมูลที่ซ่อนอยู่ในแบบฟอร์มสำหรับคุณหากไม่ใช่แบบฟอร์ม GET

  • AJAX ถูกจัดการโดยอัตโนมัติโดยjquery-ujsซึ่งอ่านโทเค็นจากmetaองค์ประกอบที่เพิ่มในส่วนหัวของคุณโดยcsrf_meta_tags(แสดงในเทมเพลตเริ่มต้น) และเพิ่มลงในคำขอใด ๆ ที่ทำ

    uJS ยังพยายามอัพเดตโทเค็นในแบบฟอร์มในแฟรกเมนต์แคชที่ล้าสมัย

แนวทางการป้องกันอื่น ๆ


ขอบคุณ แต่ประเด็นของคุณเกี่ยวกับการใช้นโยบายต้นกำเนิดเดียวกันเพื่อไม่สามารถอ่านโทเค็น CSRF ได้ก่อนดูเหมือนจะมีข้อบกพร่อง ดังนั้นก่อนอื่นคุณบอกว่าคุณสามารถ POST ไปยังแหล่งกำเนิดที่แตกต่างกัน แต่อ่านไม่ออกดูเหมือนแปลก แต่ฉันเดาว่าถูกต้อง แต่คุณสามารถฉีดรูปภาพหรือแท็กสคริปต์ด้วยการไปที่หน้าและเชื่อมโยงตัวจัดการเพื่อวิเคราะห์คำตอบ และรับใช่
bjm88

@ bjm88 ฉีดสคริปต์ที่ไหน? บนไซต์ของคุณหรือบนไซต์ที่ถูกโจมตี? หากไซต์ที่ถูกโจมตีการยอมให้มีการฉีดสคริปต์เป็นข้อบกพร่องด้านความปลอดภัยที่รู้จักกันดี ทุกเว็บไซต์จะต้องต่อสู้ผ่านการสุขาภิบาลการป้อนข้อมูล สำหรับภาพฉันไม่เห็นว่าจะใช้สำหรับการโจมตีได้อย่างไร ในการโจมตีไซต์: คุณสามารถปรับเปลี่ยนเบราว์เซอร์ของคุณเพื่อให้สามารถอ่านได้และโดยอัตโนมัติจะจำนำตัวเองตามใจชอบ :-) แต่เบราว์เซอร์ที่เหมาะสมจะป้องกันไม่ให้ใช้งานได้ตามค่าเริ่มต้นลองใช้ดู
Ciro Santilli 冠状病毒审查六四事件法轮功

43

โทเค็นของแท้ใช้เพื่อป้องกันการโจมตีข้ามการร้องขอการปลอมแปลง (CSRF) เพื่อให้เข้าใจโทเค็นของแท้คุณต้องเข้าใจการโจมตี CSRF ก่อน

CSRF

bank.comสมมติว่าคุณเป็นผู้เขียน คุณมีแบบฟอร์มบนเว็บไซต์ของคุณที่ใช้ในการโอนเงินไปยังบัญชีอื่นที่มีคำขอ GET:

ป้อนคำอธิบายรูปภาพที่นี่

แฮกเกอร์สามารถส่งคำขอ HTTP ไปยังเซิร์ฟเวอร์ว่าGET /transfer?amount=$1000000&account-to=999999ใช่ไหม

ป้อนคำอธิบายรูปภาพที่นี่

ไม่ถูกต้อง. การโจมตีของแฮกเกอร์จะไม่ทำงาน โดยทั่วไปแล้วเซิร์ฟเวอร์จะคิดอย่างไร

ฮะ? ผู้ชายคนนี้คือใครพยายามเริ่มการถ่ายโอน ไม่ใช่เจ้าของบัญชีนั่นคือแน่นอน

เซิร์ฟเวอร์รู้ได้อย่างไร เพราะไม่มีsession_idคุกกี้รับรองความถูกต้องของผู้ร้องขอ

เมื่อคุณลงชื่อเข้าใช้ด้วยชื่อผู้ใช้และรหัสผ่านเซิร์ฟเวอร์จะตั้งsession_idคุกกี้บนเบราว์เซอร์ของคุณ ด้วยวิธีนี้คุณไม่จำเป็นต้องตรวจสอบสิทธิ์แต่ละคำขอด้วยชื่อผู้ใช้และรหัสผ่านของคุณ เมื่อเบราว์เซอร์ของคุณส่งsession_idคุกกี้เซิร์ฟเวอร์จะรู้:

โอ้นั่นคือจอห์นโด เขาลงชื่อเข้าใช้สำเร็จ 2.5 นาทีที่แล้ว เขาดีที่จะไป

แฮกเกอร์อาจคิดว่า:

อืมมม คำขอ HTTP ปกติไม่ทำงาน แต่ถ้าฉันสามารถหยิบsession_idคุกกี้นั้นฉันจะเป็นสีทอง

เบราว์เซอร์ผู้ใช้มีการตั้งค่าคุกกี้จำนวนมากสำหรับbank.comโดเมน ทุกครั้งที่ผู้ใช้ทำการร้องขอไปยังbank.comโดเมนคุกกี้ทั้งหมดจะถูกส่งไปพร้อมกัน รวมไปถึงsession_idคุกกี้

ดังนั้นหากแฮ็กเกอร์สามารถให้คุณทำตามคำขอ GET ที่โอนเงินเข้าบัญชีเขาจะประสบความสำเร็จ เขาจะหลอกให้คุณทำเช่นนั้นได้อย่างไร? ด้วยการปลอมแปลงคำขอข้ามไซต์

มันค่อนข้างง่ายจริงๆ แฮกเกอร์สามารถพาคุณเยี่ยมชมเว็บไซต์ของเขาได้ บนเว็บไซต์ของเขาเขาสามารถมีแท็กรูปภาพดังต่อไปนี้:

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

เมื่อเบราว์เซอร์ผู้ใช้พบแท็กภาพนั้นจะเป็นการขอ GET ไปยัง URL นั้น และเนื่องจากคำขอมาจากเบราว์เซอร์ของเขาจึงจะส่งพร้อมคุกกี้ทั้งหมดที่เชื่อมโยงกับbank.comมัน หากผู้ใช้เพิ่งลงชื่อเข้าใช้bank.com... session_idคุกกี้จะถูกตั้งค่าและเซิร์ฟเวอร์จะคิดว่าผู้ใช้ตั้งใจจะโอนเงิน $ 1,000,000 ไปยังบัญชี 999999!

ป้อนคำอธิบายรูปภาพที่นี่

เอาล่ะอย่าไปเยี่ยมเว็บไซต์อันตรายและคุณก็สบายดี

นั่นไม่เพียงพอ จะเป็นอย่างไรถ้ามีคนโพสต์ภาพนั้นบน Facebook และมันปรากฏบนกระดานข้อความของคุณ? จะเกิดอะไรขึ้นถ้ามันถูกฉีดเข้าไปในเว็บไซต์ที่คุณเข้าชมด้วยการโจมตี XSS

มันไม่ได้เลวร้ายนัก คำขอ GET เท่านั้นที่มีช่องโหว่

ไม่จริง. แบบฟอร์มที่ส่งคำขอ POST สามารถสร้างได้แบบไดนามิก นี่คือตัวอย่างจากRails Guide on Security :

<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>

โทเค็นของแท้

เมื่อคุณApplicationControllerมีสิ่งนี้:

protect_from_forgery with: :exception

นี้:

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

รวบรวมไว้ในนี้:

<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>

โดยเฉพาะอย่างยิ่งสิ่งต่อไปนี้ถูกสร้างขึ้น:

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

เพื่อป้องกันการโจมตีจาก CSRF ถ้า Rails ไม่เห็นโทเค็นของแท้ที่ส่งมาพร้อมกับคำขอนั้นจะไม่ถือว่าคำขอนั้นปลอดภัย

ผู้โจมตีควรรู้ว่าโทเค็นนี้คืออะไร? ค่าที่แตกต่างจะถูกสร้างขึ้นแบบสุ่มในแต่ละครั้งที่สร้างแบบฟอร์ม:

ป้อนคำอธิบายรูปภาพที่นี่

การโจมตี Cross Site Scripting (XSS) - นั่นเป็นวิธี แต่นั่นเป็นช่องโหว่ที่แตกต่างกันในแต่ละวัน


39

Authenticity Tokenคือวิธีการเพื่อให้รางป้องกัน 'ข้ามไซต์ปลอมขอ (CSRF หรือ XSRF) โจมตี'

เพื่อให้ง่ายตรวจสอบให้แน่ใจว่าคำขอ PUT / POST / DELETE (วิธีการที่สามารถแก้ไขเนื้อหา) ไปยังเว็บแอปของคุณนั้นทำจากเบราว์เซอร์ของไคลเอ็นต์และไม่ใช่จากบุคคลที่สาม (ผู้โจมตี) ที่เข้าถึงคุกกี้ที่สร้างขึ้น ในฝั่งไคลเอ็นต์


34

เนื่องจากAuthenticity Tokenมีความสำคัญมากและใน Rails 3.0+ คุณสามารถใช้งานได้

 <%= token_tag nil %>

เพื่อสร้าง

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

ทุกแห่ง


สิ่งนี้มีประโยชน์สำหรับฉัน จริง ๆ แล้วฉันพยายามทำXSSในหน้าเข้าสู่ระบบไม่ใช่เพื่อจุดประสงค์ชั่วร้าย แต่เพื่อสร้างเซสชันใหม่ด้วยชื่อผู้ใช้ที่กรอกไว้ล่วงหน้า value="token_value"ตอนนี้ฉันรู้ว่าฉันก็สามารถใช้
ไมเคิล - Clay Shirky ของ

27

ระวังกลไกโทเค็นของแท้อาจส่งผลให้เกิดสภาวะการแข่งขันหากคุณมีคำขอหลายรายการพร้อมกันจากลูกค้ารายเดียวกัน ในสถานการณ์นี้เซิร์ฟเวอร์ของคุณสามารถสร้างโทเค็นความถูกต้องได้หลายตัวเมื่อควรมีเพียงหนึ่งเท่านั้นและลูกค้าที่ได้รับโทเค็นก่อนหน้าในรูปแบบจะล้มเหลวเนื่องจากคำขอครั้งถัดไปเนื่องจากโทเค็นคุกกี้เซสชันถูกเขียนทับ มีการเขียนขึ้นเกี่ยวกับปัญหานี้และวิธีแก้ปัญหาไม่ได้ทั้งหมดที่นี่: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


11

วิธีการที่authenticity_tokenจำเป็น

authenticity_token เป็นสิ่งจำเป็นในกรณีของวิธีการ idempotent เช่นการโพสต์, การวางและลบเพราะวิธีการ Idempotent มีผลกระทบต่อข้อมูล

ทำไมมันเป็นสิ่งจำเป็น

จะต้องมีการป้องกันจากการกระทำที่ชั่วร้าย authenticity_token ถูกเก็บไว้ในเซสชั่นเมื่อใดก็ตามที่มีการสร้างแบบฟอร์มบนหน้าเว็บสำหรับการสร้างหรือการปรับปรุงทรัพยากรโทเค็นของแท้จะถูกเก็บไว้ในเขตที่ซ่อนอยู่และส่งมาพร้อมกับรูปแบบบนเซิร์ฟเวอร์ ก่อนที่จะดำเนินการกับผู้ใช้ที่ดำเนินการส่ง authenticity_token จะถูกตรวจสอบข้ามโดยauthenticity_tokenเก็บไว้ในเซสชัน หากauthenticity_tokenเหมือนกันกระบวนการจะดำเนินการต่อมิฉะนั้นจะไม่ดำเนินการใด ๆ


3
จริงๆแล้วมันไม่ได้ตรงกันข้ามหรือ GET เป็น idempotent เนื่องจากการโทรไม่ควรเปลี่ยนสถานะของระบบที่ PUT POST และ DELETE verbs ไม่ได้เป็น idempotent verbs เนื่องจากพวกมันเปลี่ยนสถานะของระบบ IE: authenticity_token เป็นสิ่งจำเป็นในกรณีที่ไม่ใช่วิธี idempotent
Jean-Théo

2
@ Jean-Daube, uma: idempotent หมายความว่าถ้าทำสองครั้งการกระทำจะเกิดขึ้นเพียงครั้งเดียว GET, PUT และ DELETE เป็น idempotent: w3.org/Protocols/rfc2616/rfc2616-sec9.htmlคุณสมบัติหลักของที่นี่ไม่ใช่ idempotency แต่ถ้าวิธีนั้นเปลี่ยนหรือไม่ใช้ข้อมูลซึ่งเรียกว่า "Safe method" หรือไม่
Ciro Santilli 冠状病毒审查六四事件法轮功

6

การรับรองความถูกต้องคืออะไร

นี่คือสตริงสุ่มที่ใช้โดยแอปพลิเคชันทางรถไฟเพื่อให้แน่ใจว่าผู้ใช้กำลังร้องขอหรือดำเนินการจากหน้าแอพไม่ใช่จากแอพหรือไซต์อื่น

ทำไมต้องมี authentication_token

เพื่อปกป้องแอปหรือไซต์ของคุณจากการปลอมแปลงคำขอข้ามไซต์

วิธีเพิ่ม authentication_token ให้กับฟอร์มได้อย่างไร

หากคุณกำลังสร้างรูปแบบการใช้ form_for แท็ก authentication_token ถูกเพิ่มโดยอัตโนมัติอื่น ๆ <%= csrf_meta_tag %>ที่คุณสามารถใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.