Hook

Hook jwt: ตรวจหาการตรวจสอบ JWT ที่ไม่ได้ตรึงอัลกอริทึม

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

hook jwt ชี้ว่าเป็นปัญหาเมื่อพบ การตรวจสอบ JWT ที่ไม่ได้ตรึงอัลกอริทึม ซึ่งเป็นช่องโหว่ algorithm confusion ที่ตัวตรวจสอบเชื่อ header alg ของโทเค็นเอง และเมื่อพบ การปิดการตรวจสอบไปทั้งหมด hook นี้ เข้าใจภาษา โดยอ่านแต่ละไฟล์ตามไลบรารี JWT ที่ไฟล์นั้นใช้ และเป็นเอนจินแบบ deterministic เบื้องหลัง ความรู้เฉพาะทาง federation ซึ่งคุณรันเองได้ในโหมด scan หรือ check

การรัน​

npx lagune read jwt # scans the whole project
npx lagune read jwt --dir src # scans a directory
npx lagune read jwt --file auth.ts # scans a single file

ทุกบรรทัดใต้ Unpinned JWT verification found คือการเรียก verify ที่ไม่ได้กำหนดรายการที่อนุญาต algorithms (ในกรณีที่ไลบรารีต้องการ) ยอมรับรายการที่ไม่ปลอดภัย (none หรืออัลกอริทึมแบบอสมมาตรที่ปนกับ HMAC) หรือปิดการตรวจลายเซ็นไปเลย จึงเชื่อ alg ของโทเค็นเอง นี่คือช่องโหว่ที่ยืนยันแล้ว hook จึงจบการทำงานด้วย exit code ที่ไม่ใช่ศูนย์ การรันที่ไม่พบปัญหาจะพิมพ์ no unpinned JWT verification found

วิธีอ่านผลตัดสิน​

ผลตัดสินความหมาย
unpinnedการเรียก verify ที่ไม่มีรายการอัลกอริทึมที่อนุญาต (ในกรณีที่จำเป็น) มีรายการที่ไม่ปลอดภัย หรือปิดการตรวจสอบไว้
safeการเรียก verify ที่ตรึงรายการอัลกอริทึมที่อนุญาตไว้อย่างเหมาะสม หรือไลบรารีตรึงให้โดยปริยาย
invalidโค้ดตัวอย่างไม่มีการเรียก verify ที่ระบุได้ให้ตัดสิน

ตัวเลือก CLI​

ตัวเลือกค่าคำอธิบาย
--patternโค้ดตัวอย่างตรวจการเรียกใช้หนึ่งครั้ง ใส่ซ้ำเพื่อตรวจหลายครั้ง โดยได้ผลตัดสินบรรทัดละหนึ่งรายการ
--langภาษาจำเป็นเมื่อใช้ --pattern: เลือกหนึ่งใน javascript, python, go, java, kotlin, php, ruby, rust หรือ csharp
--dirไดเรกทอรีจำกัดการสแกนไว้ที่ไดเรกทอรีเดียว ใช้ซ้ำได้และใช้ร่วมกับ --file ได้
--fileไฟล์จำกัดการสแกนไว้ที่ไฟล์เดียว ใช้ซ้ำได้และใช้ร่วมกับ --dir ได้

หากไม่ระบุตัวเลือก hook จะสแกนทั้งโปรเจกต์ --pattern ต้องใช้คู่กับ --lang และใช้ร่วมกับ --dir หรือ --file ไม่ได้

เลือกสิ่งที่จะสแกน​

hook นี้ข้ามสิ่งที่ Git ละเว้นไว้ หากต้องการข้ามมากกว่านั้น หรือต้องการสแกนสิ่งที่ Git ละเว้นไว้ ให้กำหนดการตั้งค่าเฉพาะของ jwt เอง:

npx lagune write add --ignore test/fixtures --checker jwt
{
"checkers": {
"jwt": { "gitignore": false, "ignore": ["test/fixtures"] }
}
}

กำหนดค่า hook อธิบายการตั้งค่าทั้งหมด

ภาษาที่รองรับ​

การสแกนอ่านไลบรารีเหล่านี้โดยแยกตามนามสกุลไฟล์ เนื่องจากบางไลบรารีตรึงอัลกอริทึมให้โดยปริยาย (การไม่มีรายการที่ระบุชัดก็ยังปลอดภัย) กฎ "ไม่มีรายการที่อนุญาต ⇒ unpinned" จึงใช้เฉพาะเมื่อไลบรารีคาดหวังรายการที่ระบุชัด hook จึงไม่มีวันชี้ว่าการเรียกที่ตั้งค่าถูกต้องเป็นปัญหา

ภาษาไลบรารีถือว่าการไม่มีรายการที่อนุญาตเป็น unpinned ไหมชี้ว่าเป็นปัญหาเสมอ
JavaScript / TypeScriptjsonwebtoken, joseใช่none, การปนกันของอัลกอริทึมแบบอสมมาตรกับ HMAC
PythonPyJWT, python-joseใช่ (PyJWT บังคับให้ระบุ ส่วน python-jose ใช้ค่าเริ่มต้น algorithms=None)none, verify_signature: False
Gogolang-jwtใช่ (ไม่มี WithValidMethods)none, ParseUnverified
Rubyruby-jwtใช่none, verify = false
Java / Kotlinjjwt, nimbusไม่ (อนุมานจากคีย์)none, parser แบบไม่ลงนามหรือแบบ unsecured
PHPfirebase/php-jwtไม่ (Key ระบุ alg ไว้แล้ว)none
Rustjsonwebtokenไม่ (Validation บังคับให้ระบุอัลกอริทึม)none, insecure_disable_signature_validation
C#Microsoft.IdentityModelไม่ (พารามิเตอร์เขียนแยกหลายบรรทัด)none, RequireSignedTokens = false
tip

hook ตัดสินเฉพาะเรื่องการตรึงอัลกอริทึม: การตรวจ claim คีย์ และ flow เป็นเรื่องที่ต้องใช้วิจารณญาณ ซึ่ง ความรู้เฉพาะทาง federation ยังคงดูแลอยู่

คำถามที่พบบ่อย

ตัวตรวจสอบที่อ่านอัลกอริทึมจาก header ของโทเค็นเปิดช่องให้ผู้โจมตีสลับ RS256 เป็น HS256 แล้วลงนามด้วย public key การตรึงรายการอัลกอริทึมที่อนุญาตอย่างเหมาะสมไว้ในโค้ดช่วยป้องกันได้ และ hook jwt จะชี้ว่าการเรียก verify ที่ไม่ได้กำหนดรายการไว้ หรือกำหนดรายการที่ไม่ปลอดภัย เป็นปัญหา