เราจำเป็นต้องจัดเก็บ JWT ไว้ในคอมพิวเตอร์ไคลเอนต์ หากเราเก็บไว้ใน LocalStorage / SessionStorage มันสามารถถูกโจมตีได้อย่างง่ายดายด้วยการโจมตี XSS หากเราเก็บไว้ในคุกกี้แฮ็กเกอร์สามารถใช้งานได้ (โดยไม่ต้องอ่าน) ในการโจมตี CSRF และปลอมตัวเป็นผู้ใช้และติดต่อ API ของเราและส่งคำขอเพื่อดำเนินการหรือรับข้อมูลในนามของผู้ใช้
แต่มีหลายวิธีในการรักษาความปลอดภัย JWT ในคุกกี้เพื่อไม่ให้ถูกขโมยได้ง่าย (แต่ยังมีเทคนิคขั้นสูงบางอย่างในการขโมย) แต่ถ้าคุณต้องการพึ่ง LocalStorage / SessionStorage คุณสามารถเข้าถึง XSS ได้ง่ายๆ
ดังนั้นเพื่อแก้ปัญหา CSRF ฉันใช้ Double ส่งคุกกี้ในแอปพลิเคชันของฉัน
วิธีส่งคุกกี้สองครั้ง
เก็บ JWT ในคุกกี้ HttpOnly และใช้ในโหมดปลอดภัยเพื่อถ่ายโอนผ่าน HTTPS
การโจมตี CSRF ส่วนใหญ่มีต้นกำเนิดหรือส่วนหัวผู้อ้างอิงที่แตกต่างกับโฮสต์ดั้งเดิมของคุณในคำขอของพวกเขา ดังนั้นตรวจสอบว่าคุณมีส่วนใดส่วนหนึ่งในส่วนหัวหรือไม่พวกเขามาจากโดเมนของคุณหรือไม่! ถ้าไม่ปฏิเสธพวกเขา หากทั้งแหล่งกำเนิดและผู้อ้างอิงไม่สามารถใช้ได้ในคำขอก็ไม่ต้องกังวล คุณสามารถพึ่งพาผลลัพธ์ของการตรวจสอบความถูกต้องของส่วนหัว X-XSRF-TOKEN ซึ่งฉันได้อธิบายไว้ในขั้นตอนถัดไป
ในขณะที่เบราว์เซอร์จะจัดหาคุกกี้ของคุณโดยอัตโนมัติสำหรับโดเมนของคำขอนั้นมีข้อ จำกัด ที่มีประโยชน์: รหัส JavaScript ที่ทำงานบนเว็บไซต์ไม่สามารถอ่านคุกกี้ของเว็บไซต์อื่น ๆ ได้ เราสามารถใช้ประโยชน์จากสิ่งนี้เพื่อสร้างโซลูชัน CSRF ของเรา เพื่อป้องกันการโจมตีของ CSRF เราต้องสร้างคุกกี้ Javascript ที่อ่านได้พิเศษซึ่งเรียกว่า: XSRF-TOKEN คุกกี้นี้จะต้องสร้างขึ้นเมื่อผู้ใช้เข้าสู่ระบบและควรมีสตริงสุ่มและไม่สามารถคาดเดาได้ นอกจากนี้เรายังบันทึกหมายเลขนี้ใน JWT เองเพื่อเป็นการอ้างสิทธิ์ส่วนตัว ทุกครั้งที่แอปพลิเคชัน JavaScript ต้องการที่จะขอมันจะต้องอ่านโทเค็นนี้และส่งไปในส่วนหัว HTTP ที่กำหนดเอง เนื่องจากการดำเนินการเหล่านี้ (อ่านคุกกี้การตั้งค่าส่วนหัว) สามารถทำได้ในโดเมนเดียวกันของแอปพลิเคชัน JavaScript เท่านั้น
Angular JS ทำให้ชีวิตของคุณง่ายขึ้น
โชคดีที่ฉันใช้ Angular JS ในแพลตฟอร์มของเราและจัดทำแพ็คเกจโทเค็น CSRF โทเค็นทำให้มันง่ายขึ้นสำหรับเราที่จะใช้ สำหรับทุกคำขอที่แอปพลิเคชันของเราทำกับเซิร์ฟเวอร์$http
บริการAngular จะทำสิ่งเหล่านี้โดยอัตโนมัติ:
- ค้นหาคุกกี้ชื่อ XSRF-TOKEN บนโดเมนปัจจุบัน
- หากพบคุกกี้นั้นจะอ่านค่าและเพิ่มลงในคำขอเป็นส่วนหัว X-XSRF-TOKEN
ดังนั้นการใช้งานฝั่งไคลเอ็นต์จึงได้รับการจัดการโดยอัตโนมัติ! เราเพียงแค่ต้องตั้งชื่อคุกกี้XSRF-TOKEN
ในโดเมนปัจจุบันในฝั่งเซิร์ฟเวอร์และเมื่อ API ของเราได้รับการเรียกจากลูกค้านั้นจะต้องตรวจสอบX-XSRF-TOKEN
ส่วนหัวและเปรียบเทียบกับXSRF-TOKEN
ใน JWT หากพวกเขาตรงกันผู้ใช้จะเป็นจริง มิฉะนั้นจะเป็นคำขอปลอมและคุณสามารถเพิกเฉยได้ วิธีนี้ได้รับแรงบันดาลใจจากวิธี "ส่งคุกกี้คู่"
ความระมัดระวัง
ในความเป็นจริงคุณยังคงไวต่อ XSS เป็นเพียงผู้โจมตีที่ไม่สามารถขโมยโทเค็น JWT ของคุณเพื่อใช้ในภายหลัง แต่เขายังสามารถร้องขอในนามของผู้ใช้โดยใช้ XSS
ไม่ว่าคุณจะจัดเก็บ JWT ของคุณในlocalStorage
หรือคุณเก็บ XSRF-token ของคุณไว้ในไม่ใช่คุกกี้ HttpOnly ทั้งคู่สามารถคว้า XSS ได้อย่างง่ายดาย แม้ JWT ของคุณใน HttpOnly คุกกี้สามารถคว้าโดยการโจมตี XSS ขั้นสูงเช่นวิธี XST
ดังนั้นนอกเหนือจากวิธีการส่งคุกกี้คู่คุณต้องปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดกับ XSS รวมถึงการหลบหนีเนื้อหา นี่หมายถึงการลบรหัสที่ใช้งานได้ซึ่งจะทำให้เบราว์เซอร์ทำสิ่งที่คุณไม่ต้องการ โดยทั่วไปหมายถึงการลบ// <![CDATA[
แท็กและแอตทริบิวต์ HTML ที่ทำให้ JavaScript ได้รับการประเมิน
อ่านเพิ่มเติมได้ที่นี่: