`搜索公众号:白帽子左一,领配套练手靶场,全套安全课程及工具`
一、PHP弱类型简介
弱类型简单来说就是数据类型可以被忽视的语言,和强类型语言的强制数据类型定义不同,弱类型可以一个变量赋不同数据类型的值
php虽然属于弱语言,但是里面也有一些强语言类型相关的强制定义数据类型的方法
比如php里的 ==
和 ===
之间的区别
==
为松散比较 只比较值,不比较数据类型
而 ===
为严格比较,不仅比较值也比较类型,可以看作是强语言的强制数据类型要相同
二、PHP弱类型影响
具体表现在比如像一些数据验证上,两个变量类型不匹配时进行类型转换时可能会将传递的参数类型转换,一些函数存在松散性的问题,调用时,给函数传递函数无法处理的参数类型但是没有报错,直接返回null,这些都有可能产生各种问题
这里以一个ctf题,举例:
示例代码:
<?php
$pass=@$_GET['pass'];
$pass2=@$_GET['pass2'];
@$pass1='asdasdasd';
if(strcmp($pass,$pass2)==0&& $pass != $pass2){
echo "$pass1";
}else{
echo "aaaa!";
}
?>
这里需要传入两个变量,对比两个参数要相同且两个字符串内容要不同
那么怎么才能让它相同呢,这里可以通过传入数组去让它等
分别传入不同的数组,结果为
传入参数相同时
通过数组就绕过了限制,具体为什么可以看后面关于该函数的介绍
三.php 内核之 zval 结构
在 PHP 中声明的变量,在 ZE 中都是用结构体 zval 来保存的
php 内核中弱类型的封装
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;
其中 php 通过 type 判断变量类型 存入 value。
类型转换问题
zval.type 决定了存储到 zval.value 的类型。当源代码进行一些未限制类型的比较,或数学运算的时候,可能会导致 zval.type 的改变,同时影响 zval.value 的内容改变。
比较操作符
===
在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
==
在进行比较的时候,会先将字符串类型转化成相同,再比较
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
比较简单,不过多举例。
Hash 比较缺陷
"0e132456789"=="0e7124511451155" //true
"0e123456abc"=="0e1dddada" //false
"0e1abc"=="0" //true
在进行比较运算时,如果遇到了 0e\d + 这种字符串,就会将这种字符串解析为科学计数法。
如果不满足 0e\d + 这种模式,就会当作字符串进行比较,所以不会相等。
十六进制转换
"0x1e240"=="123456" //true
"0x1e240"==123456 //true
"0x1e240"=="1e240" //false
当其中的一个字符串是 0x 开头的时候,PHP 会将此字符串解析成为十进制然后再进行比较。
四.类型转换
<?php
$test=1 + "10.5"; // $test=11.5(float)
$test=1+"-1.3e3"; //$test=-1299(float)
$test=1+"bob-1.3e3";//$test=1(int)
$test=1+"2admin";//$test=3(int)
$test=1+"admin2";//$test=1(int)
?>
PHP 手册:当一个字符串欸当作一个数值来取值
其结果和类型如下:如果该字符串没有包含’.’,’e’,’E’ 并且其数值值在整形的范围之内该字符串被当作 int 来取值,其他所有情况下都被作为 float 来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为 0。
intval () 函数:intval () 转换的时候,会将从字符串的开始进行转换知道遇到一个非数字的字符。即使出现无法转换的字符串,intval () 不会报错而是返回 0。
var_dump(intval('2')) //2
var_dump(intval('3abcd')) //3
var_dump(intval('abcd')) //0
bool 欺骗
当存在 json_decode 和 unserialize 的时候,部分结构会被解释成 bool 类型。
json_decode 示例代码:
$json_str = '{"user":true,"pass":true}';
$data = json_decode($json_str,true);
if ($data['user'] == 'admin' && $data['pass']=='secirity')
{
print_r('logined in as bool'."\n");
}
运行结果:logined in as bool
unserialize 示例代码:
$unserialize_str = ‘a:2:{s:4:“user”;b:1;s:4:“pass”;b:1;}’;
d a t a u n s e r i a l i z e = u n s e r i a l i z e ( data_unserialize = unserialize( dataunseria