Home  >  Article  >  Backend Development  >  Talk about PHP weak type safety issues

Talk about PHP weak type safety issues

little bottle
little bottleforward
2019-04-27 11:37:303050browse

The editor of this article wants to talk to you about PHP weak typing. PHP weak typing brings great convenience to programmers when writing code, but everything has two sides. Now let’s learn about it with the editor.

0x00 A preliminary study on weak types

No one questions the simplicity and power of PHP. It provides many features for developers to use, one of which is weak type. type mechanism.

Under the weak type mechanism, you can perform such an operation

<?php
$var = 1;
$var = array();
$var = "string";
?>

php will not strictly check the type of the incoming variable, and can also freely convert the variable type.

For example, in the comparison of $a == $b

$a = null; $b = false; //为真
$a = &#39;&#39;; $b = 0; //同样为真

However, the developers of the PHP kernel originally wanted programmers to use this system that does not require declarations to be more efficient. Development, so a lot of loose comparisons and conversions are used in almost all built-in functions and basic structures to prevent variables in the program from frequently reporting errors due to programmers' irregularities. However, this brings security issues.

0x02 Knowledge Preparation PHP Kernel Zval Structure

Variables declared in PHP are stored in ZE using the structure zval The

zval is defined in zend/zend.h

typedef struct _zval_struct zval;  
struct _zval_struct {  
  /* Variable information */  
  zvalue_value value; /* value */  
  zend_uint refcount__gc;  
  zend_uchar type;/* active type */  
  zend_uchar is_ref__gc;  
};  
typedef union _zvalue_value {  
  long lval;  /* long value */  
  double dval;/* double value */  
  struct {  
    char *val;  
    int len;  
  } str;  
  HashTable *ht;  /* hash table value */  
  zend_object_value obj;  
} zvalue_value;

where PHP determines the variable type through type and stores it in value

The above is the encapsulation of weak types in the PHP kernel. It is also the principle and foundation of everything we will talk about later.

Forcing conversion of 0x03 variables

Through the previous understanding, we know that zval.type determines the type stored in zval.value.

When the source code performs some unrestricted type comparisons or mathematical operations, it may cause zval.type to change, and at the same time affect the content of zval.value to change.

When int meets string

cp.1 Mathematical operations

When PHP performs some mathematical calculations

ar_dump(0 == &#39;0&#39;); // true
var_dump(0 == &#39;abcdefg&#39;); // true  
var_dump(0 === &#39;abcdefg&#39;); // false
var_dump(1 == &#39;1abcdef&#39;); // true

When one comparison parameter is an integer, the other parameter will be forced to be converted to an integer.

Equivalent to comparing the string part

intval with the integer part. In fact, it changes the content of zval.type. Especially note that the converted value of '1assd' is 1 , and 'asdaf' is 0

It also means that intval will start from the first unit that is not a number

All also have

var_dump(intval(&#39;3389a&#39;));//输出3389

This example tells us, always Don't believe the following code

if($a>1000){    
mysql_query(&#39;update ... .... set value=$a&#39;)
}

You think that entering the branch at this time is an integer

In fact, $a may be 1001/**/union...

cp.2 Loose judgment of statement conditions

For example, PHP's switch uses loose comparison. $which will be automatically changed to 0 by intval. If there is no break in each case, it will Execute until inclusion, and finally execute to the function we need. Here is the loose judgment of the successfully included

<?php
if (isset($_GET[&#39;which&#39;]))
{
  $which = $_GET[&#39;which&#39;];
  switch ($which)
  {
  case 0:
  case 1:
  case 2:
    require_once $which.&#39;.php&#39;;
    break;
  default:
    echo GWF_HTML::error(&#39;PHP-0817&#39;, &#39;Hacker NoNoNo!&#39;, false);
    break;
  }

cp.3 function

var_dump(in_array("abc", $array));

in_array — Check whether the array is There is a value parameter

needle for the value to be searched for.

Note: If needle is a string, the comparison is case-sensitive. haystack this array.

strict If the value of the third parameter strict is TRUE, the in_array() function will also check whether the type of needle is the same as that in haystack.

As you can see, only by adding strict will the types be strictly compared. So what if we compare ××× with strings again?

var_dump(in_array("abc", $array1));</br>
var_dump(in_array("1bc", $array2));

It traverses each value of the array and performs "==" comparison ("when strict is set, use ===")

The result is obvious

If there is a value in array1 that is 0, then the first return will be true //intval('abc')=0

If there is a value in array2 that is 1, then the second one will be True//intval('1bc')=1

The same principle applies to array_search

The application here is very wide,

Many programmers will check the array value,

Then we can completely use the constructed int 0 or 1 to fool the detection function and make it return true

To summarize, enter string in all places that PHP thinks are ints. will be forced to convert, such as

$a = &#39;asdfgh&#39;;//字符串类型的a</br>
echo $a[2];  //根据php的offset 会输出&#39;d&#39;</br>
echo $a[x];  //根据php的预测,这里应该是int型,那么输入string,就会被intval成为0 也就是输出&#39;a&#39;

When the array meets string

I encountered this example in a ctf in Germany. It is very interesting. What we talked about earlier They are all comparisons between string and int

So what chemical reaction will there be when array encounters int or string?

We know from the PHP manual that

Converting Array to int/floating point type float will return the number of elements;

Converting bool returns whether there are elements in the Array; convert to string returns 'Array' and throws warning.

So what is the practical application?

if(!strcmp($c[1],$d) && $c[1]!==$d){
...
}

It can be found that this branch requires the two to be equal through strcmp function comparison and "==" requires that the two are not equal to enter.

strcmp() function compares two strings.

This function returns:

0 - if the two strings are equal

a8bacc06128749489fc86bda2552a2bc0 - if string1 Greater than string2

The strcmp function here actually converts the two variables into ascii and then performs mathematical subtraction to return the difference of an int.

That is to say, the result of typing 'a' and 'a' to compare is 0

So what if $array is compared with ‘a'?

http://localhost:8888/1.php?a[]=1
var_dump(strcmp($_GET[a],&#39;a&#39;));

At this time php returned null!

In other words, we make this function error so that it will always be true, bypassing the function check.

0x04 Always beware of weak types

As a programmer, weak types do bring great convenience to programmers when writing code. But it also makes programmers forget the habit of $array =array();. It is said that all input is harmful

In fact, it can be said that the type of all input is also suspicious. Never trust any comparison function or any mathematical operation under weakly typed PHP. Otherwise, you are definitely the one betrayed by php.

Related tutorials: PHP video tutorial

The above is the detailed content of Talk about PHP weak type safety issues. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:51cto.com. If there is any infringement, please contact admin@php.cn delete