而使用===必须类型一致,传入y=1.0 / y=1
MD5函数
在 PHP 中,md5()
函数的一个已知缺陷是所谓的“0e”碰撞。这个问题特定于 PHP 的字符串比较机制,而不是 md5()
函数本身。当使用 ==
运算符比较两个字符串时,如果字符串以“0e”开头,后面跟着一系列数字,PHP 会将这些字符串解释为科学记数法表示的浮点数,并进行数值比较而不是字符串比较。
//2、MD5函数缺陷绕过 ==弱对比 ===强类型对比
if($_GET['name'] != $_GET['password']){
if(MD5($_GET['name']) == MD5($_GET['password'])){
echo $flag;
}
echo '?';
}
根据代码逻辑,先判断传入的name和password不相等,再判断name和password讲过md5加密后相等,才会输出flag,否则输出问号
测试用例会用到以下两个字符串
QNKCDZO以MD5加密:0e830400451993494058024219903391
240610708以MD5加密:0e462097431906509019562988736854
正常情况下,如name=test&password=123456,md5加密是不相等的
而当我们使用上面两个用例字符串,md5加密后php会判断相等
当你尝试对数组使用 md5()
函数时,PHP 会发出一个警告,告诉你 md5()
期望的是一个字符串,而你提供的是一个数组。然后,由于无法对数组进行哈希计算,它会返回 null
。在使用=比较时,传入两个数组比较,等于null=null返回true
//2、MD5函数缺陷绕过 ==弱对比 ===强类型对比
if($_GET['name'] != $_GET['password']){
if(MD5($_GET['name']) === MD5($_GET['password'])){
echo $flag;
}
echo '?';
}
上面解释过产生0e碰撞是因为php当作了科学计数比较,而使用 ===
进行字符串比较会同时比较值和类型,因此不会受到上述“0e”碰撞问题的影响。
这种情况可以使用传入数组的方式绕过,name[]=1和password[]=2显然满足两者不相等这个条件,而md5不对数组哈希,并报Warning返回null,所以null===null返回true
intval
intval( $var, $base )是 PHP 中的一个内置函数,用于获取变量的整数值,默认是十进制。这个函数尝试将给定的变量转换为整数类型。如果变量是字符串,那么它会解析字符串直到遇到一个非数字字符为止,然后返回该数字。如果字符串开头就是一个非数字字符,那么它会返回 0。
当使用 intval()
函数并设置基数(base)为 0 时,它会根据字符串的内容来尝试猜测其原始的数字基数,并进行相应的转换。这通常用于处理以特定前缀开头的数字字符串,如十六进制(以 “0x” 或 “0X” 开头)或八进制(以 “0” 开头),如果字符串不符合这些模式,它会被尝试解析为十进制数。
注意:如果字符串不是一个有效的八进制或十六进制数(即,如果它包含除了 0-7 之外的字符对于八进制,或者除了 0-9 和 a-f(不区分大小写)之外的字符对于十六进制),那么 intval()
将返回 0。
测试代码:
//3、intval缺陷绕过
$i='666';
$ii=$_GET['n'];
if(intval($ii)==$i){
echo $flag;
echo "<br>";
}
$i='666';
$ii=$_GET['n'];
if(intval($ii,0)==$i){
echo $flag;
}
使用666safs两个都能正常输出 ,都能正常截断后面的字符串,但改为十六进制0x29a则只有base等与0的才能正常识别输出
strpos
strpos()
是 PHP 中的一个字符串函数,用于查找一个子字符串在另一个字符串中首次出现的位置。
strpos(string $haystack, mixed $needle, int $offset = 0): int|false
参数说明:
$haystack
:必需。要搜索的字符串。$needle
:必需。要查找的字符串。如果该参数不是字符串,它会被转换为整数并视为字符的 ASCII 值。$offset
:可选。从$haystack
字符串中的哪个位置开始搜索。
返回值:
- 如果找到子字符串,则返回其第一次出现的位置的索引(基于0的索引)。
- 如果没有找到子字符串,则返回
false
。
测试代码:
//4、对于strpos()函数,我们可以利用换行进行绕过(%0a)
$i='666';
$ii=$_GET['h'];
if(strpos($ii,$i,0)){
echo $flag;
}
在这段代码中,如果h=666,并不会输出flag,因为strpos返回 666
在 $ii
中首次出现的位置的索引,而666
是字符串的开始,它将返回 0,0在php同样代表false
可以通过换行进行绕过:%0a666
%0a:表示换行
也可以在有必要的条件下使用 数组 返回null
//4、对于strpos()函数,我们可以利用换行进行绕过(%0a)
$i='666';
$ii=$_GET['h'];
if(strpos($ii,$i,0)===null){
echo $flag;
}
in_array
in_array()
是 PHP 中的一个函数,用于检查一个值是否存在于数组中。它的基本语法如下:
bool in_array ( mixed $search , array $array [, bool $strict = FALSE ] )
参数说明:
$search
:必需。要搜索的值。$array
:必需。要搜索的数组。$strict
:可选。如果设置为TRUE
,则还会检查$search
的类型是否和数组中的元素类型相同。默认为FALSE
。(True类似===,Flase类似==)
返回值:
- 如果在数组中找到值则返回
TRUE
,否则返回FALSE
。
测试代码:
//5、in_array第三个参数安全
$whitelist = [1,2,3];
$page=$_GET['i'];
if (in_array($page, $whitelist)) {
echo "yes";
}
preg_match
preg_match
是 PHP 中的一个函数,用于执行一个正则表达式匹配。如果匹配成功,它会返回 1;如果匹配失败或发生错误,它会返回 0;如果没有进行匹配,它会返回 false
。
preg_match
只能处理字符串,如果不按规定传一个字符串,传一个数组进入,就会使preg_match
失效,从而绕过该函数的检测。
测试代码:
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
从代码逻辑看,获取并判断num参数值是否为空,不为空则判断匹配num值中是否有0-9的字符,符合条件执行die输出nonono并杀死程序,否则执行下一个条件intval(num)取整操作,不为flase输出flag
正常输入数字,会杀死程序
当我们传一个数组,就能绕过正则的检测
str_replace
str_replace
是 PHP 中的一个函数,用于在字符串中查找并替换指定的值。它接受一个或多个搜索值(需要被替换的),以及对应的替换值,并在给定的主字符串中进行替换。
缺陷是无法迭代过滤,可以双写绕过
测试代码:
//7、str_replace无法迭代过滤
$sql=$_GET['s'];
$sql=str_replace('select','',$sql);
echo $sql;
这段代码会过滤掉select并替换为空
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
]
[外链图片转存中…(img-fAJkUJlm-1715546979188)]
[外链图片转存中…(img-RwWzCotj-1715546979188)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!