2015年9月7日阿里云盾态势感知系统捕获到LuManager系统的0day一枚,经证实,该漏洞一旦被黑客利用可直接以最高权限登陆后台,上传webshell, 控制系统数据库、操作虚拟主机,后果不堪设想。
作者:云盾攻防对抗团队 - 千霄
LuManager是一种基于FreeBSD、Zijidelu、Debian、Centos、Ubuntu等Linux/Unix系统的网站服务器管理软件,目前有大量国内用户使用。云盾攻防对抗团队捕获0day后第一时间通知厂商,厂商迅速响应,于8日上午发布安全更新并致谢阿里云盾。在此次事件过程中,正是基于云盾态势感知系统灵敏的漏洞捕获能力、阿里云与厂商的快速沟通响应以及厂商负责任的态度,得以保证了阿里云用户不受该漏洞影响,避免了不必要的损失。云盾作为互联网安全的基础设施,对于基础软件的安全我们会进行深入研究和分析,保障云平台的安全稳定运行。
0x00 漏洞捕获
2015年9月6日,通过阿里云云盾态势感知系统,在异常流量中我们发现有黑客利用LuManager系统获取webshell,捕获到攻击者的一枚攻击payload:
0x01 漏洞复现
在漏洞库中,我们并未发现该系统存在安全漏洞,推测该漏洞为一枚0day。我们第一时间对该payload进行了复现:向LuManager(版本2.0.99),index.php?m=Public&a=login 发送post数据包,提交后直接绕过登陆验证进入后台,并执行了payload 中的SQL语句:
0x02 漏洞分析
官方下载了最新版本的Lumanager(2.0.99),登陆验证的代码位于/Lib/Action/PublicAction.php,LuManager核心代码使用了Zend加密和代码混淆,控制器目录代码解密后,函数名、类名无法还原,代码的可读性较差,从触发位置寻找漏洞成因比较困难。我们更换思路来定位漏洞位置,Lumanager使用了Thinkphp框架开发,框架的代码并未加密,开启ThinkPHP框架trace模式进行调试,抓取到正常登陆和发送payload时候的SQL语句如下:
通过执行的SQL结果分析,payload触发时,SQL语句中,User.user字段的值并没有单引号包围,同时这个变量可控,导致SQL注入漏洞。确定是位于where条件触发的SQL注入,继续跟踪定位代码,/Sys/Lib/Think/Db/Db.class.php 400行,parseWhere()函数内代码:
if ( “exp” == strtolower( $val[$i][0] ) )
{
$whereStr .= “(“.$key.” “.$data.”) “.$rule.” “;
}
从上述代码可以看到:当传入where条件是数组,且数组第一个元素值为“exp”,会直接拼接$val[$i][1]到SQL语句的where条件中,由于没有单引号,因此不受全局addsalash转义影响。parseWhere()函数在上层被调用时,如果没有检查传入变量的类型,直接将可控参数传入,攻击者利用这个特性就可以构造恶意SQL。
LuManager在登陆验证代码中,将$_POST[‘user’]参数传递后带入了parseWhere()函数,构造该参数为数组类型,可触发执行恶意SQL。由于该漏洞是登陆位置触发的SQL注入,我们可以简化payload,构造恒真条件,使用”万能密码”登陆后台:
POST /index.php?m=Public&a=login
user[0]=exp&user[1]==1)) or 1 --
提交后可直接以管理员身份进入后台。
LuManager登陆位置有验证码机制,发送payload时候需要先识别验证码,可以使用OCR库自动识别验证码,进行自动化检测,有兴趣可以自己实现:
从漏洞成因上说,该漏洞实质是thinkphp框架自身的一处特性(Or 漏洞)引发的,@phith0n已经提交过thinkphp框架存在的安全问题(http://www.wooyun.org/bugs/wooyun-2010-086737),但是仍有很多基于thinkphp框架开发的系统并没有意识到这个严重问题,存在漏洞的也不仅仅LuManager,建议thinkphp开发者检查自身产品是否存在同样问题。
0x03 漏洞影响
该漏洞影响LuManager 2.1.1以下的所有版本,攻击者可直接以最高权限登陆后台,上传webshell, 控制系统数据库、操作虚拟主机。测试过程中,我们发现后台可以新增计划任务,计划任务会以root权限定时执行,攻击者进入后台后可获取系统root权限。
0x04 漏洞修复
该漏洞我们已经第一时间通知厂商,9月8日上午厂商发布升级,并对阿里云云盾团队表示感谢。目前最新版本为2.1.2,建议用户尽快升级到最新版本2.1.2。
使用在线升级:
使用LuManager2.0.45以上版本的用户,可以登陆LuManager在线升级,方法如下:登陆LuManager,在LuManager的首页点击“检查更新”,如果没有启动保护密码,请输入后再重试
手动升级:
- 下载LuManager_last.tar.gz安装包:wget http://down.zijidelu.org/LuManager_last.tar.gz
- 备份之前的LuManager:mv /usr/local/LuManager /usr/local/LuManager.bak
- 解压LuManager_last.tar.gz:tar -zxvf LuManager_last.tar.gz
- 安装新的LuManager:mv LuManager /usr/local/
- 执行lu-repair命令便升级完成