php弱比较

在 PHP 中,弱比较(Weak Comparison)指的是在比较两个值时,PHP 可能会进行类型转换以使比较结果为 truefalse。弱比较通常涉及非严格的等于(==)和不等于(!=)操作符,而这些操作符会在比较之前进行隐式类型转换。

弱比较的基本概念

弱比较是 PHP 的一个特性,当两个不同类型的值进行比较时,PHP 会自动将它们转换为相同的类型,然后再进行比较。这个过程被称为 类型转换类型强制

弱比较的操作符

  • ==:等于
  • !=:不等于
  • ===:严格等于
  • !==:严格不等于

在使用 ==!= 时,PHP 会进行弱比较,也就是在比较之前自动转换数据类型;而 ===!== 是严格比较,它们不进行类型转换,只有当值和类型都匹配时才会返回 true

示例和说明

1. 等于(==

在进行弱比较时,PHP 会尝试将两个不同类型的值转换为相同的类型,然后进行比较。

  • 字符串和数字比较

    1
    2
    3
    <?php
    var_dump("123" == 123); // bool(true)
    ?>

    这里 "123" 被转换为整数 123,因此比较结果为 true

  • 布尔值和数字比较

    1
    2
    3
    4
    <?php
    var_dump(false == 0); // bool(true)
    var_dump(true == 1); // bool(true)
    ?>

    false 被转换为 0true 被转换为 1,因此都为 true

  • 空值和其他值比较

    1
    2
    3
    4
    <?php
    var_dump(null == 0); // bool(true)
    var_dump(null == ""); // bool(true)
    ?>

    null0 以及 null 和空字符串 "" 都被认为是相等的。

2. 不等于(!=

类似于 ==,PHP 在使用 != 时也会进行类型转换。

  • 字符串和数字比较

    1
    2
    3
    php复制代码<?php
    var_dump("123" != 123); // bool(false)
    ?>

    因为 "123"123 被认为是相等的,所以结果是 false

  • 布尔值和数字比较

    1
    2
    3
    4
    <?php
    var_dump(false != 0); // bool(false)
    var_dump(true != 1); // bool(false)
    ?>

    false0true1 被认为是不等的结果为 false

3. 严格比较(===!==

严格比较不会进行类型转换,只有当两个值的类型和值都完全相同时才会返回 true

  • 字符串和数字比较

    1
    2
    3
    <?php
    var_dump("123" === 123); // bool(false)
    ?>

    "123" 是字符串类型,123 是整数类型,它们的类型不同,因此比较结果为 false

  • 布尔值和数字比较

    1
    2
    3
    4
    <?php
    var_dump(false === 0); // bool(false)
    var_dump(true === 1); // bool(false)
    ?>

    false 是布尔值,0 是整数;true 是布尔值,1 是整数,类型不同,因此比较结果为 false

4. 空值比较

  • null 和其他值:

    1
    2
    3
    4
    <?php
    var_dump(null === 0); // bool(false)
    var_dump(null === ""); // bool(false)
    ?>

    null不等于任何非 null值,包括 0 和空字符串 "",因此结果为 false

可能出现的陷阱

  • 隐式类型转换可能导致意外行为

    1
    2
    3
    4
    5
    6
    <?php
    $a = 0;
    $b = "0";
    var_dump($a == $b); // bool(true)
    var_dump($a === $b); // bool(false)
    ?>

    在这个例子中,$a$b 的值被认为是相等的(true),但它们的类型不同,因此严格比较结果为 false

  • null 和非 null 的值比较

    1
    2
    3
    4
    5
    6
    <?php
    $a = null;
    $b = false;
    var_dump($a == $b); // bool(true)
    var_dump($a === $b); // bool(false)
    ?>

    nullfalse 被认为是相等的(在弱比较中),但在严格比较中它们不相等。

弱比较绕过示例

  1. 字符串与数字比较

    弱比较允许字符串和数字进行比较,通过利用 PHP 的类型转换,可以绕过一些简单的验证。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    $userInput = "123";
    $storedValue = 123;

    if ($userInput == $storedValue) {
    echo "Match found!";
    } else {
    echo "No match.";
    }
    ?>

    在这个例子中,"123"123 被认为是相等的,因为 PHP 会将 "123" 转换为 123 进行比较。

  2. 布尔值与数字比较

    false 被转换为 0true 被转换为 1。可以利用这种特性绕过一些布尔值检查。

    1
    2
    3
    4
    5
    6
    <?php
    $input = false;
    if ($input == 0) {
    echo "False is equal to zero.";
    }
    ?>

    在这里,false 被转换为 0,因此条件成立。

  3. null 与其他值比较

    null 被认为与 0 和空字符串 "" 相等。

    1
    2
    3
    4
    5
    6
    <?php
    $input = null;
    if ($input == 0) {
    echo "Null is considered equal to zero.";
    }
    ?>

    这里,null0 被认为是相等的,所以条件成立。

  4. 数组与布尔值比较

    空数组和非空数组在弱比较中与布尔值 falsetrue 进行比较。

    1
    2
    3
    4
    5
    6
    php复制代码<?php
    $arr = [];
    if ($arr == false) {
    echo "Empty array is equal to false.";
    }
    ?>

    在这个例子中,空数组 [] 被认为与 false 相等。

例题:

[SWPUCTF 2021 新生赛]easy_md5

img

分析:

如果用get方法传入的name的值不等于用post方法传入的password的值,但它们的md5值相等就可以得到flag

我们通过传入这样的name[]=1password[]=2,因为数组不能转换为md5所以都是null

若遇到===这样的强类型比较,仍然有效,或者还可以使用软件fastcoll进行md5碰撞,生成两个字符串使得他们的md5值相同

参考文章列表 | NSSCTF