แนวทางปฏิบัติที่ดีที่สุดสำหรับการจัดการโทเค็น JWT ทางฝั่งเซิร์ฟเวอร์ [ปิด]


111

(เกิดจากหัวข้อนี้ตั้งแต่นี้เป็นจริงคำถามที่เฉพาะเจาะจงของตัวเองและไม่ให้ NodeJS ฯลฯ )

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

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

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

สิ่งนี้นำฉันไปสู่คำถาม:

1) การตรวจสอบโทเค็น JWT ควร จำกัด เฉพาะการตรวจสอบลายเซ็นของโทเค็นโดยอาศัยความสมบูรณ์ของข้อมูลลับของเซิร์ฟเวอร์เพียงอย่างเดียวหรือมาพร้อมกับกลไกการตรวจสอบที่แยกต่างหาก

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

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

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

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


1
มีคำถามดีๆ Re: คำถามที่ 2 ฉันมีปัญหาเดียวกันกับคีย์ลับใด ๆ ที่เก็บไว้ที่ฝั่งเซิร์ฟเวอร์ หากคุณทำการจับคู่แฮชหรือการถอดรหัสแบบอสมมาตรไม่ว่าจะเป็นการลงนาม jwt หรือถอดรหัสข้อมูล cc ที่เก็บไว้ในฐานข้อมูลคุณจะต้องมีรหัสลับที่สามารถเข้าถึงได้ด้วยรหัสบนเซิร์ฟเวอร์ แล้วคุณเก็บมันไว้ที่ไหน ?? นี่คือคำตอบที่ดีที่สุดที่ฉันพบ: pcinetwork.org/forum/index.php?threads/… - อาจปลอดภัยพอ ๆ กับคีย์ jwt ด้วย
jbd

รหัสลับในโทเค็น jwt คืออะไร? ฉันคิดว่า jwt token เป็นความลับ หรือคีย์ลับได้RSAPrivateKey privateKey??
kittu

3
สิ่งนี้ถูกถามเมื่อไม่นานมานี้ แต่อาจมีคนคิดว่ามีประโยชน์ ในกรณีของฉันฉันมี "รหัสลับ" ต่อผู้ใช้ ดังนั้นทุกครั้งที่ผู้ใช้เข้าสู่ระบบฉันจะสร้างความลับนั้นและจัดเก็บพร้อมกับบันทึกผู้ใช้ในฐานข้อมูล ฉันตรวจสอบโทเค็นโดยใช้ความลับนั้น เมื่อออกจากระบบฉันจะล้างค่านั้น สิ่งนี้จะทำให้โทเค็นอื่น ๆ ที่สร้างไว้ก่อนหน้านี้เป็นโมฆะโดยอัตโนมัติ (นั่นคือสิ่งที่ฉันต้องการ)
Nelson Rodriguez

คำตอบ:


52

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

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

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

สำหรับคำถามของคุณ:

1. ) จากประสบการณ์ที่ จำกัด ของฉันการยืนยันโทเค็นของคุณด้วยระบบที่สองจะดีกว่าแน่นอน เพียงแค่ตรวจสอบลายเซ็นก็หมายความว่าโทเค็นถูกสร้างขึ้นด้วยความลับของคุณ การจัดเก็บโทเค็นที่สร้างขึ้นใน DB บางประเภท (redis, memcache / sql / mongo หรือที่เก็บข้อมูลอื่น ๆ ) เป็นวิธีที่ยอดเยี่ยมในการรับรองว่าคุณยอมรับโทเค็นที่เซิร์ฟเวอร์ของคุณสร้างขึ้นเท่านั้น ในสถานการณ์นี้แม้ว่าความลับของคุณจะรั่วไหล แต่ก็ไม่สำคัญมากนักเนื่องจากโทเค็นที่สร้างขึ้นจะไม่สามารถใช้งานได้ นี่เป็นแนวทางที่ฉันใช้กับระบบของฉัน - โทเค็นที่สร้างขึ้นทั้งหมดจะถูกเก็บไว้ใน DB (redis) และในแต่ละคำขอฉันตรวจสอบว่าโทเค็นอยู่ในฐานข้อมูลของฉันก่อนที่ฉันจะยอมรับ วิธีนี้สามารถเพิกถอนโทเค็นได้ไม่ว่าจะด้วยเหตุผลใดก็ตามเช่นโทเค็นที่ถูกปล่อยออกสู่ป่าอย่างใดอย่างหนึ่งการล็อกเอาต์ของผู้ใช้การเปลี่ยนรหัสผ่านการเปลี่ยนแปลงความลับเป็นต้น

