ctfshow(89,90,92,93)--PHP特性--intval函数
Web89
源代码:
include("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;
}
}
审计
GET传参num。
如果在参数num中匹配到数字,终止程序运行。
如果intval($num)=1,输出flag.
intval()函数可以获取变量的整数值,常用于强制类型转换。
返回值可以分为三种类型:
一. 返回值为0,当转换失败或传入空数组时。
二.返回值为1,当传入数组不为空时。
三.返回值为变量转换成功后的整数值。
思路
我们要让参数num中不含数字的同时让intval($num)=1。
传入非空数组即可。
https://fd97533c-67f2-456a-a94f-714edb3d0262.challenge.ctf.show/
?num[]=1
得到flag.
Web90
源代码:
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{
echo intval($num,0);
}
审计
GET传参num.
如果num强类型比较与"4476"相同,终止程序。
如果intval($num,0)强类型比较与4476相同,输出flag.
int intval( $var, $base )
intval的第一个参数是传入的变量,第二个参数是转换为整数型所使用的进制。默认值为0,此时会根据参数 $var 的格式来选择进制:var以0开头时使用八进制;0x开头则使用十六进制;其他情况下为十进制。
例如有如下代码:
<?php
var_dump(intval(10));
var_dump(intval(012));
var_dump(intval(0xA));
//输出结果为
int(10) int(10) int(10)
转换后的有效结果都是十进制整数型。
思路
利用上述特性,我们可以传入八进制或者十六进制的4476,intval函数就会将其转换为十进制的4476.
?num=010574
?num=0x117c
也可以科学计数法绕过:
?num=4476e1
得到flag.
Web92
源代码:
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{
echo intval($num,0);
}
}
审计
与90题大致相同,但是将强类型比较===
换成了弱类型比较==
=== 与 == 的主要区别在于类型转换和严格性。
=== 是严格相等运算符,不会进行类型转换,如果两边的类型不同,结果一定为不等(false)。
而==是等值运算符,会进行类型转换,如果两边的值在类型转换后相等,结果为相等(true)
思路
$_GET['num']
得到的参数num是string类型的,所以$num
是string类型。
因此比较$num==4476
,就是将字符串与数字进行比较。
如果字符串的开头不是数字,与数字比较就会返回false。
如果字符串开头是数字,就会提取出开头的数字进行比较。
如果是纯数字型字符串,就将字符串转换为数字进行比较。
例如:
<?php
var_dump('php'==10);
var_dump('10.php'==10);
var_dump('10'==10);
//输出
bool(false) bool(true) bool(true)
如果我们还是输入4476e1,那么在进行比较就会提取前面的数字4476,无法绕过条件判断。
但我们输入八进制或十六进制的4476时,字符串中提取的数字就不等于4476,成功绕过条件判断。
传入八进制或者十六进制的4476,intval函数就会将其转换为十进制的4476.
?num=010574
?num=0x117c
得到flag。
Web93
源代码:
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(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
审计
比起92题多了一处条件判断:preg_match("/[a-z]/i", $num)
即:在num中匹配字母,匹配成功则返回1.
思路
十六进制的绕过方法中含有字母x,我们使用八进制绕过即可。
?num=010574