0x01 定义
(PHP 4, PHP 5, PHP 7)
in_array — 检查数组中是否存在某个值
说明
in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) : bool
其中
neddle 是带所搜的值(如果是字符串是区分大小写)
haystack 待搜索的数组
strick 如果值为true,则in_array()函数还会检查needle的类型是否和haystack中的相同
今天在调试代码的时候发现一个关于in_array的错误使用方式导致的一个bug。在PHP中,数组是一个十分强大的数据结构,官方提供了特别多的数组操作函数,in_array()是比较常用的一个,我们经常会用它来判断数组中是否包含某个元素。但我们可能会在使用时忽略掉该函数的第三个参数而导致一类bug的产生。
0x02 实例分析
分析是选用的piwaigo2.7.1版本是一个免费的开源相册,该版本由于SQL语句直接拼接 $rate 变量,而 $rate 变量也仅是用 in_array() 函数简单处理,并未使用第三个参数进行严格匹配,最终导致sql注入漏洞发生。下面我们来看看具体的漏洞位置。漏洞的入口文件在 includefunctions_rate.inc.php 中,具体代码如下:
当我们$_GET['action']为true时候,就会调用funcion_rate.inc.php,还调用rate_picture方法,
而漏洞就在rate_picture方法中
在最下面我们可以看到是直接拼接了我们的rate变量,而在上面是用in_array()函数对$rate变量进行检测,判断$rete变量是否在$conf['rate_items']数组中,而我们的$conf['rate_items']数组内容可以再includeconfig_default.inc.php中看到,为$conf['rate_items'] = array(0,1,2,3,4,5)
而且in_array()函数没将第三个参数设置为true,所以会进行弱比较,我们是可以绕过的。
如果我们的$rate的值是1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));#,那么sql语句就是
INSERT INTO piwigo_rate (user_id,anonymous_id,element_id,rate,date) VALUES (2,'192.168.1.139',1,1 and if(ascii(substr((select database()),1,1))=112,1,sleep(3)));#,NOW()) ;
可以使用sqlmap来进行验证
sqlmap -u "http://192.168.1.139/PHPcode/piwigo/picture.php?/1/category/1&action=rate" --data "rate=1" --dbs --batch
0x03 练手
这边写个index.php
访问,发现存在时间盲注漏洞,而常见的sub hex都被过滤了 别担心我们还有mid 可以看到成功的延时了5秒,数据库第一位就是100就是d
http://192.168.1.101/exchange/in_array/index.php?id=2%20and%20if(ascii(mid((select%20database()),1,1))=100,sleep(5),1)