最近、JWT(JSON Web Token)の署名をちょっとだけ変えても、なぜか検証が通っちゃうって話を見かけて、めっちゃ気になったんだよね💭
普通なら、署名っていうのは安全のカギみたいなものだから、1文字でも変わったら絶対アウト!って思ってたのに…どういうこと?
JWTってそもそも何?
ざっくり言うと、JWTは「ユーザー認証とか情報のやりとりに使うトークン」で、
3つのパーツに分かれてるよ👇
- ヘッダー(アルゴリズムとかの情報)
- ペイロード(ユーザー情報とか)
- 署名(ちゃんと作られたか証明する部分)
この署名は、ヘッダーとペイロードを秘密のカギ(=シークレット)を使ってハッシュ化したもので、
「改ざんされてないよ」って確認するための大事なところ✨
でもホントに1文字違っても通るの?
さっそく例を出すと、これが元のJWTだよ👇(秘密のカギは your-super-secret-jwt-key-change-this-in-production
)
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjIsImVtYWlsIjoidGVzdDJAdGVzdC5jb20iLCJpYXQiOjE3NTk2ODc0OTYsImV4cCI6MTc1OTY4ODM5Nn0.clKrlPXTVNB0lpFClG0z3H2JWctC5BVGMfFj4DeJCqY
で、最後の文字だけ Y
から Z
に変えたもの👇
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjIsImVtYWlsIjoidGVzdDJAdGVzdC5jb20iLCJpYXQiOjE3NTk2ODc0OTYsImV4cCI6MTc1OTY4ODM5Nn0.clKrlPXTVNB0lpFClG0z3H2JWctC5BVGMfFj4DeJCqZ
これを https://www.jwt.io/ で検証してみると、
なんと両方とも「検証成功」になっちゃうんだよね😳
なんでそうなるの?裏側を覗いてみたら…
最初は「まさかバグ?!」って思ったけど、じつはJWTの署名はBase64URLエンコードされてるから、
1文字の違いが必ずしもビットレベルで変わってるとは限らないんだよね💡
つまり、最後の文字をちょっと変えても、実際のバイト列としては同じ内容だったりすることがあるってわけ✨
あと単純に、JWT.ioの検証ツールは完全な正規表現や厳密なチェックをしてない場合もあるから、
たまたまエラーを見逃してる可能性もあるみたい🤔
まとめると…
- JWTの署名はBase64URLエンコードされた文字列で、見た目の違いが必ずしも意味の違いじゃないことがある
- だから1文字変えても検証が通る場合がある
- オンラインツールの検証結果が必ずしも完璧じゃないこともある
- 実際の運用ではライブラリやフレームワークに任せるのが安全だよ✨
こういう小さな「ん?」があると、普段なんとなく使ってる技術の仕組みがちょっと見えてきて、面白いよね🥺
もし気になったら、自分でもいろいろ試してみるのおすすめだよ〜👀💗
コメント
ハンナ
署名の最後に余計なデータが入ってるだけかも。
ベン
これ、ジェームズ・ウェッブ望遠鏡の話かと思って完全に混乱したw