Can you guess it?

猜字符串游戏,了解一下几个函数的机制:

hash_equals ( string $known_string , string $user_string ) : bool

比较两个字符串,无论它们是否相等,本函数的时间消耗是恒定的。

本函数可以用在需要防止时序攻击的字符串比较场景中, 例如,可以用在比较 crypt() 密码哈希值的场景。

random_bytes(int $length)

生成适合于加密使用的任意长度的加密随机字节字符串,例如在生成salt、密钥或初始化向量时,一般配合bin2hex()函数使用。

bin2hex()

把ASCII字符串转换为十六进制值

我们可以看一下hash_equals()内部实现机制

<?php
if(!function_exists('hash_equals')) {
    function hash_equals($a, $b) {
        if(!is_string($a) || !is_string($b)) {
            return false;
        }

        $len = strlen($a);
        if($len !== strlen($b)) {
            return false;
        }

        $status = 0;
        for($i = 0; $i<$len; $i++) {
            $status |= ord($a[$i]) ^ ord($b[$i]);
        }

        return $status  === 0;
    }
}

基本上可以说整个流程是很安全的,所以突破口又回到了前面的文件包含。

<?php
include 'config.php'; // FLAG is defined in config.php

if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
    exit("I don't know what you are thinking, but I won't let you read it :)");
}

if (isset($_GET['source'])) {
    highlight_file(basename($_SERVER['PHP_SELF']));
    exit();
}

记录一下三个$_SERVER的区别:

网址:https://www.shawroot.cc/php/index.php/test/foo?username=root

$_SERVER[‘PHP_SELF’] 得到:/php/index.php/test/foo $_SERVER[‘SCRIPT_NAME’] 得到:/php/index.php $_SERVER[‘REQUEST_URI’] 得到:/php/index.php/test/foo?username=root

漏洞点:$_SERVER['PHP_SELF']提交index.php/config.php时,经过basename过滤后只剩下config.php,需要绕过的只有正则,basename只能转换ASCII码内的字符,通过超过ASCII码范围的字符进行绕过。

/index.php/config.php/%dd?source

Last updated