| PHP弱类型 |

Hash比较(科学计数法)

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

十六进制转换

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

字符串解析为十进制在进行比较

类型转换

Int转string

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

String转int : intval()函数

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

Ctf demo

if(intval($a)>1000) {
mysql_query(“select * from news where id=”.$a)
}

$a=1002 union… 造成sql注入

intval()

intval()转换的时候,会将从字符串的开始进行转换知道遇到一个非数字的字符。
即使出现无法转换的字符串,intval()不会报错而是返回0。
注:
在科学计数法字符串转换为数字时,如果 E 后面的数小于某个值会弄成 double 类型,再强制转换为 int 类型时可能会有奇妙的结果,测试发现某变量为 1e-1000 时已经可以触发这个漏洞绕过两个检查,使得某变量既大于 0 又不大于 0。
例如:

var_dump((int)('1e-1000')>0);
var_dump('1e-1000'>0);

结果

Command line code:1:
bool(true)
Command line code:1:
bool(false)

再如:

var_dump((int)('1e-10')>0);
var_dump('1e-10'>0);

结果

Command line code:1:
bool(true)
Command line code:1:
bool(true)

ereg()

字符串对比解析,ereg函数存在NULL截断漏洞,当ereg读取字符串string时,如果遇到了%00,后面的字符串就不会被解析。
注:这里的%00是需要urldecode才可以截断的,这是url终止符,且%00长度是1不是3

内置函数的参数的松散性

内置函数的松散性说的是,调用函数时给函数传递函数无法接受的参数类型。

md5()

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

Strcmp()

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

switch()

如果case判断值为int形,switch会将传入的参数转换为int类型

$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";
}

“==”和’===’弱类型问题

==:比较两侧的值,不同类型会自动转换为同种类型。如传参与整形比较->整形。传参与字符串比较->字符串

<?php
$a = $_GET['a'];
if ($a==1)
{
echo ‘vul->’.$a;
}

Payload : http://127.0.0.1/fuzz.php?a=1a
成功进入if条件语句中

“===”: 符号比较两侧的值和类型,但不是绝对安全的。在加减乘除中会自动进行整形转换。
DEMO:

<?php
$a = $_GET['a'];
$b = $_GET['b'];
if($a+$b===2)
{
echo 'vul->'.$a.'</br>'.$b;
}

Payload : "http://172.31.19.5/fuzz.php?a=1a&b=1b"
成功进入条件语句

修复策略

:intval强制类型转换或者过滤

In_array()函数使用不严谨导致的弱类型

if(in_array($_GET['id'],array(1,2,3,4,5)))
{
echo $_GET['id'];
}

Payload:"http://172.31.19.5/fuzz.php?id=1a"
成功转换

修复方式

开启函数中的参数strict=Ture ,传参使用intval修饰
if(in_array(intval($_GET['id']),array(1,2,3,4,5),true))

is_numeric()十六进制转换字符

<?php 
if(is_numeric($_GET['num']))

{

//echo $_GET['num'];

echo '</br>';

//假设这个插入进了mysql数据库,mysql数据库就会把十六进制转换成了字符串,这里为了方便用 Hex2String 函数代替

echo Hex2String($_GET['num']);



}

function Hex2String($hex){

$string=”;

for ($i=0; $i < strlen($hex)-1; $i+=2){

$string .= chr(hexdec($hex[$i].$hex[$i+1]));

}

return $string;

}

?>

//输入http://127.0.01/equal.php?num=0x39393939393939393939393920756e696f6e20616c6c202873656c656374202748656c6c6f21212729
//输出0x39393939393939393939393920756e696f6e20616c6c202873656c656374202748656c6c6f2121272
//输出9999999999999 union all (select ‘Hello!!’)

参考链接;https://blog.spoock.com/2016/06/25/weakly-typed-security/
https://skysec.top/2017/07/22/PHP%E5%87%BD%E6%95%B0%E9%BB%91%E9%AD%94%E6%B3%95%E5%B0%8F%E6%80%BB%E7%BB%93/


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!