JWT Knowledge Sharing

Datafarm
4 min readDec 11, 2024

สวัสดีครับ วันนี้ผมก็จะมาแนะนำการตั้งค่าการใช้งาน Token เบื้องต้นให้มีความเหมาะสมและปลอดภัย เนื่องจากเวลาเราทำการทดสอบเจาะระบบต่าง ๆ ก็จะมี Issue ที่เกี่ยวกับตัว Token เช่น มีการใช้งาน Weak Secret Key บ้าง หรือมีการตั้งค่า Expiration Time ของ Token ที่นานจนเกินไป จึงทำให้ทางผู้พัฒนามีความสงสัยว่าถ้าหากเรามี Issue ในส่วนนี้ ทางผู้พัฒนาควรมีการปรับแก้อย่างไรถึงจะถูกต้องและเหมาะสม เนื่องด้วยโปรโตคอลที่เราทำการส่ง Request ต่าง ๆ นั้นไม่ได้มีการจดจำว่าใครเป็นคนส่ง Request มา หรือเป็นแบบ Stateless จึงต้องมีสิ่งที่จะระบุได้ว่าใครเป็นคนส่ง Request นี้มา เช่น ผ่าน Cookie Header หรือ Authorization Header โดยเราเริ่มแรกจะอธิบายถึงข้อแตกต่างง่าย ๆ ระหว่าง Session กับ Token กันก่อนครับ

Session

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

Token

Token คือ ข้อมูลที่ใช้แทนตัวตนของผู้ใช้หรือการอนุญาตการเข้าถึงทรัพยากรในระบบ โดยมักถูกส่งไปมาระหว่าง Client และ Server โดยไม่มีการการเก็บสถานะในฝั่งเซิร์ฟเวอร์ (Stateless) เมื่อเราทำการออกจากระบบตัว Token จะไม่ Terminate ในทันทีแต่จะดู Expiration time จากตัวของ Token เอง หรือถ้าหากต้องการที่จะ Revoke ตัว Token ต้องมีตัวกลางมาทำการจัดการในส่วนตรงนี้ โดยกลไกลการทำงานของ Token คือ เมื่อเราทำการส่ง HTTP Request ที่แนบด้วย Token ไปยังเซิร์ฟเวอร์ที่เซิร์ฟเวอร์ก็จะทำการ Authentication ทุกครั้ง เพื่อตรวจสอบว่า Token ที่ได้รับมานั้นเป็นใครและมีสิทธิ์อะไรในการเข้าใช้งานฟังก์ชัน โดย Token ที่พบกันบ่อยก็จะเป็น JWT (JSON Web Token), OAuth, etc.

โดยตัวอย่างที่ผมหยิบยกมาเบื้องต้นคือ JWT (JSON Web Token) เนื่องจากแอปพลิเคชันต่าง ๆ มีการใช้งานกันอย่างแพร่หลายทั้ง Web Application และ Mobile Application

JWT (JSON Web Token) เป็นรูปแบบของ Token ชนิดหนึ่งโดย JWT นั้นจะแบ่งเป็นทั้งหมด 3 ส่วน คือ Header, Payload และ Signature โดยที่ Header ก็จะมีข้อมูลเกี่ยวกับประเภทของ Token (typ) และส่วนที่สำคัญคือ Algorithm (alg) JWT นั้นจะใช้ Algorithm ต่าง ๆ ในการ Sign Token เช่น HS256, RS256 หรือ ES256 ที่มีในปัจจุบัน Algorithm ที่ควรใช้งานปัจจุบันมองว่าเป็น RS256 เนื่องจาก Algorithm นี้เป็น Asymmetric Key โดยจะใช้ Private Key ในการ Sign และใช้ Public Key ในการ Validate จะต่างจาก HS256 ที่เป็นรูปแบบ Symmetric Key จะมีการใช้ Secret Key ในการ Sign และ Validate หากเกิด Secret Key หลุดจะสามารถสร้าง Token ปลอมได้

Ref: https://jwt.io/

โดยผมจะยกตัวอย่างจาก HS256 เนื่องจากว่าการ Sign JWT ด้วย Algorithm HS256 นั้นจะต้องมีการใช้ Secret Key ในการ Sign ข้อควรระวังในการใช้งาน Algorithm HS256 คือการใช้งาน Secret Key ที่ไม่ปลอดภัย แล้วเราจะมีการตั้งค่า Secret Key อย่างไรถึงจะปลอดภัย?

การใช้งาน Secret Key ที่ปลอดภัย

ควรมีการกำหนดดังนี้

1. การใช้งาน Secret Key นั้น ไม่ควรใช้ Secret Key ที่สามารถคาดเดาได้ทั่วไปและเป็น Secret Key ที่อ่อนแอ (Weak Key) เช่น secret, supersecret หรือคำต่าง ๆ ที่อยู่ใน Wordlists ทั่วไป

2. กำหนดความยาวของ Secret Key ตามมาตรฐาน OWASP คือต้องมีความยาวไม่ต่ำกว่า 64 ตัวอักษร และ generate จาก Secure Random Number Generation

3. Secret Key ต้องเก็บที่เซิร์ฟเวอร์เท่านั้น ไม่ควรไว้ที่ Client หรือตาม Request/Response เด็ดขาด เพราะทำให้เกิด Secret Leak ได้

4. หลีกเลี่ยงการใช้งาน Secret Key เดียวกันกับระบบอื่น ๆ

5. หากมีการนำตัวอย่าง Source Code จากแหล่งต่าง ๆ มาใช้ควรทำการปรับเปลี่ยน Secret Key ใหม่ ไม่ควรใช้งานซ้ำกับของเดิม

ตาราง Secure Random Number Generation ที่ Unsafe และ Secure ของแต่ละภาษาตาม OWASP

Ref: https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation

ถ้าพูดถึงเรื่อง Token ที่ไว้ใช้สำหรับ Authentication นั้นโดยปกติ Token ที่เราใช้งานนั้นจะมี 2 แบบ คือ Access Token และ Refresh Token ที่ได้มาจากการ Login

Access Token

เป็น Token ชนิดหนึ่งที่ไว้ใช้สำหรับการเข้าใช้งานระบบโดยใช้สำหรับยืนยันตัวตนและสำหรับการตรวจสอบสิทธิ์ โดยทำการส่งไปพร้อมกับ HTTP Request Header เช่น Authorization Header เป็นต้น แล้วเราควรมีการตั้งค่า Access Token อย่างไรถึงจะปลอดภัย?

เนื่องด้วย Access Token นั้นเป็น Token ที่ใช้สำหรับเข้าถึง Resource ต่าง ๆ ของระบบ เกิดว่าผู้ใช้งานมีการทำ Token Leak หรือถูกขโมยด้วยวิธีการต่าง ๆ เช่น XSS หากมีการกำหนด Expiration time ที่นานจนเกินไปส่งผลให้ผู้ไม่ประสงค์ดีที่ได้รับ Token ด้วยวิธีการต่าง ๆ สามารถสวมรอยเข้าไปโจมตีระบบได้ การตั้งค่า Expiration time ของ Token นั้น โดยตามมาตรฐานจะมีการกำหนด Expiration time ไว้ไม่เกิน 1 ชั่วโมง สำหรับการใช้งานทั่วไป หากเป็นกรณีที่เกี่ยวข้องกับการทำธุรกรรมทางการเงินที่มีความเสี่ยงสูงจะต้องมีการตั้งค่า Expiration time ของ Token ไว้เพียงแค่ 2–5 นาที เท่านั้น ส่วนที่รองลงมาจะเป็น 15–30 นาที

Refresh Token

เป็น Token ที่ไว้ใช้สำหรับต่ออายุเมื่อเวลาที่ Access Token นั้นหมดอายุ ระบบจะทำการส่ง Access Token และ Refresh Token ไปที่เซิร์ฟเวอร์เพื่อทำการขอ Access Token ชุดใหม่ สำหรับใช้งานต่อไป บทบาทของ Refresh Token อาจจะเห็นว่าไม่ค่อยใช้งานบ่อยเท่า Access Token แต่ความสำคัญในการให้ความปลอดภัยนั้นไม่ด้อยไปกว่ากันเลย เพราะว่าหากผู้ใช้งานเกิดทำ Refresh Token Leak หรือหลุดไปยังผู้ไม่ประสงค์ดีเท่ากับว่าผู้ไม่ประสงค์ดีจะสามารถโจมตีระบบด้วย Access Token และขอ Access Token ใหม่ได้เรื่อย ๆ จนกว่า Refresh Token นั้นจะหมดอายุ การกำหนดอายุของ Refresh Token นั้นเป็นสิ่งที่ต้องให้ความสำคัญทั้งในด้านของความปลอดภัยและ Business Requirement เนื่องจากว่าหาก Refresh Token นั้นหมดอายุเท่ากับว่าผู้ใช้งานนั้นต้องทำการ Login เข้าสู่ระบบใหม่ ถ้าหากมีการตั้งค่าระยะเวลา Refresh Token ที่ต่ำไปผู้ใช้งานต้องทำการ Login บ่อยมากขึ้นนั่นเอง หรือถ้ามีการตั้งค่าระยะเวลา Refresh Token นานจนเกินไปก็มีความเสี่ยงด้านความปลอดภัย จึงต้องมีความ Balance ซึ่งกันและกัน โดยปกติการตั้งค่า expiration time ของ Refresh Token นั้นจะขึ้นอยู่กับระบบเช่น 7 วัน, 14 วัน, 1 เดือน เป็นต้น แล้วเราควรจะทำอย่างไรหากต้องมีการตั้งค่า Expiration time ของ Refresh Token ที่มีระยะเวลานาน?

การเก็บ Access Token และ Refresh Token ควรเก็บไว้ในที่ปลอดภัย (Secure Storage) เช่น หากเป็น Mobile Application ก็มีการเก็บไว้ที่ Secure Storage, Encryption Storage เช่น Keychain, Keystore เพื่อป้องกันการโจมตีที่อาจจะเกิดขึ้นได้ในอนาคต

Conclusion

สรุปการใช้งาน Token นั้นมีความสะดวกสำหรับการทำงานหลาย ๆ อย่าง แต่ทั้งนี้เราต้องคำนึงถึงความปลอดภัยในการตั้งค่าการใช้งานของ Token ด้วย ไม่ว่าจะเป็น Algorithm ต่าง ๆ ในการ Sign, ความปลอดภัยในการใช้งาน Secret Key ต่าง ๆ เช่น มีความยาว 64 ตัวอักษรขึ้นไป ทำการสร้างการ Secure Random Number Generation รวมถึงไม่ควรใช้งาน Secret Key เดียวกันในหลาย ๆ ระบบ และเมื่อทำการนำตัวอย่าง Source Code มาใช้งาน ควรเปลี่ยนแปลง Secret Key ด้วย อีกทั้ง Access Token และ Refresh Token นั้น มีบทบาทของตัวเองที่แตกต่างกันไปแต่สิ่งที่เหมือนกันที่ต้องคำนึงถึงคือความปลอดภัยในการตั้งค่าระยะเวลาต่าง ๆ เช่น ถ้าเป็นการทำธุรกรรมเกี่ยวข้องกับการเงินระยะเวลาที่เหมาะสมคือ 2–5 นาที หรือถ้ารองลงมาก็จะเป็น 15–30 นาที หรือไม่ควรเกิน 1 ชม. หากมีการใช้งานทั่วไป ส่วน Refresh Token นั้นขึ้นอยู่กับการพิจารณาร่วมกับทางด้าน Business ด้วย เช่น 7 วัน 14 วัน จนถึง 1 เดือน โดยการเก็บ Token นั้นต้องเก็บอยู่ใน Secure Storage หรือ Encryption Storage เท่านั้น และไม่เก็บข้อมูลสำคัญไว้ใน Token หากมีการจัดการที่ไม่ดีแล้วเกิดเหตุการณ์ที่มี Token Leak หรือหลุดจะทำการให้เกิดคามเสียหายต่อระบบได้ครับ

--

--

No responses yet