wechall:Time to Reset

佐藤です。今回はwechallの問題をやりましたがなかなか面倒で最後まで答えが出せてません。しかし、脆弱性は理解したので書きます。


f:id:eyesjapan:20150428014047p:plain

上記のように、メールアドレスを入れてリセットするとトークンがもらえます。自分のメールでやってみました。

f:id:eyesjapan:20150428014420p:plain

今回はの問題は、admin@wechall.net のユーザーのトークンを奪えということです。
このアプリのソースコードも公開されているので見てみました。
どうやらトークンの生成に脆弱性があるようです。

function ttr_random($len, $alpha='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
        $alphalen = strlen($alpha) - 1;
        $key = '';
        for($i = 0; $i < $len; $i++)
        {
                $key .= $alpha[rand(0, $alphalen)];
        }
        return $key;
}

要求があった個数だけランダムにアルファベット数字が帰ります。
28行目でこれらのrandのシード値が生成されています。

srand(time()+rand(0, 100));

これらをまとめると、

<?php
srand(time()+rand(0, 100));

function ttr_random($len, $alpha='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
        $alphalen = strlen($alpha) - 1;
        $key = '';
        for($i = 0; $i < $len; $i++)
        {
                $key .= $alpha[rand(0, $alphalen)];
        }
        return $key;
}

echo ttr_random(16);

?>

実行結果は、
f:id:eyesjapan:20150428022509p:plain
乱数となっていますね。では時間を固定するとどうでしょう?

<?php
srand(12345678+rand(0,10));
function ttr_random($len, $alpha='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
        $alphalen = strlen($alpha) - 1;
        $key = '';
        for($i = 0; $i < $len; $i++)
        {
                $key .= $alpha[rand(0, $alphalen)];
        }
        return $key;
}
echo ttr_random(16);
?>

f:id:eyesjapan:20150428023854p:plain

いくつか同じトークンが生成されていることがお分かりでしょうか。
randの範囲も100から10に縮めています。10分の1の確率でトークンが衝突します。
つまり、今回のwebアプリケーション(問題)は時間が固定されていれば約100分の1であたることになります。
問題に戻ります。
メールアドレスを送ったとき、そのときの時間と100分の1でトークンが生成されてるとしたらトークンが判明してしまうと思いませんか!?
で、多分ここからブルートフォースだと思います。
生成した時間よりシードを作成しそこから100通りのトークンがどれかになるはずです。
スクリプトができ次第編集します。