URLパラメータの改ざん検出をする


目的

  • URLにユーザーごとのパラメータを埋め込んで公開したい
  • Twitterなどに投稿されたとき、パラメータが改ざんされているかをチェックしたい
  • 改ざん検知のために、DBなどの仕組みを使用したくない
    • (単純に、パラメータが書き換えられていないかのチェックでよい)

使用例

上記の目的がわかりにくいと思うので、実例を説明します。
三点リーダー症候群チェッカーというWebサービスを作りました。
自分の過去のツイートに、どのくらい三点リーダー(…)が使用されているかを表示できます。
Twitterへのシェア機能が実装されており、自分の分析結果を動的OGP画像として共有できます。

ユーザーごとのシェアURLhttps://santen-leader.nankakaku.com/share/Misa_Fd/32/169/FX174A

シェアURLは、以下のような構成をしています。
/share/{ユーザー名}/{スコア分子}/{スコア分母}/{ハッシュ値}

もしパラメータに改ざんを検出した場合は、デフォルトのOGP画像が表示されます。
改ざんされたシェアURLhttps://santen-leader.nankakaku.com/share/Misa_Fd/100/169/FX174A

このユーザ名・スコア分子・スコア分母の値を使用して動的OGP画像を作成しますが、
改ざん検出の仕組みを入れないと、ユーザーが自分のスコアを偽装できてしまいます。
分析結果をサーバに保存していないため、実際のデータと比較することもできません。
そのため、末尾にハッシュ値を付加して対策しています。

実装概要

大まかには、以下のような仕組みを採用しています。
URL作成時:シェアURL生成時に、「ユーザ名」「スコア分子」「スコア分母」「ハッシュ化文字列」を使用してハッシュ値を生成する
改ざんチェック時:「ユーザ名」「スコア分子」「スコア分母」「ハッシュ値」が改ざんされていないか、「ハッシュ化文字列」を使用して検証する

実装詳細

URL生成時

下記ような関数を使用して、パラメータからハッシュを作成しています。

public static function generateShortHash($screenName, $matchCount, $totalCount, $algo = 'CRC32') {
    $hashSource = $screenName . "/" . $matchCount . "/" . $totalCount . "/STRING_FOR_HASHING";
    return strtr(rtrim(base64_encode(pack('H*', hash($algo, $hashSource))), '='), '+/', '-_');
}

短いハッシュを作成するための方法は、下記の記事を参考にさせていただきました。ありがとうございました。
https://qiita.com/koriym/items/efc1c419e4b7772b65c0

改ざんチェック時

上記の関数を用いて、送信されたハッシュ値が一致するかを検証しています。
一致する場合は動的OGP画像を生成し、一致しない場合はデフォルトの静的OGP画像を、シェアURLのOGP画像に指定しています。

参考ページ

PHPで短いハッシュ