JWT ควรเก็บไว้ใน localStorage หรือคุกกี้? [ซ้ำ]


105

สำหรับวัตถุประสงค์ของการรักษาความปลอดภัย REST API ที่ใช้ JWT ตามวัสดุบางอย่าง (เช่นนี้คู่มือและคำถาม ) ที่ JWT สามารถเก็บไว้ในทั้งlocalStorageหรือคุกกี้ ตามความเข้าใจของฉัน:

  • localStorageอยู่ภายใต้ XSS และโดยทั่วไปไม่แนะนำให้เก็บข้อมูลที่ละเอียดอ่อนใด ๆ ไว้ในนั้น
  • ด้วยคุกกี้เราสามารถใช้แฟล็ก "httpOnly" ซึ่งช่วยลดความเสี่ยงของ XSS ได้ อย่างไรก็ตามหากเราต้องการอ่าน JWT จากคุกกี้ในแบ็กเอนด์เราจะต้องอยู่ภายใต้ CSRF

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

ความเข้าใจของฉันถูกต้องหรือไม่? หากเป็นเช่นนั้นแนวทางข้างต้นมีข้อกังวลด้านความปลอดภัยหรือไม่? หรือจริงๆแล้วเราสามารถใช้งาน localStorage ได้ตั้งแต่แรก?


4
ตรวจสอบสิ่งนี้: cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions
corlaez

@ lrn2prgrm เนื่องจากไม่ควรใช้ (stateless) JWT และ (stateful) semantics ร่วมกัน
ozanmuyes

@corlaez ฉันใช้ JWT และฉันวางแผนที่จะใช้ Authentication header "Bearer mytoken" บนฝั่งเซิร์ฟเวอร์เพื่อตรวจสอบ jwt ของฉัน ความสับสนของฉันคือ: ถ้าฉันส่ง jwt ดั้งเดิมในคุกกี้เมื่อเข้าสู่ระบบครั้งแรก (ส่งจากเซิร์ฟเวอร์ไปยังเบราว์เซอร์) ด้วยแฟล็ก httpOnly ฉันจะแยก jwt จากฝั่งไคลเอ็นต์เพื่อใส่ในส่วนหัวการพิสูจน์ตัวตนสำหรับคำขอในภายหลังได้อย่างไร การตั้งค่าสถานะ httpOnly จะไม่อนุญาตให้ฉันดึงข้อมูลจากคุกกี้ทางฝั่งไคลเอ็นต์ใช่หรือไม่
Harshit Trehan

คำตอบ:


60

ฉันชอบวิธี XSRF Double Submit Cookies ที่กล่าวถึงในบทความที่ @ pkid169 กล่าว แต่มีสิ่งหนึ่งที่บทความไม่ได้บอกคุณ คุณยังไม่ได้รับการป้องกันจาก XSS เนื่องจากสิ่งที่ผู้โจมตีสามารถทำได้คือการแทรกสคริปต์ที่อ่านคุกกี้ CSRF ของคุณ (ซึ่งไม่ใช่ HttpOnly) จากนั้นส่งคำขอไปยังปลายทาง API ของคุณโดยใช้โทเค็น CSRF นี้พร้อมกับคุกกี้ JWT ที่จะถูกส่งโดยอัตโนมัติ

ดังนั้นในความเป็นจริงคุณยังคงอ่อนไหวต่อ XSS แต่ผู้โจมตีไม่สามารถขโมยโทเค็น JWT ของคุณเพื่อใช้ในภายหลังได้ แต่เขายังสามารถร้องขอในนามผู้ใช้ของคุณโดยใช้ XSS ได้

ไม่ว่าคุณจะจัดเก็บ JWT ของคุณไว้ใน localStorage หรือคุณเก็บโทเค็น XSRF ของคุณไว้ในคุกกี้ที่ไม่ใช่ http อย่างเดียวทั้งสองอย่างก็สามารถคว้าได้โดย XSS แม้แต่ JWT ของคุณในคุกกี้ HttpOnly ก็สามารถคว้าได้ด้วยการโจมตี XSS ขั้นสูง

ดังนั้นนอกเหนือจากวิธี Double Submit Cookies แล้วคุณต้องปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดกับ XSS รวมถึงการหลีกเลี่ยงเนื้อหาด้วย ซึ่งหมายถึงการลบโค้ดปฏิบัติการใด ๆ ที่อาจทำให้เบราว์เซอร์ทำสิ่งที่คุณไม่ต้องการ โดยทั่วไปหมายถึงการลบ // <! [CDATA [แท็กและแอตทริบิวต์ HTML ที่ทำให้ JavaScript ได้รับการประเมิน


