Web安全企业Sucuri周二在博客(Security Advisory – WP-Slimstat 3.9.5 and lower)中表示,他们在最新版本的Wordpress分析插件WP-Slimstat中发现了一个sql注入漏洞,利用该漏洞,攻击者可以进行sql盲注,从而获取数据库的敏感信息。互联网上超过100万网站受到影响。
WP SlimStat 是一个功能非常强大的WordPress实时统计分析插件,通过该插件可以查看网站的访问情况。WordPress上的记录显示,这款插件下载次数已超过130万次。
所有3.9.6以前版本的WP-Slimstat都包含一个简单可猜测的密钥,这个密钥被WP-Slimstat用来标记网站的访问者。只要该密钥被攻破,攻击者可以通过SQL注入(盲注)攻击目标网站以获取敏感的数据库信息,包括用户名、密码(hash)以及至关重要的wordpress安全密钥。
WP-Slimstat密钥仅仅是该插件安装时的时间戳(MD5 hash版本号),而诸如Internet Archive这种“网站时光机”可以帮助攻击者更轻松地猜出插件安装的时间。为此攻击者需要付出3千万次的猜解测试,而对于流行的CPU来说,这种量级的暴力破解只需要10分钟。
安全专家建议所有使用这款流行插件的站长尽快进行升级。
小编经过分析发现这个漏洞并不是一个简单的sql注入,还是比较有意思的,下面带大家一起来看下。
首先当你开启了WP-Slimstat插件之后,每当你访问一个网页,系统都会通过ajax向/wp-admin/admin-ajax.php发送post请求,记录你当前访问网页的情况。
发送的数据如下图所示:
其中data是一段base64编码过的数据,经过解码之后是
ci=YToyOntzOjEyOiJjb250ZW50X3R5cGUiO3M6NDoiaG9tZSI7czo4OiJjYXRlZ29yeSI7czowOiIiO30=.ae93e0c4e2f76695c4dd540456ab7945 &ref=&res=aHR0cDovLzEwLjE4LjE4MC4zNy93b3JkcHJlc3Mv &sw=1920&sh=1080&cd=24&aa=1&sl=2004&pp=7267&pl=flash|
我们直接到插件的文件中去看他是如何处理这段数据的。
在wp-content\plugins\wp-slimstatwp-slimstat.php文件的第86行
我们可以看到,data经过base64解码之后传递给了$data_string。随后通过parse_str方法将其赋给了$data_js。
随后下面的部分他做了一个很有意思的事情
在102行我们可以看到,他把$data_js[ci]分成了两部分,“.”后面的赋给了$nonce,前面的覆盖了原来的$data_js[ci]。
在105行,他将$data_js[ci]的后面添加了一个秘钥,md5加密后和$nonce做对比,如果不相等将直接退出程序。也就是说,他对数据包是否被篡改进行了校验,如果被篡改将直接退出程序。
我们接着往下看,如果数据没有被篡改,在第374行:
他将$data_js[ci] base64解码再反序列化之后赋给了$content_info
之后在417行
$content_info进入了maybe_insert_row函数,跟进该函数,1036行
可以看到数据被带入到了查询中,在第1044行我们看到,程序还是严谨的使用了wordpress自带的数据库查询函数对获取的数据进行了预处理,但是百密终有一疏,$a_key这个变量没有在预处理的行列中,而这个变量也是我们可控的,这也是这个漏洞的罪魁祸首。
那么问题来了:我们该如何绕过校验呢,让程序认为数据没有被篡改过呢?
从上面我们知道只有$nonce 和 md5(self::$data_js['ci'].self::$options['secret'])相等时才可以继续执行程序,现在我们可以控制的是$nonce和$data_js['ci'],只要再知道$options['secret']即可。我们看下$options['secret']是什么
在1095行我们可以看到他是简单的系统当前时间被md5加密过后的值,time()函数返回的是Unix时间戳,是一个10位的纯数字,而且根据推测网站的建立时间,我们可以大大缩小猜测的范围,根据测试,大约3000万次即可猜出系统的secret秘钥,一旦我们猜出了秘钥,我们便可以篡改数据包,进行注入。
小编写了个程序,几秒钟就猜出了秘钥。
拥有了秘钥之后我们开始注入,由于注入出在数组的键值上,所以我们在category后面添加一个单引号。构造的payload如下:
a:2:{s:12:"content_type";s:4:"home";s:9:"category'";s:0:"";}
把他base64编码然后加上秘钥md5加密,获得了13688da6b1bad69d677948ebed0fa19a的加密值,把他加入请求,对请求base64再次编码后得到了我们最终的payload
Y2k9WVRveU9udHpPakV5T2lKamIyNTBaVzUwWDNSNWNHVWlPM002TkRvaWFHOXRaU0k3Y3pvNU9pSmpZWFJsWjI5eWVTY2lPM002TURvaUlqdDkuMTM2ODhkYTZiMWJhZDY5ZDY3Nzk0OGViZWQwZmExOWEmcmVmPSZyZXM9YUhSMGNEb3ZMekV3TGpFNExqRTRNQzR6Tnk5M2IzSmtjSEpsYzNNdiZzdz0xOTIwJnNoPTEwODAmY2Q9MjQmYWE9MSZzbD0yMDA0JnBwPTcyNjcmcGw9Zmxhc2h8
用burp发包
从Mysql日志中可以看到单引号被带入了查询
由于没有输出点,无法union,只能盲注了。
附猜解秘钥程序
<?php $ci = "YToyOntzOjEyOiJjb250ZW50X3R5cGUiO3M6NDoiaG9tZSI7czo4OiJjYXRlZ29yeSI7czowOiIiO30="; $nonce="ae93e0c4e2f76695c4dd540456ab7945"; for($secret=time();$secret>1136044800;$secret--){ if($nonce==md5($ci.md5($secret))){ echo "find the secret is ".md5($secret); break; } } ?>
【原文:360安全播报 流行Wordpress分析插件WP-Slimstat弱密钥及sql注入漏洞分析 SP小编整理发布】