avatar

piwigo SQL injection

写在前面

最近在先知社区看到红日安全一个系列的php代码审计文章,最近也在学代码审计,文章很好理解又有例子。纸上得来终觉浅,绝知此事要躬行。所以我打算把这些demo都复现一遍,加深对代码审计的理解,红日安全在先知社区的文章

piwigo2.7.1 cms 审计

环境搭建mac下是mxsrvs集成的,类似于phpstudy。但其中有几个坑需要填一下。

1、如果启动nginx时出现了:Nginx 启动失败,nginx: [emerg] getpwnam(“501”) failed in /Applications/MxSrvs/bin/nginx/conf/nginx.conf:2,这个报错请求的话,解决方案如下。

切换到配置编辑,选择nginx。在第二行把501更改为www。

enter image description here
2、 如果安装目录进不去的话,可以查看php版本,默认是7版本的,这个cms不支持,切换到5版本就正常了。

我遇到的就这么两个,其它暂时没遇到,环境搭建好以后就可以分析逻辑了。

漏洞的成因在:include/functions_rate.inc.php,include/config_default.inc.php,以及根目录下的picture.php。

include/functions_rate.inc.php 关键代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function rate_picture($image_id, $rate)  
{
global $conf, $user;

if (!isset($rate)
or !$conf['rate']
or !in_array($rate, $conf['rate_items']))
{ return false;
}
----------------------------中间省略-----------------------
if ($user_anonymous)
{ $query.= ' AND anonymous_id = \''.$anonymous_id.'\'';
}
pwg_query($query);
$query = '
INSERT
INTO '.RATE_TABLE.'
(user_id,anonymous_id,element_id,rate,date) VALUES (' .$user['id'].','
.'\''.$anonymous_id.'\','
.$image_id.','
.$rate
.',NOW())

include/config_default.inc.php 关键代码

1
$conf['rate_items'] = array(0,1,2,3,4,5);

picture.php 关键代码

1
2
3
4
5
6
7
8
9
10
if (isset($_GET['action']))  
{
switch ($_GET['action'])
----------------------------中间省略-----------------------
case 'rate' :
{
include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
rate_picture($page['image_id'], $_POST['rate']);
redirect($url_self);
}

漏洞利用原理

因为$rate最终会被写入数据库,之前对$rate变量的过滤可以绕过,所以我们可以执行sql语句从而造成sql注入。原理很简单,接下来我们实际的去分析一下。

首先通过picture.php通过get传一个action参数,action参数的值为rate,让程序的逻辑进入case rate。这时,include/functions_rate.inc.php 中的rate_picture这个方法会被执行。在post传入rate值时,会对所传的值进行校验。这个if是万万不能进入的,进入的话就会返回false退出。第三个判断in_array()函数对$rate变量进行检测,判断$rate是否在 $conf[‘rate_items’] 中,看似对rate设置了一个白名单,但它没有把in_array()函数第三个属性设置为true,函数会对数据进行弱比较。

一些知识铺垫~

1
bool in_array ( mixed $needle , array $haystack [,  bool $strict = FALSE ]  )

needle —— 必须 —–规定要在数组搜索的值。
haystack —— 必须 —– 规定要搜索的数组
strict —— 可选 —— 如果该参数设置为 TRUE,则 in_array() 函数检查搜索的数据与数组的值的类型是否相同。

OK,来看一下怎么绕过。

enter image description here

这样的话,就可以绕过对rate的过滤从而注入sql语句。

实战测试

首先安装好网站后,随便发布一张图片,这时候可以用sqlmap来验证。

1
sqlmap -u "http://127.0.0.1/piwigo/picture.php?/1/category/1&action=rate" --data "rate=1" --dbs --batch

enter image description here

修复建议

官方在新版中,对$rate用正则进行了二次过滤。可以将in_array()函数的第三个参数设置为true,或者用intval() 函数将变量强转成数字。

Author: CarlStar
Link: http://yoursite.com/2018/08/01/piwigo/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment