はまやんはまやんはまやん

hamayanhamayan's blog

JWT [VolgaCTF 2021 Qualifier]

調査

Sign InとSign Upができる。 アカウントを作って、ログインすると、挨拶できるページがある。 /say-hi -> You are simple user. adminユーザーで挨拶すればよさそう。

Proxy履歴を見てみよう。 それほど気になる部分もない。 タイトルにもあるようにJWTが使われているのでCookieに着目してみよう。

Cookie

token=eyJraWQiOiJIUzI1NiIsImFsZyI6IkhTMjU2In0.eyJqa3UiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvc2VjcmV0IiwiZXhwIjoxNjE3NTE2NjQ2LCJqdGkiOiJydU9Gend4S3E0ZWFNM2Q5OEN2dWxRIiwiaWF0IjoxNjE2OTExODQ2LCJuYmYiOjE2MTY5MTE3MjYsInN1YiI6ImV2aWxtYW4ifQ.v-nrjUjhjgdd5JNIi14KwXx5YpFwrqbKJ4s_CSC96t4
JSESSIONID=DE2FB55273E90C1D401C2EE1793BD917

JSESSIONIDは一旦無視して、tokenの中身を見る。

{
  "kid": "HS256",
  "alg": "HS256"
}
.
{
  "jku": "http://localhost:8080/secret",
  "exp": 1617516646,
  "jti": "ruOFzwxKq4eaM3d98CvulQ",
  "iat": 1616911846,
  "nbf": 1616911726,
  "sub": "evilman"
}
.
署名

/secretへアクセスしてみたが403 Forbiddenだった。 jwks spoofingだろう

jwks spoofing

jku部分を自前のものに変更して、秘密鍵を差し替えよう。 How to generate a JSON Web Key (JWK) | Connect2id ここを参考にして、以下のように作って、公開する。

{ 
  "kty" : "oct",
  "kid" : "HS256",
  "k"   : "FdFYFzERwC2uCBB46pZQi4GG85LujR8obt-KWRBICVQ"
}

鍵がkになるので、これを署名時に使ってJWSを作る。 後は、subをadminにして、jwt.ioでトークンを作り直す。 注意として、「secret base64 encoded」にチェックを入れること。 作ったJWTトークンを渡して/say-hiを見ればフラグゲット。 VolgaCTF{jW5_jku_5u85T1TUt10n}

余談

RFC的にはjkuはHEADERに入っているべきだと思うが、これは正しい解釈? 別にPayloadに入っていてもいいのか?