代码审计数组返回NULL绕过
http://123.206.87.240:9009/19.php
<?php
$flag = "flag";
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)//限定密码格式
//“[A-Za-z0-9]"
//方括号表示字符集,[A-Za-z0-9]匹配大小写字母和数字其中一个字符
//"^[A-Za-z0-9]$"
//^表示字符串开始,$表示字符串结束 ,这个匹配只有一个大小写字母和数字字符的字符串
//
//“^[A-Za-z0-9]+$"
//+号表示重复1到多次,匹配由多个数字大小字母组成的字符串
//.ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。
//搜索字母的字符是大小写敏感的。int ereg(string pattern, string originalstring, [array regs]);
//例,$email_id = "admin@tutorialspoint.com"; $retval = ereg("(\.)(com$)", $email_id); ereg()限制password的格式,只能是数字或者字母。
//但ereg()函数存在NULL截断漏洞,可以使用%00绕过验证。 这里ereg有两个漏洞:
// ①%00截断及遇到%00则默认为字符串的结束
// ②当ntf为数组时它的返回值不是FALSE
//另外提示,科学计数法的表示是1e9=1000000000e一定是小写
echo 'You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
//strpos() 函数查找字符串在另一字符串中第一次出现的位置。
//注释:strpos() 函数对大小写敏感。
//注释:该函数是二进制安全的。
//关键在于strpos函数,这个函数如果传入数组
//
//会返回null,与false不相等得以绕过
die('Flag: ' . $flag);
else
echo 'Invalid password';
}
?>
//所以最后构建出http://123.206.87.240:9009/19.php?password[]=2%00
//<!--/Flag: flag{ctf-bugku-ad-2131212}-->
error_reporting(0);
show_source(__FILE__);
$flag='you_get_me!';
if (isset (
$_GET['password'])) {
if (
ereg("^[a-zA-Z0-9]+$",$_GET['password']) ===FALSE)
echo 'You password must be alphanumeric';
else if (
strpos($_GET['password'],'--') !==FALSE)
die($flag);
else
echo 'Invalid password';}
?>
Solution
1、ereg()用途
ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。
可选的输入参数规则包含一个数组的所有匹配表达式,他们被正则表达式的括号分组。
2、题中ereg()正则限制了password的形式,只能是一个或者多个数字、大小写字母
3、strpos() 函数查找字符串在另一字符串中第一次出现的位置(区分大小写)
4、ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配
5、ereg()只能处理字符串的,遇到数组做参数返回NULL,判断用的是 === ,要求类型也相同,而NULL跟FALSE类型是不同的,strpos()的参数同样不能为数组,否则返回NULL,而判断用的是 !== ,所以这里的条件成立,也能得到flag


作者:queena_
链接:https://www.jianshu.com/p/7b732d4b8eac
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。