常见的弱类型问题
类型转换问题
类型转换是无法避免的问题。例如需要将GET或者是POST的参数转换为int类型,或者是两个变量不匹配的时候,PHP会自动地进行变量转换。但是PHP是一个弱类型的语言,导致在进行类型转换的时候会存在很多意想不到的问题。
数学运算
当php进行一些数学计算的时候
<?phpvar_dump(0 == '0'); // truevar_dump(0 == 'abc'); // true var_dump(0 === 'abc'); // falsevar_dump(1 == '1abc'); // truevar_dump('1e0'=='1e2'); // falsevar_dump('0.0'==0); // truevar_dump('0.0'==''); //false//还有下面这样的if(md5('s878926199a')==0){ echo 'true';}?>因为md5('s878926199a')=0e545993274517709034328855841020就是0的n次方,所以还是等于0
但是要注意:
"0e123456abc"=="0e1dddada"//false
这种返回的是为假
语句条件的松散判断
<?phpif (isset($_GET['which'])){ $which = $_GET['which']; switch ($which) { case 0: case 1: case 2: require_once $which.'.php'; break; }}?>函数的松散判断
<?phpif(strcmp('1a',1)){ echo 'test';}?><?phpvar_dump(in_array("1a", array(1,2,3)));?>In_array函数和array_search函数的问题可以在in_array函数后面加一个true选项,就能解决比如:
<?phpif(in_array("1a", array(1,2,3),true)){ echo 'true';}?>md5()$array1[] = array( "foo" => "bar", "bar" => "foo",);$array2 = array("foo", "bar", "hello", "world");var_dump(md5($array1)==md5($array2));//回显为true十六进制转换
还存在一种十六进制余字符串进行比较运算时的问题。例子如下:
"0x1e240"=="123456"//true "0x1e240"==123456//true "0x1e240"=="1e240"//false当其中的一个字符串是0x开头的时候,PHP会将此字符串解析成为十进制然后再进行比较,0×1240解析成为十进制就是123456,所以与int类型和string类型的123456比较都是相等。
下面我们来看一个dedecms的弱类型安全问题。
漏洞分析
dedecms/member
//75行
管理员帐号admin的$row['safequestion']
默认是为’0’
(字符串),所以$safequestion
不能为空。否则不进入$row['safequestion'] == $safequestion
。而$_GET[‘safequestion ’]
传过来的值为字符串,当$_GET[‘safequestion ’
]为’0’
时进入if(empty($safequestion))
。当$_GET[‘safequestion ’]
为’0.0’
时不进入if(empty($safequestion))
,而’0’=’0.0’
进入if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer)
,右边的$safeanswer
本身就为空。所以不用理。
跟进函数sn
:
这里从数据库取出来的值应该为空$sql = "SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'";
于是进入
注意一下$send
为N
我们跟进newmail
函数:
这里直接是对dede_pwd_tmp
表插入临时密码,临时密码为$randval = random(8);
是8位,但是别急。紧接着插入完成之后ShowMsg('稍后跳转到修改页', $cfg_basehost.$cfg_memberurl."?dopost=getpasswd&id=".$mid."&key=".$randval);
也就是说在insert
完成之后跳转把$randval
输出到了页面。