前言
文章同步我的个人博客http://www.quan9i.top/,欢迎大家访问。
php特性的intval是一个比较常见的漏洞,今天就来比较全面的学习这个函数,将其简单的利用方式总结一下
函数学习
学习函数最好的方式就是去学习官方的,这样学习得到的收获更多一些,这里我们先来看一下这个函数定义
intval — 获取变量的整数值
而它的具体格式和解释如下
intintval(var,base)//var指要转换成 integer 的数量值,base指转化所使用的进制
Note:
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
◦ 如果字符串包括了 "0x"(或 "0X") 的前缀,使用 16 进制 (hex);否则,
◦ 如果字符串以 "0" 开始,使用 8 进制(octal);否则,
◦ 将使用 10 进制 (decimal)。
这里这个Note对我们来说就尤为重要了,没有声明base参数时,字符串首字母是0则视为8进制,是0X则视为16进制,具体可以看官方给出的例子
<?phpechointval(042);// 34echointval(0x1A);// 2?>
此时就可以看出它的一个利用方式了,当过滤某个数字时,我们可以利用它的进制转换来绕过。
此时再往下看
返回值
成功时返回 var 的 integer 值,失败时返回 0。空的 array 返回 0,非空的 array
返回 1。
这时候就可以看出另一个利用方式了,如果是一个弱比较
a==b
我们输入
a[]=1
和
b[]=2
,此时这两个是不同的,但还都会返回1,此时也就实现了一种绕过,这是第二种绕过思路。
此时官方还给出了其他示例,我们再看
echointval(42);// 42echointval(4.2);// 4
我们可以发现小数点后的数字会直接舍去,所以这可以作为第三种,当过滤4的时候,我们可以输入4.2来绕过
然后呢,我们还发现例子里有
1e
这种格式的,
echointval(1e10);// 1410065408echointval('1e10');// 1
这个呢我们发现单引号传值的时候,它只识别字母前面的一部分,当我们进行get传参时,我们其实就是默认加单引号的,所以这又是一种绕过方式。
还有说一下这里不是必须是e,这里只要是字母就可以
实战
0X01
<?phpinclude("flag.php");highlight_file(__FILE__);if(isset($_GET['num'])){$num=$_GET['num'];if(preg_match("/[0-9]/",$num)){die("no no no!");}if(intval($num)){echo$flag;}}?>
看见这题我的思路就是用数组绕过,可能是因为之前md5()的时候强比较看习惯了,这里构造payload如下即可
num[]=1
0X02
include("flag.php");highlight_file(__FILE__);if(isset($_GET['num'])){$num=$_GET['num'];if($num==="4476"){die("no no no!");}if(intval($num,0)===4476){echo$flag;}else{echointval($num,0);}}
这关的话就是要求变量值不能为4476,但用过intval函数后为4476,这里的话我们首先需要知道intval的第二个参数为0时的意思是什么
intintval(var,base)
Note:
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
◦ 如果字符串包括了 "0x"(或 "0X") 的前缀,使用 16 进制 (hex);否则,
◦ 如果字符串以 "0" 开始,使用 8 进制(octal);否则,
◦ 将使用 10 进制 (decimal)。
此时的话我们再看一下在这个函数的运算
看到这里的话就可以看出payload就有多种构造方法了
num=4476e123//这里就跟上面那个单引号的1e10情况一样,此时只看字母前面的
num=4476.1//计算int值时,后面有小数点会直接舍去
num=0x117c//0x表明是十六进制数,117c是4476的十六进制数
num=010574//0表明是八进制数,10574是4476的八进制数
测试如下
执行结果如下
0X03
include("flag.php");highlight_file(__FILE__);if(isset($_GET['num'])){$num=$_GET['num'];if($num==4476){die("no no no!");}if(intval($num,0)==4476){echo$flag;}else{echointval($num,0);}}
这里的话就是从强比较换成了弱比较,用之前的解题payload即可
num=4476.1
0X04
include("flag.php");highlight_file(__FILE__);if(isset($_GET['num'])){$num=$_GET['num'];if($num==4476){die("no no no!");}if(preg_match("/[a-z]|\./i",$num)){die("no no no!!");}if(!strpos($num,"0")){die("no no no!!!");}if(intval($num,0)===4476){echo$flag;}}?>
这道题的话看着几乎是防死了,多过滤了
.
,这就意味着小数点绕过行不通,此时我们看到这个i修饰符,想到那个m修饰符,此时就想起来有个换行符%0a,它对实际输出没影响,它还可以绕过上面的那些函数,因此我们这里构造如下语句,就实现了绕过,由于小数点不能用,这里就用八进制
num=%0a010574
版权归原作者 quan9i 所有, 如有侵权,请联系我们删除。