Weak PHP security
0x00 weak type
No one doubts the simplicity and power of php. It provides many features for developers, one of which is the weak type mechanism.
You can perform such operations in a weak type mechanism.
<?php$var = 1;$var = array();$var = "string";?>
Php does not strictly check the input variable type, or can convert the variable type freely.
For example, in the comparison of $ a = $ B
$ A = null; $ B = false; // true $ a = ''; $ B = 0; // true
However, developers of the php kernel originally wanted programmers to develop more efficiently with this non-declarative system, therefore, many loose comparisons and conversions are used in almost all built-in functions and basic structures to prevent frequent errors in program variables due to programmer irregularities, however, this brings security issues.
0x02 knowledge preparation: zval structure of php Kernel
The variables declared in PHP are all stored using the zval struct in ZE.
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;
In this example, php uses type to determine whether the variable type is stored in value.
The above is the weak type encapsulation in the php kernel, which is also the principle and basis of everything we will talk about later.
Forced conversion of 0x03 Variables
Based on our understanding, we know that zval. type determines the type stored in zval. value.
When the source code is compared with some unrestricted types or mathematical operations, zval. type may change, and the content of zval. value may change.
When int encounters stringcp.1 mathematical operation
When php performs some mathematical calculations
var_dump(0 == '0'); // truevar_dump(0 == 'abcdefg'); // true var_dump(0 === 'abcdefg'); // falsevar_dump(1 == '1abcdef'); // true
When a comparison parameter is an integer, another parameter is forcibly converted to an integer.
Equivalent
Intval is compared with the integer part. In fact, zval. type is changed. Note that the value of '1assd' after conversion is 1, while that of 'asdaf' is 0.
It also indicates that intval starts from the unit where the first digit is not a number.
All have
Var_dump (intval ('3389a '); // output 3389
This example tells us that we should never trust the following code.
if($a>1000){ mysql_query('update ... .... set value=$a')}
You think the result is an integer.
In fact, $ a may be 1001/**/union...
Loose judgment of cp.2 statement Conditions
For example
Php switch uses loose comparison. $ which will be automatically intval to 0
If there is no break in each case, it will always be executed to include, and finally run to the function we need, which is successfully included
<?phpif (isset($_GET['which'])){ $which = $_GET['which']; switch ($which) { case 0: case 1: case 2: require_once $which.'.php'; break; default: echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false); break; }
Loose judgment of cp.3 Functions
var_dump(in_array("abc", $array));
In_array-check whether a value parameter exists in the array
Needle value to be searched.
Note: If needle is a string, the comparison is case sensitive. Haystack array.
Strict if the value of the third parameter strict is TRUE, the in_array () function also checks whether the needle type is the same as that in haystack.
We can see that only strict type comparison is performed when strict is added, so what if we compare the integer with the string?
var_dump(in_array("abc", $array1));</br>var_dump(in_array("1bc", $array2));
It traverses every value of the array and compares it with "=" ("use =" when strict is set ")
The result is obvious.
If a value in array1 is 0, the first return value is true // intval ('abc') = 0.
If there is a value of 1 in array2, the second one will be true // intval ('1bc') = 1
The same principle applies to array_search.
The application here is very extensive,
Many programmers check the value of the array,
So we can use the constructed int 0 or 1 to cheat the detection function and make it return true.
To sum up, all input strings that are considered as int in php will be forcibly converted. For example
$ A = 'asdfgh'; // string type a </br> echo $ a [2]; // output 'D' according to the php offset </br> echo $ a [x]; // according to the php prediction, this should be int type, then input string, it will be converted into 0 by intval, that is, the output 'A'
When the array encounters a string
This is an example I met in a ctf in Germany. It is very interesting.
We have discussed the comparison between string and int.
What is the chemical reaction of an array when it encounters an int or a string?
Known by the php Manual
The number of elements returned when the Array is converted to the int/float type;
Convert bool to return whether there are elements in Array; convert to string to return 'array', and throw a warning.
So what is the actual application?
if(!strcmp($c[1],$d) && $c[1]!==$d){...}
It can be found that this branch requires that the two are equal through the strcmp function comparison and "=" requires that the two are not equal before entering.
The strcmp () function compares two strings.
This function returns:
0-if the two strings are equal <0-If string1 is smaller than string2> 0-If string1 is greater than string2
The strcmp function converts two variables to ascii and then performs mathematical subtraction to return the difference value of an int.
That is to say, the result of comparing 'A' and 'A' is 0.
What if we compare $ array with 'A?
http://localhost:8888/1.php?a[]=1var_dump(strcmp($_GET[a],'a'));
At this time, php returns null!
That is to say, we let this function go wrong, so that it will remain genuine and bypass the function check.
The following is a loose table.
0x04 always guard against weak types
As a programmer, the weak type does bring great convenience to the programmer to write code, but it also makes the programmer forget
$ Array = array.
All input is harmful.
In fact, it can be said that all input types are suspicious. Never trust any comparison function or any mathematical operation in a weak type of php. Otherwise, you are definitely the one sold by php.