知识点
php中的类型转换可以分为2种,一种是是自动类型转换如下:
1 2 3 4 5 6 7
| <?php $foo = "1"; // $foo 是字符串 (ASCII 49) $foo *= 2; // $foo 现在是一个整数 (2) $foo = $foo * 1.3; // $foo 现在是一个浮点数 (2.6) $foo = 5 * "10 Little Piggies"; // $foo 是整数 (50) $foo = 5 * "10 Small Pigs"; // $foo 是整数 (50) ?>
|
第二种是强制类型转换其中支持:
(int), (integer) - 转换为整形 integer
(bool), (boolean) - 转换为布尔类型 boolean
(float), (double), (real) - 转换为浮点型 float
(string) - 转换为字符串 string
(array) - 转换为数组 array
(object) - 转换为对象 object
(unset) - 转换为 NULL (PHP 5)
如:
1 2 3 4
| <?php $foo = 10; // $foo is an integer $bar = (boolean) $foo; // $bar is a boolean 为 1 ?>
|
但是这2种转换中有特别之处需要我们特别注意的,就是字符串内为16进制格式的或者科学计数法格式的
这两种格式,在is_numeric函数中和与数字进行运算时,是会被解析的。而强制类型转换是不进行解析的直接截取例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php $a="0x10"; echo $a."\n"; $c="15"; if($a>$c){ echo "true\n"; } echo $a-0; echo "\n"; echo (double)$a-1; ----------------------------- 0x10 true 16 -1
|
这样就及其可能被利用了,如果开发人员没注意。
其实上面的(double)替换为 int float 等也是成立的。
看道题加深下印象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php show_source(__FILE__); $flag = "xxxx"; if(isset($_GET['time'])){ if(!is_numeric($_GET['time'])){ echo 'The time must be number.'; }else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){ echo 'This time is too short.'; }else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){ echo 'This time is too long.'; }else{ sleep((int)$_GET['time']); echo $flag; } } ?>
|
题目要求我们get传入一个time且它在(5184000,7776000)之间,随后又进行这么长的时间睡眠。这里注意有个 int 强制类型转换 ,我们利用上面说道的知识可以利用16进制或者科学计数法进行绕过。payload如:
1 2
| ?time=6e6 //需要我们等6秒 ?time=0x4f1a01
|