2. ) นี่เป็นสิ่งที่ฉันไม่มีประสบการณ์มากนักและเป็นสิ่งที่ฉันยังคงค้นคว้าอย่างจริงจังเนื่องจากฉันไม่ใช่ผู้เชี่ยวชาญด้านความปลอดภัย หากคุณพบแหล่งข้อมูลใด ๆ อย่าลังเลที่จะโพสต์ที่นี่! ตอนนี้ฉันแค่ใช้คีย์ส่วนตัวที่โหลดจากดิสก์ แต่เห็นได้ชัดว่านั่นยังห่างไกลจากโซลูชันที่ดีที่สุดหรือปลอดภัยที่สุด


5
สำหรับประเด็นที่สองนี่คือคำตอบที่ดี: security.stackexchange.com/questions/87130/…
Bossliaw

1
เนื่องจากโทเค็นมีอยู่ในส่วนหัวจะเกิดอะไรขึ้นหากโทเค็นถูกขโมยและมีผู้ประสงค์ร้ายพยายามเข้าสู่ระบบด้วยโทเค็นนั้น (โดยรับรู้ที่อยู่อีเมลของผู้ใช้)
kittu

22
หากคุณจัดเก็บ JWT ทุกๆ JWT จะไม่มีประโยชน์ต่อ JWT และคุณอาจยึดติดกับรหัสเซสชันแบบสุ่ม
ColinM

46

