PHP8字符串数字弱类型比较优化

这一个改动可能会对安全漏洞挖掘的影响较大。PHP 8 以前,在使用==比较或任何有弱类型转换的情况时,字符串都会先转换成数字,再和数字进行比较。

比如,这个代码在PHP 8以前的结果是true和0,在PHP 8以后得到的则是false和1:

var_dump('a' == 0);
switch ('a') {
    case 0:
        echo 0;
        break;
    default:
        echo 1;
        break;
}

老的弱类型可能会有什么安全问题呢?我曾经挖掘到的一个真实案例,大概代码是这样:

$type = $_REQUEST['type'];
switch ($type) {
    case 1:
        $sql = "SELECT * FROM `type_one` WHERE `type` = {$type}";
        break;
    case 2:
        $sql = "SELECT * FROM `type_two` WHERE `type` = {$type}";
        break;
    default:
        $sql = "SELECT * FROM `type_default`";
        break;
}

开发者认为$type是1和2的时候才会进入SQL语句拼接中,但实际我们传入1 and 1=2即可进入case 1,导致SQL注入漏洞。

PHP 8以后彻底杜绝了这种漏洞的产生。