目录(PS:仅个人思路,不保熟🐔🦄🐔🦄🐔🦄🐔🦄🐔🦄🐔🦄🐔🦄🐔🦄🐔🦄🐔)
intval()绕过思路汇总一下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;
}
}
主要流程:大概就是你要给它个“num”参数(get请求),绕过preg——match()函数和intval()函数之后就能拿到flag了
对于intval()函数的绕过我推荐这篇:PHP intval()函数详解,intval()函数漏洞原理及绕过思路_intval函数-CSDN博客
intval()绕过思路
汇总一下intval()函数漏洞的绕过思路:
1)当某个数字被过滤时,可以使用它的 8进制/16进制来绕过;比如过滤10,就用012(八进制)或0xA(十六进制)。
2)对于弱比较(a==b),可以给a、b两个参数传入空数组,使弱比较为true。
3)当某个数字被过滤时,可以给它增加小数位来绕过;比如过滤3,就用3.1。
4)当某个数字被过滤时,可以给它拼接字符串来绕过;比如过滤3,就用3ab。(GET请求的参数会自动拼接单引号)
5)当某个数字被过滤时,可以两次取反来绕过;比如过滤10,就用~~10。
6)当某个数字被过滤时,可以使用算数运算符绕过;比如过滤10,就用 5+5 或 2*5
————————————
此处只要intval返回有值即可,而此处preg-match又过滤了所有的数字,则只需要过滤preg-match就可以获得flag了(intval没有受限制)
对于preg-match这里也是摘一篇文供大家详细了解:
https://www.cnblogs.com/iwantflag/p/15262445.html
preg-match绕过总结:
1,数组绕过 a[]=(想要传的参数)
2,利用PCRE回溯次数绕过(100万次,不推荐)
3,换行符绕过(在web传参时传入换行符"%0a",此处不知道为啥不行🤨🤨)
我使用的是第一种,写成“/?num[]=1”即可
tips:preg_match当检测的变量是数组的时候会报错并返回0。而intval函数当传入的变量也是数组的时候,会返回1
web90:
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num']; //接受num(git参数)
if($num==="4476"){ //强比较类型
die("no no no!");
}
if(intval($num,0)===4476){ //对于intval($var,$base)第二个参数为空时,
echo $flag; //默认值是 0,会根据 $var 的格式来调整转换的进制。
}else{
echo intval($num,0);
}
}
这题只有一个函数需要绕过。记一个知识点,强弱类型区别及绕过:
强类型比较与弱类型比较的区别:
强类型:===,比较值也比较类型
弱类型:==只比较值
绕过方法:
Tips:这样写感觉排版好一些,放到黑框框里单纯觉得好看,并无其他含义也不是代码
1、0e绕过
弱比较会把0exxxx当做科学计数法,不管后面的值为任何东西,0的任何次幂都为0
以下是一些字符串md5值以0e开头
QNKCDZO
240610708
s878926199a
s155964671a
s21587387a
payload:?a=QNKCDZO&b=240610708 即可绕过
2、数组绕过
因为php中md5(数组)返回空值
空值=空值返回ture
3、强类型绕过
(1)、哈希碰撞
4、双md5绕过,就是md5的值和双md5还是0e开头
这个是摘的,后面有道题会用到,到时候详细说,这里只做简单了解。
回顾本题,
第一种方法:我们采用进制转换。
在线进制转换网站(网上搜一下都有):在线进制转换器
1),将4476转换为8进制,并在开头加上0让intval()函数知道我们传入的是8进制数并于4476进行对比,拿下flag。
2),将4476转换为16进制,以0x开头,同上不再赘述。
第二种方法:采用浮点类型。
intval() 转换小数类型时,只返回个位数,不遵循四舍五入的原则。那么我们就可以传入4476.3来实现绕过
还有其他方法大家可以自己思考下。本题过。
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';
}
此处如果我们采取数组绕过“cmd[]=php”就无法行通了,应为我们必须要有“php”才能进入第一个if条件内,而第二个if条件我们又不能有“php”。对于PRCE回溯绕过应该是可行的,但我不hui~(抱歉哈)
因此这里我们只能利用代码特性来思考了。
首先对于preg-match()函数,我们就需要有一个全面的了解,这里摘这个网址:php正则表达式中preg_match函数的详解-php教程-PHP中文网
对于正则表达式的学习还是一个很艰难的过程(不推荐小白学,容易受挫),如果你想了解推荐这篇:正则表达式 – 语法 | 菜鸟教程
emmmmmm再就是正则表达式休止符“/”后面加的参数(仅限PHP语言):php preg match i,PHP中preg_match正则表达式 /i, /is, /s, /isU等含义-CSDN博客
摘录出要用的知识点:
PHP正则表达式修饰符的种类及介绍:
◆i :如果在修饰符中加上"i",则正则将会取消大小写敏感性,即"a"和"A" 是一样的。
◆m:默认的正则开始"^"和结束"$"只是对于正则字符串如果在修饰符中加上"m",那么开始和结束将会指字符串的每一行:每一行的开头就是"^",结尾就是"$"。
综上,对于这题的解法也就有了。
现明确下目标:
我们要传入一个参数,需要拥有“php”关键字以便进入第一个if,在之后绕过第二个preg-match()使其识别不到php。
思路:
既然第一个preg-match() (后面简写preg)修饰符为“im”即匹配每一行,而另一个preg修饰符为“i”即对大小写不敏感(无用,两个preg都有该修饰符),其没有“匹配每一行”的能力,那么我们就可以这样做
php
使用换行符来绕过第二个preg而又不会影响到第一个preg的判断。
Tips:url传参时,换行符的编码为“%0a”
本题过。
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);
}
}
此处和Web90题类似。
先分析,传入参数还是$num,第一个if我们要绕过(使其无法匹配我们的4476),第二个if我们要使之成立,拿到flag。
这里直接就说方法了,详细内容前面都有的。
对于intval()它有一个特性,就是会自动进行进制转换,而且它第二个参数也是“0”,开启了这个功能 。那么方法如之前Web90一样(①转换进制,②小数点),这里放一个传送门,可以去看。
绕过方法:(传送门)
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);
}
}
emmm再次看到相同(几乎)的代码,不知道用意何在。。。难道是防止字符串绕过吗?这里的preg_match()前面也有说过preg-match绕过总结:这里相信大家也能看懂,就是加了一个防止字符串的限制,i修饰符是不区分大小写(即“a”与“A”一样)
我想这是为了限制字符串绕过intval()函数,特此我还去web92试了一下,字符串是绕不过的
对于第一个if,它会检索到你传入的4476然后停止后续判断,这样你的intval()根本就如法解析(传不过去)你传入的参数,所以我还是不明白用意何在🤨🤨绕过同样是采用进制转换(但是这里无法使用16进制,因为你的“0x”中“x”会被检索到)和浮点型绕过。
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;
}
}
这道题就太简单了啊,尽然使用了强类型转换。那么只要类型不一致就ok了(对于第一个if),第二个if还是限制了字母的出现;至于第三个if,等会介绍strpos()函数时说;接下来看第四个if,首先要知道intval函数输出的类型就是整型(int)那么这个强类型比较在类型比较方面就无用了,它只能判断数值是否相同。目前算是简单的分析完了,之后我们再来细看一下,在第一个if中($num==="4476")是将我们传入的参与字符串类型的“4476”做强类型比较。
知识点:传入的参会自动转换为字符串
这里我们需要知道一个东西啊,在我们传参时,emmm专业术语不太会,反正就是在服务器接受该参数时会自动带上双引号,帮助我们转换成字符串格式,所以传参一般不加双引号,如果加了呢也是把双引号传过去,而不是转换字符串。
而对于前面几道题,我们可以发现它的写法是这样的($num==4476)
为什么这里不是与("4476")这种形式做比较呢?是因为对于弱类型比较,不会去比较类型,只比较数值,所以没有这样写。
strpos()函数
前两个if说完了我们来了解下strpos()函数(摘一篇其他人的)了解函数的话我这里只帮你们找,就不做重复叙述,看就行了。
if(!strpos($num, "0")){
die("no no no!");
对于这里为了方便理解,我们先处理“!”,这个符号的意思是取反,如果你是Ture那么就会当作Flase看待,如果是Flase就被当作Ture看待。这里我们是为了跳过if的,也就是说if判断的条件应是Flase,那么经过“!”,我们就得让后面的函数输出Ture或者说是有值输出。
但这里就会有一个陷阱。我们知道,这题同以前一样还是呢两种方法绕过,而对于进制转换,由于prag-match()我们失去了转16进制的方法,而剩下的转8进制,需要最前面是0。陷阱就在这里!可以设想下当我们传入010574时,strpos()函数会检测到“0”并输出第一次“0”所出现的位置,这就相当于strpos()函数输出值为0,而在布尔类型中(Ture和Flase)0代表Flase,1代表Ture。这就相当于我们输出了Flase一样,经过“!”绕过就失败了!所以,这里把8进制绕过法也限制了!
Tips:在字符串中,字符的序号是从0开始排起的,eg:"abcd"中a的序号就是0,c的序号就是2。
因此,我们就只剩下了小数点绕过,但注意我们要保证传入的参数中有0但0又不能在第一个位置上。你可以是4476.0或4476.12312412301231241。只要保证上述条件即可。
本篇就写到这了,也有小5000字了😛😛😛纯纯个人码出来的,其中可能会有错误,毕竟我也是小白🤣,后续还会有。
感谢参考
🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲🐲