ไทย

สิ่งที่ถอดรหัส JWT พิสูจน์ได้

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

สามส่วน สองส่วนเป็นเพียง JSON

JWT ในรูปแบบทั่วไปคือ JWS: ส่วน base64url สามส่วนคั่นด้วยจุด อันแรกคือส่วนหัว ส่วนอันที่สองคือเพย์โหลด ส่วนอันที่สามคือลายเซ็น

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

ผลที่ตามมานั้นคุ้มค่าที่จะระบุอย่างชัดเจนเพราะมันพลาดเป็นประจำ: อย่าเก็บสิ่งใดที่เป็นความลับไว้ในเพย์โหลด JWT ไม่ใช่รหัสผ่าน ไม่ใช่ตัวระบุสัญชาติแบบเต็ม ไม่ใช่รายละเอียดระบบภายใน สมมติว่าเพย์โหลดเป็นแบบสาธารณะ เพราะสำหรับใครก็ตามที่มีโทเค็น ก็เป็นอย่างนั้น

ส่วนที่สามคือลายเซ็น ซึ่งคำนวณจากสองส่วนแรก มันเป็นเพียงส่วนเดียวที่มีค่าความปลอดภัยใดๆ และเป็นส่วนที่ตัวถอดรหัสไม่สามารถประเมินได้

การถอดรหัสพิสูจน์อะไร: ไม่มีเลย

นี่คือประเด็นของคำแนะนำทั้งหมด การถอดรหัส JWT แยกวิเคราะห์สตริง base64url สองสตริงเป็น JSON เป็นการยืนยันว่าโทเค็นมีรูปแบบที่ดี ไม่ได้ยืนยันว่าโทเค็นเป็นของแท้ ว่าออกโดยฝ่ายที่มีชื่ออยู่ในข้อเรียกร้อง "iss" ว่าข้อเรียกร้องไม่ได้รับการแก้ไข หรือว่ามันเคยใช้ได้

ใครๆ ก็สามารถสร้างโทเค็นได้ รับ JWT ใดๆ เปลี่ยน "role": "user" เป็น "role": "admin" เข้ารหัสเพย์โหลดอีกครั้ง เย็บลายเซ็นใดๆ ที่ส่วนท้าย จากนั้นตัวถอดรหัสจะแสดงการอ้างสิทธิ์ที่คุณแก้ไขแล้วอย่างมั่นใจเหมือนกับที่แสดงต้นฉบับ ไม่มีทางทราบความแตกต่างได้ เนื่องจากการตรวจสอบความแตกต่างนั้นเป็นการดำเนินการที่แตกต่างกันซึ่งต้องใช้คีย์ที่ตัวถอดรหัสไม่มี

ดังนั้นเมื่อตัวถอดรหัส — อันนี้หรืออย่างอื่น — แสดง "exp: 2026-01-01" ให้กับคุณ สิ่งที่มันบอกคุณจริงๆ คือ โทเค็นนี้มีการอ้างว่ามันจะหมดอายุในวันนั้น การเรียกร้องนั้นมีความหมายหรือไม่นั้นขึ้นอยู่กับว่าลายเซ็นนั้นถูกต้องหรือไม่ซึ่งยังไม่ได้ตรวจสอบ

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

เหตุใดเครื่องมือนี้จึงไม่เสนอการยืนยัน

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

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

อัลกอริธึมเป็นปัญหาเล็กๆ น้อยๆ และเป็นแหล่งที่มาของการโจมตีที่ทราบกันดีถึงสองครั้ง อย่างแรกคือ alg: "none": ส่วนหัวอ้างว่าโทเค็นไม่ได้ลงนาม และผู้ตรวจสอบที่ให้เกียรติส่วนหัวมากกว่าการกำหนดค่าของตัวเองจะยอมรับสิ่งใดๆ อย่างที่สองคือความสับสน RS256-to-HS256 ผู้โจมตีใช้รหัสสาธารณะ ซึ่งตามคำจำกัดความแล้ว สาธารณะ เปลี่ยนส่วนหัวเป็น HS256 และลงนามโทเค็นโดยใช้รหัสสาธารณะนั้นเป็นความลับ HMAC ตัวตรวจสอบที่อ่านอัลกอริธึมจากโทเค็นและค้นหา "คีย์" จะตรวจสอบความถูกต้อง

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