สิ่งที่ควรพิจารณาเมื่อนำ JWT ไปใช้ในแอปพลิเคชันของคุณมีดังนี้

  • รักษาอายุการใช้งาน JWT ของคุณให้สั้นและมีการจัดการตลอดอายุการใช้งานที่เซิร์ฟเวอร์ หากคุณไม่ทำและต้องการข้อมูลเพิ่มเติมใน JWT ของคุณในภายหลังคุณจะต้องรองรับ 2 เวอร์ชันหรือรอจนกว่า JWT รุ่นเก่าของคุณจะหมดอายุก่อนจึงจะสามารถใช้การเปลี่ยนแปลงได้ คุณสามารถจัดการได้อย่างง่ายดายบนเซิร์ฟเวอร์หากคุณดูเฉพาะiatฟิลด์ใน jwt และไม่สนใจexpฟิลด์นั้น

  • พิจารณารวม url ของคำขอใน JWT ของคุณ ตัวอย่างเช่นหากคุณต้องการให้ JWT ของคุณถูกใช้ที่จุดสิ้นสุด/my/test/pathให้รวมฟิลด์เช่น'url':'/my/test/path'ใน JWT ของคุณเพื่อให้แน่ใจว่ามันเคยถูกใช้ในเส้นทางนี้เท่านั้น หากไม่ทำเช่นนั้นคุณอาจพบว่าผู้คนเริ่มใช้ JWT ของคุณที่จุดสิ้นสุดอื่นแม้กระทั่งสิ่งที่พวกเขาไม่ได้สร้างขึ้น คุณสามารถพิจารณารวม md5 (url) แทนได้เนื่องจากการมี url ขนาดใหญ่ใน JWT จะทำให้ JWT ใหญ่ขึ้นมากและอาจมีขนาดใหญ่มาก

  • การหมดอายุของ JWT ควรกำหนดได้ตามกรณีการใช้งานหากมีการนำ JWT มาใช้ใน API ตัวอย่างเช่นหากคุณมี 10 จุดสิ้นสุดสำหรับ 10 กรณีการใช้งานที่แตกต่างกันสำหรับ JWT ตรวจสอบให้แน่ใจว่าคุณสามารถกำหนดให้จุดสิ้นสุดแต่ละจุดยอมรับ JWT ที่หมดอายุในเวลาที่ต่างกัน วิธีนี้ช่วยให้คุณสามารถล็อกจุดสิ้นสุดบางจุดได้มากกว่าจุดอื่น ๆ เช่นข้อมูลที่ให้บริการโดยจุดสิ้นสุดหนึ่งมีความละเอียดอ่อนมาก

  • แทนที่จะทำให้ JWT หมดอายุภายในระยะเวลาหนึ่งให้ลองใช้ JWT ที่รองรับทั้งสองอย่าง:

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

  • พิจารณาเพิกเฉยต่อ "ส่วนหัว" ของ JWT ของคุณเนื่องจากข้อมูลรั่วไหลและให้มาตรการควบคุมแก่แฮกเกอร์ ส่วนใหญ่เกี่ยวข้องกับalgฟิลด์ในส่วนหัว - อย่าสนใจสิ่งนี้และสมมติว่าส่วนหัวเป็นสิ่งที่คุณต้องการสนับสนุนเนื่องจากหลีกเลี่ยงแฮกเกอร์ที่พยายามใช้Noneอัลกอริทึมซึ่งจะลบการตรวจสอบความปลอดภัยของลายเซ็น

  • JWT ควรมีตัวระบุที่ระบุรายละเอียดว่าแอปใดสร้างโทเค็น ตัวอย่างเช่นหาก JWT ของคุณถูกสร้างขึ้นโดยไคลเอนต์ 2 ตัว mychat และ myclassifiedsapp แต่ละรายการควรมีชื่อโปรเจ็กต์หรือชื่อที่คล้ายกันในฟิลด์ "iss" ใน JWT เช่น "iss": "mychat"

  • ไม่ควรล็อกไฟล์ JWT ในล็อกไฟล์ เนื้อหาของ JWT สามารถบันทึกได้ แต่ไม่ใช่ JWT เอง สิ่งนี้ช่วยให้มั่นใจได้ว่า devs หรือคนอื่น ๆ ไม่สามารถดึง JWT จากไฟล์บันทึกและทำสิ่งต่างๆกับบัญชีผู้ใช้รายอื่นได้
  • ตรวจสอบให้แน่ใจว่าการใช้งาน JWT ของคุณไม่อนุญาตให้ใช้อัลกอริทึม "ไม่มี" เพื่อหลีกเลี่ยงไม่ให้แฮกเกอร์สร้างโทเค็นโดยไม่ได้ลงนาม ข้อผิดพลาดระดับนี้สามารถหลีกเลี่ยงได้ทั้งหมดโดยไม่สนใจ "ส่วนหัว" ของ JWT ของคุณ
  • พิจารณาใช้iat(ออกที่) แทนexp(หมดอายุ) ใน JWT ของคุณ ทำไม? เนื่องจากiatโดยพื้นฐานแล้วหมายถึงเวลาที่ JWT สร้างขึ้นสิ่งนี้จะช่วยให้คุณสามารถปรับเปลี่ยนบนเซิร์ฟเวอร์เมื่อ JWT หมดอายุตามวันที่สร้าง หากใครสักคนผ่านไปในอีกexp20 ปีข้างหน้า JWT โดยพื้นฐานแล้วจะมีชีวิตอยู่ตลอดไป! โปรดทราบว่าคุณจะหมดอายุ JWT โดยอัตโนมัติหากiatเป็นในอนาคต แต่อนุญาตให้มีห้องกระดิกเล็กน้อย (เช่น 10 วินาที) ในกรณีที่เวลาของไคลเอนต์ไม่ตรงกับเวลาเซิร์ฟเวอร์เล็กน้อย
  • พิจารณาใช้จุดสิ้นสุดสำหรับการสร้าง JWT จากเพย์โหลด json และบังคับให้ไคลเอนต์ที่ใช้งานทั้งหมดของคุณใช้ปลายทางนี้เพื่อสร้าง JWT ของพวกเขา วิธีนี้ช่วยให้มั่นใจได้ว่าคุณสามารถแก้ไขปัญหาด้านความปลอดภัยที่คุณต้องการด้วยวิธีสร้าง JWT ในที่เดียวได้อย่างง่ายดาย เราไม่ได้ทำสิ่งนี้ในแอปของเราโดยตรงและตอนนี้ต้องค่อยๆปล่อยการอัปเดตความปลอดภัยฝั่งเซิร์ฟเวอร์ JWT เนื่องจากไคลเอนต์ 5 รายของเราต้องใช้เวลาในการใช้งาน นอกจากนี้ทำให้ปลายทางการสร้างของคุณยอมรับอาร์เรย์ของเพย์โหลด json สำหรับ JWT เพื่อสร้างและสิ่งนี้จะลด # ของคำขอ http ที่เข้ามาในปลายทางนี้สำหรับลูกค้าของคุณ
  • หากจะใช้ JWT ของคุณที่จุดสิ้นสุดที่รองรับการใช้งานตามเซสชันด้วยตรวจสอบให้แน่ใจว่าคุณไม่ได้ใส่อะไรลงใน JWT ที่จำเป็นเพื่อตอบสนองคำขอ คุณสามารถทำได้อย่างง่ายดายหากคุณแน่ใจว่าจุดสิ้นสุดของคุณทำงานกับเซสชันเมื่อไม่มีการให้ JWT
  • ดังนั้นโดยทั่วไปการพูดของ JWT จะลงท้ายด้วย userId หรือ groupId ของบางประเภทและอนุญาตให้เข้าถึงส่วนหนึ่งของระบบของคุณตามข้อมูลนี้ ตรวจสอบให้แน่ใจว่าคุณไม่อนุญาตให้ผู้ใช้ในพื้นที่ส่วนหนึ่งของแอปของคุณแอบอ้างเป็นผู้ใช้รายอื่นโดยเฉพาะอย่างยิ่งหากสิ่งนี้ให้การเข้าถึงข้อมูลที่ละเอียดอ่อน ทำไม? แม้ว่ากระบวนการสร้าง JWT ของคุณจะสามารถเข้าถึงได้เฉพาะกับบริการ "ภายใน" แต่ devs หรือทีมงานภายในอื่น ๆ ก็สามารถสร้าง JWT เพื่อเข้าถึงข้อมูลสำหรับผู้ใช้รายใดก็ได้เช่น CEO ของ บริษัท ของลูกค้าแบบสุ่ม ตัวอย่างเช่นหากแอปของคุณให้การเข้าถึงบันทึกทางการเงินสำหรับลูกค้าจากนั้นโดยการสร้าง JWT นักพัฒนาสามารถคว้าบันทึกทางการเงินของ บริษัท ใด ๆ ได้เลย! และหากแฮ็กเกอร์เข้ามาในเครือข่ายภายในของคุณพวกเขาก็สามารถทำได้เช่นเดียวกัน
  • หากคุณกำลังจะอนุญาตให้มีการแคช URL ที่มี JWT ไม่ว่าด้วยวิธีใดก็ตามตรวจสอบให้แน่ใจว่ามีการรวมสิทธิ์สำหรับผู้ใช้ที่แตกต่างกันไว้ใน url ไม่ใช่ JWT ทำไม? เนื่องจากผู้ใช้อาจได้รับข้อมูลที่ไม่ควรทำ ตัวอย่างเช่นสมมติว่ามีผู้ใช้ขั้นสูงลงชื่อเข้าใช้แอปของคุณและขอ URL ต่อไปนี้/mysite/userInfo?jwt=XXXและ URL นี้จะถูกแคช พวกเขาออกจากระบบและสองสามนาทีต่อมาผู้ใช้ทั่วไปก็เข้าสู่ระบบแอปของคุณ พวกเขาจะได้รับเนื้อหาแคช - พร้อมข้อมูลเกี่ยวกับผู้ใช้ขั้นสูง! สิ่งนี้มีแนวโน้มที่จะเกิดขึ้นน้อยลงในไคลเอนต์และอื่น ๆ บนเซิร์ฟเวอร์โดยเฉพาะอย่างยิ่งในกรณีที่คุณใช้ CDN เช่น Akamai และคุณปล่อยให้ไฟล์บางไฟล์ใช้งานได้นานขึ้น สิ่งนี้สามารถแก้ไขได้โดยรวมข้อมูลผู้ใช้ที่เกี่ยวข้องใน url และตรวจสอบความถูกต้องบนเซิร์ฟเวอร์แม้กระทั่งสำหรับคำขอแคชเช่น/mysite/userInfo?id=52&jwt=XXX
  • หาก JWT ของคุณมีจุดมุ่งหมายเพื่อนำมาใช้เช่นคุกกี้เซสชั่นและมีเพียงควรจะทำงานในเครื่องเดียวกัน JWT ที่ถูกสร้างขึ้นสำหรับคุณควรพิจารณาเพิ่มJTIฟิลด์ JWT ของคุณ โดยพื้นฐานแล้วนี่คือโทเค็น CSRF ซึ่งทำให้แน่ใจว่า JWT ของคุณไม่สามารถส่งผ่านจากเบราว์เซอร์ของผู้ใช้รายหนึ่งไปยังอีกเบราว์เซอร์ได้

