ブログ

Cookieについて調べてみた

前回の記事で、Cookieとはサーバー側がクライアント側に与える名前のようなものだ、と述べた。
今回はCookieがどのように発行されるのか、や
実際のPCでどのように管理されているか、などといった
Cookieの実体に迫ってみようと思う。
 
まず自分が現在どのようなCookieを保持しているのかをエクスチュアのページを例に確認してみよう。
 
Chromeでは
設定 → プライバシー → コンテンツの設定 → Cookieとサイトデータ
から簡単に確認ができる。
blog3_1
このようにエクスチュアでは14個のクッキーを発行しているようだ。
さて、これらのCookieが実際に発行される様子を見てみよう。
 
CookieはHTTPリクエストヘッダ内のCookie項目で宣言されなかった場合、
レスポンスヘッダ内のSet-Cookie項目で発行される。
したがって、先ほどの14個のCookieを削除した状態で、エクスチュアのサイトにアクセスすれば、
新たにCookieが発行されるはずである。
 
実際にやってみた様子がこちら。
blog3_2
blog3_4
このようにCookieが新たに発行され、Chromeの管理下に追加されたことが確認できる。
 
この後にページをリロードしてみると、先ほど発行されたばかりのCookieが、
リクエストヘッダのCookie項目で宣言されていることも確認できた。
blog3_3
さて、このようにCookieがHTTPレスポンスヘッダで発行され、
リクエストヘッダで宣言されていることが分かった。
ところでChromeは今までに発行されたCookieの情報をどこに記憶しているのだろうか。
 
調べたところ、windowsでは%UserProfile%配下の
/AppData/Local/Google/Chrome/User Data/Default
にCookiesという名前のSqliteファイルとして管理されていることが分かった。
 
せっかくなので実際にSqlite3を操作して、中身を覗いてみよう。
blog3_5
Cookieはcookieというテーブルで管理されており、
host_keyというカラムでそのCookieが発火するタイミングを指定しているようなので、
エクスチュアのページで送られるCookieを抽出してみたところ、
先ほど発行されたCookie(らしきもの)が確認できた。
blog3_6
しかし残念なことにvalueカラムが表示されず、これが本当に先ほど発行されたCookieなのか確信が持てない。
どうやらChrome33.0からvalueを暗号化して、encrypted_valueカラムに登録するようになったらしく、
これを復号化しなければvalueが手に入らないようだ。
 
どのようにして複合化すれば良いのか。
Googleの力を借りてcookie-issue-with-chrome-33-betaというページにたどり着くことができた。
 
どうやらWindowsにおけるCookieの暗号化は、
Windows OSが提供しているDPAPIという暗号および複合化用のAPIを使って行われているらしい。
この場合、暗号化時と同じユーザーで実行されているアプリケーションによって
複合化することが可能なようだ。上記のサイトのPythonスクリプトは、
ctypesという動的ライブラリ(dll)を呼ぶための標準ライブラリを使ってDPAPIを操作し、複合化を行っている。
 
したがってこのPythonスクリプトに少しだけ変更を加え、
host_Keyカラムが”.ex-ture.com”、 nameカラムが”__cfduid”、となっているレコードのencrypted_valueカラムを複合化して表示するスクリプト、CookieDecrypt.pyを書いた。

from ctypes import *
from ctypes.wintypes import DWORD
import sqlite3;
class DATA_BLOB(Structure):
    _fields_ = [("cbData", DWORD), ("pbData", POINTER(c_char))];
def getData(blobOut):
    cbData = int(blobOut.cbData);
    pbData = blobOut.pbData;
    buffer = c_buffer(cbData);
    memcpy(buffer, pbData, cbData);
    LocalFree(pbData);
    return buffer.raw;
def decrypt(cipherText):
    bufferIn = c_buffer(cipherText, len(cipherText));
    blobIn = DATA_BLOB(len(cipherText), bufferIn);
    blobOut = DATA_BLOB();
    if CryptUnprotectData(byref(blobIn), None, None, None, None,
                              CRYPTPROTECT_UI_FORBIDDEN, byref(blobOut)):
        return getData(blobOut);
    else:
        raise Exception("Failed to decrypt data");
LocalFree = windll.kernel32.LocalFree;
memcpy = cdll.msvcrt.memcpy;
CryptProtectData = windll.crypt32.CryptProtectData;
CryptUnprotectData = windll.crypt32.CryptUnprotectData;
CRYPTPROTECT_UI_FORBIDDEN = 0x01;
cookieFile="C:/Users/mitsuiki/AppData/Local/Google/Chrome/User Data/Default/Cookies"
hostKey=".ex-ture.com";
name="__cfduid"
conn = sqlite3.connect(cookieFile);
c = conn.cursor();
c.execute("""\
SELECT
    host_key,
    name,
    path,
    value,
    encrypted_value
FROM cookies
WHERE host_key = '{0}' and name='{1}'
;
""".format(hostKey,name));
cookie = c.fetchone();
c.close()
print( \
"""
host_key: {0}
name: {1}
path: {2}
value: {3}
encrpyted_value(decrypted): {4}
""".format(cookie[0], cookie[1], cookie[2], cookie[3], decrypt(cookie[4])));

このスクリプトの実行結果が次。
blog3_7
無事復号化に成功し、このレコードが先ほど発行されたCookieであると判明した。
 
インターン生 薄井

ピックアップ記事

  1. 最速で理解したい人のためのIT用語集

関連記事

  1. ブログ

    東南アジアのデジタルマーケティング

    こんにちは!インターン生の山本です!今回は、現在私が調…

  2. ブログ

    "Marketo"を使ってみて。パート2

    こんにちは!インターン生の山田です。前回に引き続き、今回は"Mark…

  3. ブログ

    ダッシュボードでよくある間違い①

    こんにちは!インターン生の山本です。前回はダッシュボードの定義を振り…

  4. ブログ

    ベイズとR

    ベイズの定理の初めのほうをまとめておこうと思います。ミーハーなのでつ…

  5. ブログ

    「Power BI」を用いたダッシュボードの作成!②

    こんにちは!インターンの山本です。前回は「Power BI」を用いて…

  6. ブログ

    エクセル関数の基礎

    こんにちはインターン生の松本です。今回は僕があるタスクで関数をしようす…

最近の記事

  1. 回帰分析はかく語りき Part3 ロジスティック回帰
  2. GCSへのSnowflake Open Catalogによる…
  3. VPC Service Controlsで「NO_MATCH…
  4. モダンデータスタックなワークフローオーケストレーションツール…
  5. Streamlit in Snowflakeによるダッシュボ…
  1. Adobe Analytics

    Adobe AEP SDKをTypeScriptで開発したReactNative…
  2. Google Tag Manager

    サーバーサイドGTM: ウェブコンテナを使って1stパーティドメインからgtm.…
  3. YOTTAA

    YOTTAA:ECサイトで見るべき8つのサイトパフォーマンス指標について
  4. Adobe Analytics

    Adobe Analytics: BigQueryにロードしたデータフィードをD…
  5. ブログ

    ①DMPについて
PAGE TOP