代码审计 | strcmp()漏洞

php strcmp bypass漏洞

在PHP 5.3版本以上的strcmp()有一个bypass漏洞,在说这个漏洞之前我们先来看一下strcmp()这个函数。

int strcmp ( string $str1 , string $str2 )


如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。(注意该比较区分大小写。)

测试代码如下:

<?php

$password = $_GET['pass'];

if (strcmp('websec',$password)){

    echo "No!";
}

else{

    echo "Success!";
}

?>

可知,传入的期望类型是字符串类型的数据,但是如果我们传入非字符串类型的数据的时候,这个函数将会有怎么样的行为呢?实际上,当这个函数接受到了不符合的类型,这个函数将发生错误,但是在5.3之前的php中,显示了报错的警告信息后,将return 0 !!!! 也就是虽然报了错,但却判定其相等了。这对于使用这个函数来做选择语句中的判断的代码来说简直是一个致命的漏洞,当然,php官方在后面的版本中修复了这个漏洞,使得报错的时候函数不返回任何值。但是我们仍然可以使用这个漏洞对使用老版本php的网站进行渗透测试。

strcmp()在比较字符串和数组的时候直接返回0,这样通过把目标变量设置成数组就可以绕过该函数的限制

bugku - strcmp比较字符串

http://120.24.86.145:9009/6.php

<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。
//比较两个字符串(区分大小写)
die('Flag: '.$flag);
else
print 'No';
}
?>

解题思路:

strcmp漏洞
int strcmp ( string str1,stringstr2 )
str1是第一个字符串,str2是第二个字符串。如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。
但是如果我们传入非字符串类型的数据的时候,这个函数将发生错误,在5.3之前的php中,显示了报错的警告信息后,将return 0 ! 也就是虽然报了错,但却判定其相等了。
因此,解这道题,就只要传入一个非字符串类型的变量即可,一般情况下,我们我们传数组,所以payload为:?a[]=123

构造链接:http://120.24.86.145:9009/6.php?a[]   

                   http://120.24.86.145:9009/6.php?a[]=1    诸如此类,即可

猜你喜欢

转载自blog.csdn.net/qq_42357070/article/details/81982968