camouflage

音楽は素晴らしい。管理職(という仕事)は素晴らしくない。

全体表示

[ リスト ]

擬似 Cookie 改良版

最近のマイブーム

最近のマイブームは この辺の話題 でして、飲み会断られた夜は Cookie 未使用のトラッキング方法をあれこれと試行、といった空しい過ごし方をしております。

以前の PNG 擬似 Cookie 改良版 のそのまたさらに改良版で、PNG 画像や canvas を用いることなくブラウザ識別を可能にした getCookie.php を作ってみました。おおまかな処理の流れは以下の通りです。

ローカルキャッシュ有り :
01. [Client] "getCookie.php" にアクセス(以下は例)

  <html>
  <body>
  <script type='text/javascript' src='http://HOST/PATH/getCookie.php'>
  </script>
  </body>
  </html>

02. [Server] 生成した識別子を含む JavaScript を返す
03. [Client] "getCookie.php?cookie=" にアクセス
04. [Server] 304 を返す
05. [Client] キャッシュされた JavaScript から識別子を得る(2. の識別子とは異なる)

  alert(window.getCookie.cookie);

06. [Client] 識別子を用いビーコンクエリ等を行う

ローカルキャッシュ無し :
01. 〜 04. は上記同様
05. [Client] "getCookie.php?cookie=識別子" にアクセス(2. の識別子)
06. [Server] 識別子を一時ファイルに保存し "getCookie.php?cookie=" にリダイレクト
07. [Client] "getCookie.php?cookie=" にアクセス
08. [Server] 一時ファイルが存在すればそこから識別子を取得し JavaScript として返す
09. [Server] 一時ファイルを削除
10. [Client] レスポンスの JavaScript から識別子を得る
11. [Client] 識別子を用いビーコンクエリ等を行う

一時ファイルの名前には IP や User-Agent 等から作成した簡易 FingerPrint を用いてます。
Cookie を無効にしたブラウザだろうと一意に識別することが可能です。

getCookie.php :
<?php

define('SELF', "http://{$_SERVER['HTTP_HOST']}{$_SERVER['SCRIPT_NAME']}");
define('JSNAMESPACE', 'getCookie');

function fingerPrint($in_prefix = '')
{
    $elems = array('REMOTE_ADDR', 'HTTP_USER_AGENT', 'HTTP_ACCEPT_LANGUAGE');
    foreach ($elems as $elem) {
        $in_prefix .= $_SERVER[$elem];
    }
    return md5($in_prefix);
}

function js1($in_cookie)
{
    $SELF = SELF;
    $JSNAMESPACE = JSNAMESPACE;
    print <<<EOJS
(function() {
    var target = document.getElementsByTagName('SCRIPT').item(0);
    var makeScript = function(in_src) {
        var ret = document.createElement('SCRIPT');
        ret.type = 'text/javascript';
        ret.src = in_src;
        return ret;
    };
    window.setTimeout(function() {
        if (window.{$JSNAMESPACE}) {
            return;
        }
        target.parentNode.insertBefore(makeScript('{$SELF}?cookie={$in_cookie}'), target);
    }, 1000);
    target.parentNode.insertBefore(makeScript('{$SELF}?cookie='), target);
})();
EOJS;
}

function js2($in_cookie)
{
    $JSNAMESPACE = JSNAMESPACE;
    print <<<EOJS
(function() {
    if (!window.{$JSNAMESPACE}) {
        window.{$JSNAMESPACE} = {};
    }
    window.{$JSNAMESPACE}.cookie = '{$in_cookie}';
    alert(window.{$JSNAMESPACE}.cookie);
})();
EOJS;
}

date_default_timezone_set('Asia/Tokyo');

if ($_SERVER['QUERY_STRING']) {
    $params = explode('&', $_SERVER['QUERY_STRING']);
    $fv = explode('=', $params[0]);
    if (count($fv) != 2) {
        print '// error';
        exit;
    }
    $fname = fingerPrint($fv[0]);
    if ($fv[1]) {
        /* 1st-2 */
        $fh = fopen($fname, 'w+');
        fwrite($fh, $fv[1]);
        fclose($fh);
        header("Location: " . SELF . "?{$fv[0]}=");
    } else {
        if (is_file($fname)) {
            /* 1st-3 */
            $fh = fopen($fname, 'r');
            header('Content-Type: text/javascript');
            header('Last-Modified: ' . date(DATE_RFC822));
            header('X-Finger-Print: ' . $fname);
            js2(fread($fh, filesize($fname)));
            fclose($fh);
            unlink($fname);
        } else {
            /* 2nd, 3rd, ... */
            header("HTTP/1.1 304 Not Modified");
        }
    }
} else {
    /* 1st-1 */
    header('Content-Type: text/javascript');
    js1(fingerPrint(rand()));
}

?>

.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事