ทำไมไม่วางโทเค็นการผลิตไว้ที่ใดก็ได้

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

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

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

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

การอ่านข้อเรียกร้องที่สำคัญ

RFC 7519 ลงทะเบียนชื่อการอ้างสิทธิ์ชุดเล็กๆ "iss" เป็นผู้ออก "sub" หัวข้อเกี่ยวกับโทเค็น "aud" กลุ่มเป้าหมาย "exp" การหมดอายุ "nbf" เวลาที่เร็วที่สุดที่ถูกต้อง "iat" เวลาออก และ "jti" รหัสเฉพาะสำหรับการตรวจจับการเล่นซ้ำ อย่างอื่นเป็นแอปพลิเคชันเฉพาะทั้งหมด

เวลาที่อ้างสิทธิ์เป็นค่า NumericDate: วินาทีนับตั้งแต่ยุค Unix ไม่ใช่มิลลิวินาที สิ่งนี้ทำให้ผู้คนสะดุดอย่างต่อเนื่อง เนื่องจากค่าเวลา JavaScript ส่วนใหญ่เป็นมิลลิวินาที โทเค็นที่ดูเหมือนจะหมดอายุใน 1970 มักจะได้รับค่าเป็นมิลลิวินาที ค่าที่ดูเหมือนจะหมดอายุในปี 55000 มักจะมีค่าที่สองคูณด้วย 1000 ที่ไหนสักแห่ง

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

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

รายการตรวจสอบสั้นๆ สำหรับระบบที่ทำการไว้วางใจ

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

  1. ตรวจสอบลายเซ็นก่อนด้วยรหัสที่คุณได้รับจากวงดนตรี ก่อนที่จะอ่านการเรียกร้องใด ๆ
  2. ปักหมุดอัลกอริทึมในการกำหนดค่าของคุณเอง อย่าอ่านจากส่วนหัวโทเค็น ปฏิเสธ "ไม่มี" โดยไม่มีเงื่อนไข
  3. ตรวจสอบ "exp" และ "nbf" เทียบกับนาฬิกาที่เชื่อถือได้ โดยมีค่าเผื่อความเอียงได้เล็กน้อย
  4. ตรวจสอบ "iss" และ "aud" กับค่าที่คุณคาดหวัง ลายเซ็นที่ถูกต้องบนโทเค็นที่มีไว้สำหรับบุคคลอื่นยังคงเป็นโทเค็นที่ผิด
  5. ใช้ไลบรารีที่ผ่านการตรวจสอบแล้วสำหรับแพลตฟอร์มของคุณแทนที่จะประกอบด้วยตัวเอง ทุกรายการในรายการนี้อยู่ในรายการเนื่องจากการใช้งานผิดพลาด
  6. รักษาอายุการใช้งานโทเค็นให้สั้นและมีเส้นทางการเพิกถอน โทเค็นที่มีอายุสั้นจะจำกัดความเสียหายจากการรั่วไหลที่คุณไม่ได้สังเกตเห็น

จะเกิดอะไรขึ้นกับสิ่งที่คุณวาง

  • ทุกการแปลง แฮช ถอดรหัส และส่วนต่างจะทำงานในแท็บเบราว์เซอร์ของคุณ ไม่มีการอัปโหลด บันทึก หรือจัดเก็บอินพุตบนเซิร์ฟเวอร์ เนื่องจากไม่มีเซิร์ฟเวอร์ที่เกี่ยวข้องเมื่อโหลดเพจแล้ว
  • แฮชมาจากการใช้งาน Web Crypto ของเบราว์เซอร์เอง และ UUID จากตัวสร้างแบบสุ่มที่ปลอดภัยด้วยการเข้ารหัส ไม่เกี่ยวข้องกับการโทรผ่านเครือข่าย
  • ไม่มีสิ่งใดที่คุณพิมพ์ถูกเขียนลงในที่จัดเก็บในตัวเครื่องหรือคุกกี้ การโหลดหน้าซ้ำจะทิ้งหน้านั้นไป การปิดแท็บจะทิ้งมันไป
  • การวิเคราะห์ทั่วทั้งไซต์ทำงานบนโฮสต์การผลิตตามรูปแบบบัญญัติที่กำหนดค่าไว้เท่านั้น และได้รับการเปิดเผยในนโยบายความเป็นส่วนตัว โฮสต์ในท้องถิ่นและโฮสต์ตัวอย่างปฏิเสธ ค่าที่วาง โทเค็น URL และเนื้อหาไฟล์จะไม่รวมอยู่ในเหตุการณ์การวิเคราะห์ของ ToolAcre เอง การโฆษณาถูกปิดใช้งานในการกำหนดค่าปัจจุบัน
  • ที่กล่าวว่า: คีย์ JWT หรือ API เป็นข้อมูลประจำตัวที่ใช้งานอยู่ นิสัยที่ปลอดภัยคืออย่าวางสิ่งใดสิ่งหนึ่งลงในหน้าเว็บที่คุณไม่ได้เขียน ไม่ว่าคำกล่าวอ้างนั้นจะน่าเชื่อถือเพียงใด รวมถึงหน้านี้ด้วย

