PHP

基礎知識

演算子の比較表

画像は PHP STRING COMPARISON VULNERABILITIES に載っているやつです。

strcmp

配列や3引数以上与えると NULL が返ってくる。

var_dump(strcmp("a", "a")); // int(0)
var_dump(strcmp("a", "b")); // int(-1)
var_dump(strcmp("a", "b", "c")); // NULL
var_dump(strcmp([], "a")); // NULL

そのため == で比較してたりするとバイパスできてしまう。(strcmp は2つの文字列が等しい場合 0 を返すため、NULL == 0 が成立する)

// 問題のあるコード
if (strcmp("a", "b", "c") == 0) {
echo "bypassed (arity 3)";
}
// 問題無いコード
if (strcmp("a", "b", "c") === 0) {
echo "bypassed (arity 3)";
}

parse_str

与えられたクエリパラメータ key=valを用いて、変数 key に val を代入する。

その際、既存の変数を上書きできてしまう点に注意。

以下のコードは一見問題なさそうに見えるが、?hashed_key=xxx というパラメータが与えられた場合、hashed_key の既存の値が xxx になってしまう。つまり、任意の値に書き換えることができる。

$hashed_key = '79abe9e217c2532193f910434453b2b9521a94c25ddc2e34f55947dea77d70ff';
$parsed = parse_url($_SERVER['REQUEST_URI'])
$parsed_query = parse_str($parsed["query"]);
$hashed_input = hash('sha256', $_GET["key"]);
if($hashed_input !== $hashed_key){
die("GTFO!");
}
echo file_get_contents("/flag");

parse_url

パラメータ・フラグメントに @ から始まるホスト名を指定すると、なぜか上書きできてしまう。

報告

Fix

5.6.26

5.6.28

php > echo parse_url("http://example.com:80#@google.com/")["host"];
google.com
php > echo parse_url("http://example.com:80?@google.com/")["host"];
google.com