1
สิ่งที่คุณอ้างถึงcreated_byมีการอ้างสิทธิ์ใน JWT อยู่แล้วและเรียกว่าiss(ผู้ออก)
Fred

ใช่จุดที่ดี - ฉันจะอัปเดตว่า ... ขอบคุณ!
Brad Parks

8

ฉันไม่คิดว่าฉันเป็นผู้เชี่ยวชาญ แต่ฉันอยากจะแบ่งปันข้อมูลเกี่ยวกับ Jwt

  • 1: ดังที่ Akshay กล่าวว่าควรมีระบบที่สองเพื่อตรวจสอบความถูกต้องของโทเค็นของคุณ

    a: วิธีที่ฉันจัดการ: ฉันเก็บแฮชที่สร้างไว้ในที่เก็บเซสชันพร้อมกับเวลาที่หมดอายุ ในการตรวจสอบโทเค็นจำเป็นต้องมีการออกโดยเซิร์ฟเวอร์

    ข: มีอย่างน้อยหนึ่งอย่างที่ต้องตรวจสอบวิธีการเซ็นที่ใช้ เช่น :

    header :
    {
      "alg": "none",
      "typ": "JWT"
    }
    

ไลบรารีบางแห่งที่ตรวจสอบ JWT จะยอมรับอันนี้โดยไม่ต้องตรวจสอบแฮช นั่นหมายความว่าโดยไม่ทราบว่าเกลือของคุณใช้ในการเซ็นโทเค็นแฮ็กเกอร์สามารถให้สิทธิ์บางอย่างแก่ตนเองได้ ตรวจสอบให้แน่ใจเสมอว่าสิ่งนี้จะไม่เกิดขึ้น https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/

