PHP过滤函数缺陷

  • ==与===

    ==不比较类型,===比较类型。

  • md5

    1
    2
    3
    4
    5
    if($_GET['name'] != $_GET['password']) {
    if(MD5($_GET['name']) == MD5($_GET['password'])) {
    echo $flag;
    }
    }
    • 科学计数法

      如果一个字符串为合法数字+e+合法数字类型,将会解释为科学计数法的浮点数。

      那么只要找到字符串的MD5值为0e开头的,即可绕过。如:name=QNKCDZO&password=240610708

      但是这种方法只能在==情况下绕过,因为===是会比较类型,而MD5函数返回的是字符类型,无法转换成数字。

    • 数组

      md5函数无法处理数组,如果传入的为数字,会返回NULL。如:name[]=1&password[]=2。这种绕过在===的情况下也可以使用。

  • intval

    1
    2
    3
    4
    5
    $num = 68;
    $n = $_GET['n'];
    if(intval($n$base=0) == $num) {
    echo $flag;
    }

    $base=0时,如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);如果字符串以 “0” 开始,使用 8 进制(octal);否则,将使用 10 进制。

    这样就可以通过n=0104的方式绕过。

  • strpos

    1
    2
    3
    4
    5
    $num = 666;
    $n = $_GET['n'];
    if(strpos($n, $num) !== FALSE) {
    echo $flag;
    }
    • 数组绕过

      strpos无法处理数组,会返回null

    • 首次出现下标为0

      传入n=666strpos函数返回0,即可成功绕过。

  • in_array

    1
    bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

    默认情况下,$strict = FALSE,即不比较类型是否相同,可以通过科学计数法等方法绕过。

  • preg_match

    1
    2
    3
    4
    5
    6
    7
    8
    9
    if(isset($_GET['num'])){
    $num = $_GET['num'];
    if(preg_match("/[0-9]/", $num)){
    die("no no no!");
    }
    if(intval($num)){
    echo $flag;
    }
    }

    preg_match函数无法处理数组,传入的如果是数组就无法进行处理,而intval函数若传入的是一个非空数组,则返回1,即可绕过。

  • str_replace

    1
    2
    3
    $sql = $_GET['s'];
    $sql = str_replace('select','',$sql);
    echo $sql;

    str_replace函数只会进行单次过滤,可以通过双写等方法进行绕过。如:s=seselectlect