Summary of weak type safety problems in PHP on the 20th day

php
comparison table https://www.php.net/manual/en/types.comparisons.php

Introduction to weak typing in PHP

In PHP, the following operations can be performed.

$a= 1;
$a = array();
$a = "stringg";

Weakly typed languages ​​have no restrictions on the data type of variables. You can assign variables to any other type of variable at any time, and variables can also be converted to any other type of data.

type conversion problem

Type conversion is an unavoidable problem. For example, when the parameters of GET or POST need to be converted to int type, or when the two variables do not match, PHP will automatically convert the variables. But PHP is a weakly typed language, which leads to many unexpected problems when performing type conversions.

comparison operator

A feature of PHP's weak type is used here. When an integer is compared with another type, it will first convert the other type to an integer and then compare.

There are also type conversion problems when using comparison operators, as follows:

<?php
$a = '0';
$b = '';
$c = ' ';
$d = null;
$e = 0;
var_dump($a == $b);  //false
var_dump($a == $c);  //false
var_dump($a == $d);  //false
var_dump($a == $e);  //true
var_dump($b == $c);  //false
var_dump($b == $d);  //true
var_dump($b == $e);  //true
var_dump($c == $d);  //false
var_dump($c == $e);  //true
var_dump($d == $e); 

When variables of different types are compared, there will be problems with variable conversion, and there may be problems after conversion.
insert image description here

Automatic type conversion to 0

When a number is compared with a string, the automatic conversion of the string to the data type will occur. From the left side of the string to the right side, if a number is obtained, then it will be taken down.

otherwise end

insert image description here
insert image description here
1. ==: Type conversion will be performed first, and then comparison will be performed.
2. ===: Types will be compared first. If the types are different, false will be returned directly. Refer to the following
https://www.php.net/manual/zh/types. comparisons.php

insert image description here
insert image description here
insert image description here
insert image description here

Hex conversion

There is also a problem when comparing hexadecimal remainder strings. Examples are as follows:

"0x1e240"=="123456"		//true
"0x1e240"==123456		//true
"0x1e240"=="1e240"		//false

When one of the strings starts with 0x, PHP will parse the string into decimal and then compare it. When 0x1240 is parsed into decimal, it is 123456, so the comparison with 123456 of int type and string type is equal. This feature of phpy.

When performing comparison operations, if a string such as 0x is encountered, PHP will parse it as hexadecimal

10进制数字和10进制数字认为都属于同一个整形的数据类型
insert image description here
Change what a string is now

insert image description here

Type conversion
The common conversion is mainly to convert int to string, and string to int. int to string:

$var = 5;
方式1$item = (string)$var;  
方式2$item = strval($var);

String to int: intval() function. For this function, you can look at 2 examples first.

var_dump(intval('2'))        //2
var_dump(intval('3abcd'))    //3
var_dump(intval('abcd'))    //0

Explain that when intval() converts, it will convert from the beginning of the string until it encounters a non-numeric character. Even if there is a string that cannot be converted, intval() will not report an error but return 0. At the same time, programmers should not use the following code when programming:

if(intval($a)>1000) {
    
    
    mysql_query("select * from news where id=".$a)  //不要轻易比较
}
//这个时候$a的值有可能是1002 union…..

In versions 5.6 and below, when comparing a string containing a number with a string containing a hexadecimal number, a default hex conversion will be performed.
In 7.2, the default conversion will not be performed.
insert image description here

Hash comparison 0exxxx

In addition to the above method, there are also problems when performing hash comparison. as follows:

"0e132456789"=="0e7124511451155"   //true
"0e123456abc"=="0e1dddada"        //false
"0e1234"=="0"                    //true

During the comparison operation, if a string such as 0e\d+ is encountered, the string will be parsed into scientific notation. So in the above example both numbers have the value 0 and thus are equal. If the pattern of 0e\d+ is not satisfied, it will not be equal.

The php feature is equivalent to a power of 0**1234567 when dealing with strings starting with 0e

Version 5.6
insert image description here
insert image description here
insert image description here

++$a $a-- first addition and then subtraction difference

insert image description here
insert image description here

insert image description here

Looseness of arguments to built-in functions

The looseness of built-in functions says that when a function is called, the function is passed an argument type that the function cannot accept. It's a bit hard to explain, but it's better to explain the problem directly through practical examples.

in_array() function

In the PHP manual, the explanation of the in_array() function is bool in_array ( mixed $needle , array $haystack [, bool strict = FALSE ] ) , if the strict parameter is not provided, then inarray will use loose comparison to determine strict = FALSE ] ), if the strict parameter is not provided, then in_array will use loose comparison to determinestrict=FALSE]),If the s t r i c t parameter is not provided , then inar r a y will use a loose comparison to determine if the needle is in $haystack. When the value of strict is true, in_array() will compare whether the type of needsls is the same as the type in haystack.

insert image description here
insert image description here

$array=array(0,1,2,'3');
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true

You can see that the above cases return true, because 'abc' will be converted to 0, and '1bc' will be converted to 1. array_search() and in_array() have the same problem.

in_array, array_search Weakly typed comparison
Under loose comparison, any string is equal to true:

// in_array('a', [true, 'b', 'c'])       // 返回bool(true),相当于数组里面有字符'a'
// array_search('a', [true, 'b', 'c'])   // 返回int(0),相当于找到了字符'a'
// array_search 会使用'ctf'和array中的每个值作比较,这里的比较也是弱比较,所以intval('ctf')==0.
if(is_array(@$a["a2"])){
    
    
        if(count($a["a2"])!==5 OR !is_array($a["a2"][0])) die("nope");
        $pos = array_search("ctf", $a["a2"]);
        $pos===false?die("nope"):NULL;
        foreach($a["a2"] as $key=>$val){
    
    
            $val==="ctf"?die("nope"):NULL;
        }
        $v2=1;
}