คำถาม

เครื่องมือนี้ตรวจสอบลายเซ็นหรือไม่

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

แล้วฉันจะรู้ได้อย่างไรว่าโทเค็นเป็นของแท้?

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

โทเค็นของฉันถูกส่งไปที่ใดก็ได้เมื่อฉันถอดรหัสที่นี่หรือไม่

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

เพราะเหตุใดทุกคนจึงสามารถอ่านเพย์โหลด JWT ของฉันได้

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

alg คืออะไร: "ไม่มี"?

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

โทเค็นของฉันมีห้าส่วนและไม่สามารถถอดรหัสได้ ทำไม

ห้าส่วนหมายถึง JWE — โทเค็นที่เข้ารหัส — แทนที่จะเป็น JWS ที่ลงนาม เนื้อหาไม่สามารถอ่านได้หากไม่มีคีย์ถอดรหัส ดังนั้นจึงไม่มีอะไรให้แสดงโดยแท้จริง เครื่องมือนี้จะระบุกรณีดังกล่าวอย่างชัดเจน แทนที่จะรายงานความล้มเหลวในการแยกวิเคราะห์ที่คลุมเครือ

การหมดอายุดูผิดด้วยปัจจัย 1000

การอ้างสิทธิ์เวลา JWT เป็น NumericDate: วินาทีนับตั้งแต่ยุค ไม่ใช่มิลลิวินาที ค่าที่สร้างโดย Date.now() มีขนาดใหญ่เกินไปเป็นพันเท่า ยูทิลิตี้การประทับเวลาในชุดเครื่องมือนี้จะแปลงระหว่างทั้งสองและแจ้งให้คุณทราบเสมอว่าใช้หน่วยใด

ปลอดภัยหรือไม่ที่จะจัดเก็บ JWT ใน localStorage

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

ข้อจำกัด

  • เครื่องมือนี้ถอดรหัสเท่านั้น มันไม่ได้ตรวจสอบลายเซ็น และนั่นคือการตัดสินใจออกแบบถาวรแทนที่จะเป็นคุณสมบัติที่ขาดหายไป ดูคำแนะนำด้านบนว่าทำไม
  • โทเค็นที่เข้ารหัส (JWE, ห้าส่วน) ไม่สามารถถอดรหัสได้เลยหากไม่มีคีย์ เครื่องมือจะระบุและหยุด
  • JWT ที่ซ้อนกัน — โทเค็นที่มีเพย์โหลดเป็นโทเค็น — จะไม่ถูกแกะโดยอัตโนมัติ ถอดรหัสโทเค็นภายในเป็นขั้นตอนแยกต่างหาก
  • ความหมายที่นอกเหนือจากชุดที่ลงทะเบียนไว้ใน RFC 7519 เป็นความหมายเฉพาะของแอปพลิเคชัน ดังนั้นเครื่องมือจึงแสดงค่าโดยไม่ต้องตีความ
  • การหมดอายุที่แสดงไว้ที่นี่สะท้อนถึงสิ่งที่โทเค็นอ้างสิทธิ์เกี่ยวกับตัวมันเองเท่านั้น การกล่าวอ้างนั้นจะมีความหมายหรือไม่นั้นขึ้นอยู่กับลายเซ็นที่เครื่องมือนี้ไม่ได้ตรวจสอบ
  • โทเค็นที่มีขนาดใหญ่กว่า 200,000 อักขระถูกปฏิเสธ JWT จริงใดๆ ก็ตามจะมีลำดับความสำคัญน้อยกว่า