PHP中一些特征函数导致的漏洞总结

第一部分: 特征函数

接触到几个常用的函数:
\=\=
\=\=\=
md5
intval
strpos
in_array
preg_match
str_replace

php用这些函数实现过滤一些代码,漏洞可能有一些特性,利用这些特征代码进行对比;账号密码对比;强制检测数据类型等都会用到这些函数,接下来具体讲解一下各个函数的使用:

  1. = 赋值
  2. == 弱类型对比,但是不会对比类型,这种存在缺陷绕过,举个例子,判断一个值是否==1,这种情况用户输入的+1,1.0,1a都会被当成正确的情况进行处理,这点在数据库中也是,当输入的值是字符串类型的时候,1a和1对比时,1a只取1和1对比,和后面的a无关,利用这点,如果1a=1报错,说明是数字型,如果1a=1不报错,说明时字符型,在这里时为了说明如果不进行强类型的对比1后面可以接入字符串。
    让我们来拓展一下,如果只进行弱类型对比,假设密码用md5进行加密了存放在数据库中,存放的密码和用户输入的密码的md5加密值中间用/=/=判断而不是用/=/=/=判断的后果,就是可能产生hash碰撞,如下图所示。:
    这样就达到了绕过的目的。
  3. . === 对比,会对比类型
    此时可以使用数组进行绕过,对于数组name[]来说$_GET['name']获取到的值就是null,让我们来看个例子:

如果输入的值是name[]=1&password[]=2的结果就是获取到的值为null,在图中上面的部分,判断的值也就相等了,从而达到绕过的目的。这种情况在ctf中比较常见。

  1. intval()函数:就是把其他类型的东西变成10进制int类型的数据。具体用法参考:https://www.runoob.com/php/php-intval-function.html
    这个东西,可以用来过滤sql注入,比如id=1 and 1=1 ,使用这个函数,只能获取到id = 1 ,同时根据文档里的这段话: 语法

    int intval ( mixed $var [, int $base = 10 ] )

    参数说明:

    $var:要转换成 integer 的数量值。

    $base:转化所使用的进制。

    如果 base 是 0,通过检测 var 的格式来决定使用的进制:

    如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,

    如果字符串以 "0" 开始,使用 8 进制(octal);否则,

    将使用 10 进制 (decimal)。

666的十六进制的值是0x29a,此时如果用户输入的值是0x29a,这两个值仍然是相等的关系,也会输出flag。

  1. strpos()函数:查找字符串在另一字符串中第一次出现的位置(区分大小写)。

    参考:https://www.runoob.com/php/func-string-strpos.html

  2. in_array() 函数:

    参考:https://www.runoob.com/php/func-array-in-array.html

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

参数 描述

needle 必需。规定要在数组搜索的值。

haystack 必需。规定要搜索的数组。

strict 可选。如果该参数设置为 TRUE,则 in_array() 函数检查搜索的数据与数组的值的类型是否相同。

如果strict的位置是true可以检查类型相当于/=/=/=,如果是false的话,就相当于/=/=,这种情况就相当于存在绕过,例如1e在[1,2,3]中也算是出现过,1d/+1/1.0也出现过。

  1. preg_match()函数:用于执行一个正则表达式匹配
    参考:https://www.runoob.com/php/php-preg_match.html
    这里可以使用数组绕过:

并且这里最后获取的值num的值是1,这是chatgpt给我的解释:

$_GET['num'] 是一个数组,而数组的首个元素是1,可以成功转换为数字。
因此,intval($num) 的结果是1,条件 if(intval($num)) 为真,导致 echo $flag; 被执行。

后面我去手动输出验证了一下,该段代码中:

<?php
$flag = 'success ----';
if(isset($_GET['num'])){
	$num = $_GET['num'];
if(preg_match("/[0-9]/",$num)){
die("no no no");
}
if(intval($num)){
echo "===================";
echo intval($num);
echo $flag;
}
}
?>

$_GET['num']获取到的值是Array,而intval( $_GET['num'])的值是1,所以可以输出最后正确的结果。

  1. str_replace()函数:以其他字符替换字符串中的一些字符(区分大小写)。
    //参考:https://www.w3school.com.cn/php/func_string_str_replace.asp

    <!DOCTYPE html> <html> <body> <?php echo str_replace("world","Shanghai","Hello world!"); ?> </body> </html>

    //输出结果:Hello Shanghai!

常常用于过滤sql

这种过滤无法迭代执行,例如输入sselectelect,最终还是会出现select的字样。

正则表达式中/i 是否区分大小写;/m 是否接受换行,可以使用%0a %20进行绕过。

%0a:代表换行符(Line Feed),ASCII码值为10。在URL编码中,换行符被表示为 %0a。

%20:代表空格字符。在URL编码中,空格通常被表示为 %20。

这类ctf题不仅可以参加比赛,而且还可以学习实际代码,将来实战很有帮助,不要单纯做ctf狗。

循环过滤一般用的就是正则表达式,顺序过滤用的是str_replace(),但是这个有比较特殊的用法,如下列代码:

<?php
$s = "..//..../";
$search = array('../','./');
$dir = str_replace($search,'',$s);
echo $dir;

?>

首先会把$s中先将.../的结果替换完之后,再将结果中的./替换成空,这是我从实验中得来的,所以这种替换是按照数组的顺序进行替换的。

相关推荐
余子桃2 分钟前
Python获取QQ音乐歌单歌曲
开发语言·python
q567315239 分钟前
Python/Django 服务器升级脚本
服务器·开发语言·python·游戏·django
Michael Lee.25 分钟前
Python学习篇:Python基础知识(三)
开发语言·python·学习·pycharm
martian66527 分钟前
学懂C#编程:属性(Property)的概念定义及使用详解
java·开发语言·c#·属性·property
逸群不凡36 分钟前
C++11|lambda语法与使用
开发语言·c++
来世做春风嘛38 分钟前
第二十一章 网络编程
服务器·网络·php
DieSnowK44 分钟前
[C++][CMake][CMake基础]详细讲解
开发语言·c++·makefile·make·cmake·新手向·详细讲解
时间瑾1 小时前
线程池实践篇
java·开发语言
JY9401 小时前
使用Qt制作一个简单的界面
开发语言·qt
萝卜地里的兔子1 小时前
面向对象编程思想新解 第二章 编程的本质
java·开发语言