🎃

レガシーコードをあるがままに保護しつつセッションを盗み見するための工夫

2021/06/23に公開

PHPレガシーコード、保全したいんですよね、僕はしたくないですが。

たとえばこういうコードがあったとする。

<?php
## Old-skool style PHP will never die.
session_start();

## Confidential must be stored within the session, you know?
if(!isset($_SESSION['my-secret'])){
    $secret = rand(1,1000);
    $_SESSION['my-secret'] = $name . $secret;
}
echo "<h2>my-secret:".$_SESSION['my-secret']."</h2>";
?>

ちょっとした依頼で「これ、どうなってるのか調べて」といわれる。色々ページを行き来すると、SESSIONに保持されたCSRF_TOKENが予期せぬタイミングで書き換わってる「らしい」とか、なんとか。

「ただし、調査のためにはコードは一切いじらないでね、そして本番しか環境ないから」といわれることが有ります。なるほど。

で、この間Symfonyのコードをみながらそうかーとなって、昔ながらのトリックをつかった様子がこちらです。

<?php // steal-session.php
# capture SESSION
session_start();
$pre_session = $_SESSION;
session_write_close();

ob_start();
@include($_SERVER['SCRIPT_FILENAME']);
echo $____output = ob_get_clean();

# check modified SESSION.
$after_session = $_SESSION;

# save.
@file_put_contents(
    'my-bag.ndjson',
    @json_encode(
        [
            'pre' => $pre_session,
            'after' => $after_session,
        ],
        JSON_UNESCAPED_UNICODE
    ),
    FILE_APPEND
);

exit();
$ php  -d auto_prepend_file=steal-session.php -S 127.0.0.1:3000
$ cat my-bag.ndjson |jq .
{
  "pre": [],
  "after": {
    "my-secret": "asdf432"
  }
}
{
  "pre": {
    "my-secret": "asdf432"
  },
  "after": {
    "my-secret": "asdf432"
  }
}

@ つかいまくってるので、実にレガシーですね。もちろん上のjsonにはREQUEST_URIとかタイムスタンプとかをいれることもできますし、実際いれます。$_SERVER['REMOTE_ADDR']とかで絞ることもするでしょう。

本番にこういうコードをいれるの正気かって?そうですね、しかしまあ、言われた通りに「既存の」コードはさわってないですし、Apacheの.htaccessに一行入れるくらいならゆるされる世界というのもあります。

応用は色々あるんですけど、省略します。

https://github.com/uzulla/sneak-thief.php

ではまた。

Discussion