0%

php的强制类型转换问题

知识点

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

-------------本文结束感谢您的阅读-------------