c.: การใช้คุกกี้กับรหัสเซสชันจะไม่มีประโยชน์ในการตรวจสอบโทเค็นของคุณ หากมีคนต้องการจี้เซสชันของผู้ใช้แลมด้าเขาก็ต้องใช้สนิฟเฟอร์ (เช่น Wireshark) แฮ็กเกอร์รายนี้จะมีข้อมูลทั้งสองอย่างในเวลาเดียวกัน

  • 2:ความลับทุกอย่างก็เหมือนกัน มีทางที่จะรู้ได้เสมอ

วิธีที่ฉันจัดการกับมันเชื่อมโยงกับประเด็นที่ 1 a. : ฉันมีความลับผสมกับตัวแปรสุ่ม ความลับนี้ไม่ซ้ำกันสำหรับทุกโทเค็น

อย่างไรก็ตามฉันพยายามทำความเข้าใจแนวทางปฏิบัติที่ดีที่สุดว่าควรตรวจสอบโทเค็นอย่างไรและเพียงใดเพื่อสร้างระบบที่ปลอดภัยอย่างแท้จริง

หากคุณต้องการความปลอดภัยที่ดีที่สุดคุณไม่ควรทำตามแนวทางปฏิบัติที่ดีที่สุดแบบสุ่มสี่สุ่มห้า วิธีที่ดีที่สุดคือทำความเข้าใจว่าคุณกำลังทำอะไรอยู่ (ฉันคิดว่ามันโอเคเมื่อฉันเห็นคำถามของคุณ) จากนั้นจึงประเมินความปลอดภัยที่คุณต้องการ และหากมอสสาดต้องการเข้าถึงข้อมูลที่เป็นความลับของคุณพวกเขาจะหาทางเสมอ (ฉันชอบบล็อกโพสต์นี้: https://www.schneier.com/blog/archives/2015/08/mickens_on_secu.html )


จุดที่ดีสำหรับการมีความลับเฉพาะสำหรับทุกโทเค็น แต่คุณจะสร้างความลับเฉพาะในแต่ละครั้งได้อย่างไร? ฉันใช้ห้องสมุด nimbus jwt
kittu

1
อาจใช้รหัสผ่านแฮชของผู้ใช้ของคุณ
momokjaaaaa

1
"ถ้าคุณไม่ได้ทำในแบบเดียวกับที่คนอื่นทำคนอื่นจะหาทางผ่านความปลอดภัยของคุณได้ยากขึ้น" ฟังดูเหมือนความปลอดภัยผ่านความคลุมเครือสำหรับฉัน แนวทางปฏิบัติที่ดีที่สุดเรียกว่าเพราะลดความเสี่ยงที่พบบ่อยที่สุดในทางปฏิบัติ
Mnebuerquo

@Mnebuerquo ฉันเห็นด้วยกับคุณคนที่เขียนว่าไม่ควรเชื่อถือ ;-)
Deblaton Jean-Philippe

