第一部分: 特征函数
接触到几个常用的函数:
\=\=
\=\=\=
md5
intval
strpos
in_array
preg_match
str_replace
php用这些函数实现过滤一些代码,漏洞可能有一些特性,利用这些特征代码进行对比;账号密码对比;强制检测数据类型等都会用到这些函数,接下来具体讲解一下各个函数的使用:
如果输入的值是name[]=1&password[]=2的结果就是获取到的值为null,在图中上面的部分,判断的值也就相等了,从而达到绕过的目的。这种情况在ctf中比较常见。
语法
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。
strpos()函数:查找字符串在另一字符串中第一次出现的位置(区分大小写)。
参考:https://www.runoob.com/php/func-string-strpos.html
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也出现过。
并且这里最后获取的值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,所以可以输出最后正确的结果。
<!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中先将…/的结果替换完之后,再将结果中的./替换成空,这是我从实验中得来的,所以这种替换是按照数组的顺序进行替换的。