12
คุณช่วยอธิบายได้ไหมว่า JWT ในคุกกี้ HttpOnly สามารถคว้าได้อย่างไร XSRF สามารถใช้งานได้หากโทเค็น XSRF ถูกทำลายโดย XSS แต่จะสามารถคว้าได้จริงหรือ?
Jacek Gorgoń

1
ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ฉันต้องการถามคำถาม ... นั่นหมายความว่าสคริปต์ที่สร้างมาอย่างดีสามารถอ่านได้ทั้ง localStorage และคุกกี้หรือไม่? ถ้าเป็นเช่นนั้นจะปลอดภัยหรือไม่ที่จะสันนิษฐานว่า JWT อาจถูกขโมยไม่ว่าเราจะเก็บไว้ที่ใดในเบราว์เซอร์ จากนั้นฉันรู้สึกว่าการพึ่งพา JWT เพียงอย่างเดียวนั้นมีความเสี่ยงมาก
Hiroki

2
"แม้แต่ JWT ของคุณในคุกกี้ HttpOnly ก็สามารถคว้าได้ด้วยการโจมตี XSS ขั้นสูง" เป็นเท็จ แก้ไขโพสต์ต้นฉบับเพื่อแก้ไขสิ่งนี้
java-addict301

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

"ฉีดสคริปต์ที่อ่านคุกกี้ CSRF ของคุณ (ซึ่งไม่ใช่ HttpOnly)" การใช้งานเริ่มต้นHtml.AntiForgeryToken()ใน ASP.NET MVC จะใช้คุกกี้ HttpOnly สำหรับโทเค็น CSRF ฉันคิดว่าคุณยังอ่อนไหวต่อ XSS บางตัว แต่คิดว่านี่เป็นสิ่งที่ควรค่าแก่การกล่าวถึง
Lovethenakedgun

22

โพสต์ทันเวลาจาก Stormpathได้อธิบายประเด็นของฉันอย่างละเอียดและตอบคำถามของฉัน

TL; ดร

เก็บ JWT ในคุกกี้จากนั้นส่งผ่าน JWT ในส่วนหัวการอนุญาตในทุกคำขอตามที่ฉันได้กล่าวไปหรือตามที่บทความแนะนำให้พึ่งพาแบ็กเอนด์เพื่อป้องกัน CSRF (เช่นใช้xsrfTokenในกรณีของ Angular)


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

CrossOrigin ไม่ได้หมายถึงสถานที่ตั้งจริง หมายถึงคำขอที่มาจากโดเมนอื่น ใน. net core เมื่อคุณตัดสินใจใช้ CORS คุณจะต้องระบุโดเมนที่คุณจะอนุญาต ส่วนหัวใดที่คุณจะอนุญาตเป็นต้น
Brian Allan West

12
  • อย่าจัดเก็บโทเค็นของคุณใน LocalStorage หรือ SessionStorage เนื่องจากโทเค็นดังกล่าวสามารถอ่านได้จากจาวาสคริปต์ดังนั้นจึงไม่สามารถใช้งานได้กับการโจมตี XSS
  • อย่าเก็บโทเค็นของคุณในคุกกี้ คุกกี้ (พร้อมแฟล็ก HttpOnly) เป็นตัวเลือกที่ดีกว่า - เป็น XSS ได้ง่าย แต่ก็ไม่สามารถใช้งานได้กับการโจมตี CSRF

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

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

ฉันขอแนะนำอย่างยิ่งให้อ่านบทความนี้: https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/


6
ทำไมความซับซ้อนที่เพิ่มเข้ามาเมื่อคุณสามารถถือว่าโทเค็นการรีเฟรชเป็นโทเค็นการเข้าถึงได้? วิธีการคือวิธีการนี้ได้รับความปลอดภัยมากขึ้นฉันทำเครื่องหมายการเข้าถึงของฉัน token เป็นsecure, samesite: strict, http-only?
Charming Robot

มันไม่ปลอดภัยมากกว่านี้
Chris Hawkes

3

เพื่อช่วยป้องกันการโจมตี CSRF ที่ใช้ประโยชน์จากคุกกี้ที่มีอยู่คุณสามารถตั้งค่าคุกกี้ของคุณด้วยSameSiteคำสั่ง ตั้งค่าเป็นlaxหรือstrictหรือ

นี่ยังคงเป็นแบบร่างและในปี 2019 เบราว์เซอร์ปัจจุบันทั้งหมดยังไม่รองรับทั้งหมดแต่ขึ้นอยู่กับความไวของข้อมูลของคุณและ / หรือการควบคุมเบราว์เซอร์ที่ผู้ใช้ของคุณใช้อาจเป็นตัวเลือกที่ใช้ได้ การตั้งค่าคำสั่งด้วยSameSite=laxจะช่วยให้ "การนำทางระดับบนสุดซึ่งใช้วิธี 'ปลอดภัย' ... HTTP"

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