Laravelでの暗号化されたCookieからセッションID等を取得

参考にしたページ

※ やってることは下記サイトと全く同じ。

Laravel の Cookie 暗号化の仕組みを理解する

環境

  • Laravel Sail
    Laravel:10.15.0
    セッションドライバ:file
  • PHP:8.2.8

結論

セッションIDやCSRFトークンを確認したければ、
Chromeのデベロッパツール等でレスポンスCookieの該当の値を
次の$originalCookieValue変数に格納し、次のコードをtinkerで実行すれば良い。
(app.keyの値がわかればtinkerでなくても良い)
(暗号化方式を確認するならconfig/app.phpのcipherを確認すれば良い)

$originalCookieValue = 'レスポンスCookieの該当の値';
$laravelSessionDecoded = base64_decode($originalCookieValue);
$json = json_decode($laravelSessionDecoded);
$ivDecoded = base64_decode($json->iv);
$keyDecoded = base64_decode(substr(config('app.key'), 7));
$valueDecrypted = openssl_decrypt($json->value, 'aes-256-cbc', $keyDecoded, 0, $ivDecoded);
$result = substr($valueDecrypted, strpos($valueDecrypted, '|') + 1);

詳細

Laravelで動いているページのどこかにアクセスすると、
laravel_session(デフォルトならこの名前)やXSRF-TOKENのCookieがセットされる。
セットされることやそのCookieの値はChromeのデベロッパーツールから確認できる(レスポンスCookie)。

LaravelのセッションIDを確認する。
Laravelのセッションドライバがfileの場合は、次のフォルダ内を確認する。
(ファイル名がセッションID)

storage/framework/sessions

Laravelのセッションドライバがdatabaseの場合は、sessionsテーブルのidを確認する。

レスポンスCookieの確認したいCookieの値が次の文字列だとする。(後ろの%3Dはなくても結果は変わらなかった。もし存在するならURLデコードが必要だと思われる)

eyJpdiI6IkV5ZlJReTJxeGFFRUUvM25kZXpJcXc9PSIsInZhbHVlIjoiK2ZLZ3lLVXRCeUFDTmt2RlN4ODRDdXJnS1pRVHhJQ3FKQ1N0Z2xBQXpiWkRRM0NFSUM2NWVKSUpFS0hVWHdPbnk0bXc4anBIem9NNDJhY3dZTzRwUVBhRUxwd0JMMjVvcXlkMzRLZ2Ntb3d6YkpKNE53M3RsUVZHUmRibzdPbEciLCJtYWMiOiIyYTYzZmViNzkyMjk1Njg0OWI3YjIzNWE3ZDQxYmViY2UzYjkzMjU1Nzk0MjZkZDIxODA0MzQxOTU0NTY1MTNlIiwidGFnIjoiIn0

Laravelのtinkerを起動して、上の結論にあるコードを次のように実行する。

$originalCookieValue = '
eyJpdiI6IkV5ZlJReTJxeGFFRUUvM25kZXpJcXc9PSIsInZhbHVlIjoiK2ZLZ3lLVXRCeUFDTmt2RlN4ODRDdXJnS1pRVHhJQ3FKQ1N0Z2xBQXpiWkRRM0NFSUM2NWVKSUpFS0hVWHdPbnk0bXc4anBIem9NNDJhY3dZTzRwUVBhRUxwd0JMMjVvcXlkMzRLZ2Ntb3d6YkpKNE53M3RsUVZHUmRibzdPbEciLCJtYWMiOiIyYTYzZmViNzkyMjk1Njg0OWI3YjIzNWE3ZDQxYmViY2UzYjkzMjU1Nzk0MjZkZDIxODA0MzQxOTU0NTY1MTNlIiwidGFnIjoiIn0
';
$laravelSessionDecoded = base64_decode($originalCookieValue);
$json = json_decode($laravelSessionDecoded);
$ivDecoded = base64_decode($json->iv);
$keyDecoded = base64_decode(substr(config('app.key'), 7));
$valueDecrypted = openssl_decrypt($json->value, 'aes-256-cbc', $keyDecoded, 0, $ivDecoded); 
$result = substr($valueDecrypted, strpos($valueDecrypted, '|') + 1);

最後に$resultに格納された文字列は次の通りだった。

eSZNZ3PVi7DoMhS1keK7jXzMH1ZtWeRpQlTdqxza

次に該当するセッションIDがあることを確認すれば良い。

CSRFトークンを確認するなら、XSRF-TOKENのCookieの値に対して上記のコードを実行すれば良い。
XSRF-TOKENの値は、該当するセッション内に_tokenという名前で保存されている。

余分なお話

Cookieの値について

上記コードを実行後、$jsonの内容を見るとこうなっていた。

> $json;
= {#6262
    +"iv": "EyfRQy2qxaEEE/3ndezIqw==",
    +"value": "+fKgyKUtByACNkvFSx84CurgKZQTxICqJCStglAAzbZDQ3CEIC65eJIJEKHUXwOny4mw8jpHzoM42acwYO4pQPaELpwBL25oqyd34KgcmowzbJJ4Nw3tlQVGRdbo7OlG",
    +"mac": "2a63feb7922956849b7b235a7d41bebce3b9325579426dd2180434195456513e",
    +"tag": "",
  }
  • iv
    AES-256-CBCでの暗号化復号化で使用するもの。
  • value
    暗号化された内容。「|」の左側の文字列はEncryptCookies->encryptメソッド内で、CookieValuePrefix::createメソッドで加えられている、Cookie名とキーとCookie値のハッシュなので気にしないで良い。
  • mac
    ivとvalueの値とキーをもとにハッシュ化された文字列。
  • tag
    未確認。

再度暗号化したい場合

確認のために再度暗号化したいなら、上記コードを実行後、次のコードを実行することで確認できる。

$encrypted = openssl_encrypt($valueDecrypted, 'aes-256-cbc', $keyDecoded, 0, $ivDecoded);
if (strcmp($encrypted, $json->value) === 0) printf ('match');

macの値について

次のコードを実行すると、$json->macと同じ値が生成できる。

hash_hmac('sha256', $json->iv.$json->value, base64_decode(substr(config('app.key'), 7)));

コメント

タイトルとURLをコピーしました