strcmp() feature

The description of the strcmp() function in the official PHP manual is int strcmp ( string $str1 , string $str2 ), and you need to pass 2 string type parameters to strcmp(). If str1 is less than str2, return -1, if equal, return 0, otherwise return 1. The essence of the strcmp function to compare strings is to convert two variables into ascii, then perform a subtraction operation, and then determine the return value according to the operation result.
What if the argument passed to strcmp() is a number?

$array=[1,2,3];
var_dump(strcmp($array,'123')); //null,在某种意义上null也就是相当于false。

insert image description here
insert image description here
strcmp(string1, string2): Compare the two strings string1 and string2 in parentheses, when they are equal, return 0; when string1 is greater than string2, return >0; when less than return <0.
In php version 5.3 and later, when strcmp() parentheses are an array and string comparison, null will also be returned.

switch()

If switch is a case judgment of a number type, switch will convert the parameter to int type. as follows:

$i ="2abc";
switch ($i) {
    
    
case 0:
case 1:
case 2:
    echo "i is less than 3 but not negative";
    break;
case 3:
    echo "i is 3";
}

At this time, the output of the program is i is less than 3 but not negative, because the switch() function converts the type of $i, and the conversion result is 2.

md5 hash collision

The description of the md5() function in the PHP manual is string md5 ( string $str [, bool $raw_output = false ] ), and md5() needs to be a string type parameter. But when you pass an array, md5() will not report an error, but it will not be able to calculate the md5 value of the array correctly, which will cause the md5 value of any two arrays to be equal.

$array1[] = array(
    "foo" => "bar",
    "bar" => "foo",
);
$array2 = array("foo", "bar", "hello", "world");
var_dump(md5($array1)==var_dump($array2));       //true

insert image description here
Take advantage of array properties
insert image description here
insert image description here

insert image description here

For md5 hash collision,
see https://blog.csdn.net/m0_43405474/article/details/123228885?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164847994116782092971598%2522%252C%25%253 252220140713.130102334.pc%255Fall.%2522%257D&request_id=164847994116782092971598&biz_id=0&spm=1018.2226.3001.4187

ctfhub : md5 collision
PHP will use "!=" or "==" to compare hash values ​​when processing hash strings, it interprets each hash value starting with "0E" as 0, So if two different passwords are hashed and their hash values ​​start with "0E", then PHP will think they are the same and both are 0.

An attacker can exploit this vulnerability by entering a hashed string starting with "0E", which will be interpreted as 0 by PHP. If there is such a password with a hash value starting with "0E" in the database, He can then log in as this user, even though there is no real password.

$a = $_GET[2];
$b = $_GET[1];
if ($a != $b && md5($a) == md5($b)){
    
    
    echo 'success';
}
else{
    
    
    echo 'failed';
}

insert image description here
insert image description here
insert image description here

Summarize

  1. in_array uses weak type-based comparison by default, and the third one is set to true if the type is also taken into account
  2. strcmp performs a string comparison by default. If the first string is ranked before the second string, it returns -1,
    otherwise the first string is ranked after the second string and returns 1. If the strcmp function is used , it
    returns 0 .
    If an array is compared with a string, it will return
    null

example

<?php
include "flag.php";
if (isset($_GET['message'])) {
    
    
    $message = json_decode($_GET['message']);
    if ($message->key == $flag) {
    
    
        echo 'ok';
    } else {
    
    
        echo 'fail';
    }
}

insert image description here
insert image description here
The default server in the parameter pass will treat the passed parameter as a string

<?php

if (!is_array($_GET['bihuo'])){
    
    
    die();
}
$bihuo = $_GET['bihuo'];
for($i = 0; $i < count($bihuo); ++$i){
    
    
    if($bihuo[$i] === 'bihuo.cn'){
    
    
        echo 'no';
        die();
    }
    $bihuo[$i] = intval($bihuo[$i]);
}
 
if (array_search('bihuo.cn', $bihuo) === 0){
    
    
    echo 'ok, you get it ';
}
else{
    
    
    echo 'no, you failed';
}

insert image description here

in summary

in_array  判断对应的值是否存在于对应的数组中 默认进行基于弱类型的比较 如果说想要基于类型的比较 此时需要设置第三个参数$strict 为true
strcmp 函数 默认用来对比两个字符串的排序问题 当第一个字符串应该排在第二个字符串前 则返回负数(-1) 当第一个字符串应该排在第二个字符串后 返回正数(1) 相等返回0
	当使用strcmp比较一个字符串与数组 此时返回值为null

The default md5 function is to generate a corresponding md5 value from a string
1. The value after the hash collision of two strings is not equal to md5 starts with 0e. At this time, a weak type-based comparison is considered equal
2. When using md5 processing When an array is used, the return value is null

The json_decode function takes a string to generate json formatted content into the integer
array_search function searches the array to see if there is a specific value value, if it exists, it returns the value of its corresponding key, otherwise it returns false by default for weak type-based comparison
switch comparison Use weak typing to compare

Reference https://blog.spoock.com/2016/06/25/weakly-typed-security/
https://github.com/JnuSimba/MiscSecNotes/blob/master/PHP%E5%AE%89%E5%85 % A8 / php% 20% E5% BC% B1% E7% B1% BB% E5% 9E% 8B% E9% 97% AE% E9% A2% 98.md
https://www.ddosi.org/b174/ #% E5% BC% B1% E7% B1% BB% E5% 9E% 8B% E6% AF% 94% E8% BE% 83

Guess you like

Origin blog.csdn.net/qq_42096378/article/details/123794432