1
เขาถูกต้องแม้ว่าคนนั้นไม่ควรทำตามแนวทางปฏิบัติที่ดีที่สุดแบบสุ่มสี่สุ่มห้า มันเป็นสิ่งที่ดีที่จะเข้าใจว่าทำไมปฏิบัติที่ดีที่สุดได้รับการพิจารณาที่ดีที่สุด ในการตัดสินใจออกแบบการรักษาความปลอดภัยทุกครั้งจะมีการแลกเปลี่ยนระหว่างความปลอดภัยและการใช้งาน การทำความเข้าใจสาเหตุหมายความว่าคุณสามารถตัดสินใจได้อย่างชาญฉลาด (ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดแม้ว่าผู้ใช้ของคุณจะไม่ทำก็ตาม)
Mnebuerquo

3

คำตอบดีๆมากมายที่นี่ ฉันจะรวมคำตอบบางส่วนที่ฉันคิดว่าเกี่ยวข้องมากที่สุดและเพิ่มคำแนะนำเพิ่มเติม

1) การตรวจสอบโทเค็น JWT ควร จำกัด เฉพาะการตรวจสอบลายเซ็นของโทเค็นโดยอาศัยความสมบูรณ์ของข้อมูลลับของเซิร์ฟเวอร์เพียงอย่างเดียวหรือมาพร้อมกับกลไกการตรวจสอบที่แยกต่างหาก

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

มาตรการรักษาความปลอดภัยอื่น ๆ รวมถึงการไม่บันทึก JWT และต้องใช้อัลกอริทึมการลงนามที่ปลอดภัยเช่น SHA256

2) หากการตรวจสอบลายเซ็น JWT เป็นวิธีเดียวในการตรวจสอบโทเค็นซึ่งหมายความว่าความสมบูรณ์ของความลับของเซิร์ฟเวอร์คือจุดแตกหักความลับของเซิร์ฟเวอร์ควรได้รับการจัดการอย่างไร?

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

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

อย่างไรก็ตามระบบเพื่อลดความเสียหายของความลับของเซิร์ฟเวอร์ที่ถูกบุกรุกและหลีกเลี่ยงการจัดเก็บความลับในซอร์สโค้ดนั้นเกี่ยวข้องกับการหมุนเวียนโทเค็นลับโดยใช้บริการประสานงานเช่นhttps://zookeeper.apache.org. ใช้งาน cron เพื่อสร้างความลับของแอปทุกๆสองสามชั่วโมงหรือมากกว่านั้น (ไม่ว่าโทเค็นการเข้าถึงของคุณจะใช้ได้นานแค่ไหนก็ตาม) และส่งข้อมูลลับที่อัปเดตไปยัง Zookeeper ในแต่ละแอ็พพลิเคชันเซิร์ฟเวอร์ที่ต้องการทราบความลับของโทเค็นให้กำหนดค่าไคลเอ็นต์ ZK ที่อัพเดตเมื่อใดก็ตามที่ค่าโหนด ZK เปลี่ยนแปลง จัดเก็บความลับหลักและความลับรองและทุกครั้งที่มีการเปลี่ยนแปลงความลับของโทเค็นให้ตั้งค่าความลับโทเค็นใหม่เป็นความลับหลักและโทเค็นเก่าเป็นความลับรอง ด้วยวิธีนี้โทเค็นที่ถูกต้องที่มีอยู่จะยังคงใช้ได้เนื่องจากจะถูกตรวจสอบเทียบกับความลับรอง เมื่อความลับรองถูกแทนที่ด้วยความลับหลักแบบเก่าโทเค็นการเข้าถึงทั้งหมดที่ออกด้วยความลับรองจะหมดอายุอย่างไรก็ตาม


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