CmsEasy暴力注入
- 发布时间:2015-12-21
- 公开时间:2016-03-03
- 漏洞类型:sql注射
- 危害等级:高
- 漏洞编号:WooYun-2015-160093
- 测试版本:CmsEasy_5.6_UTF-8_20151009
简要描述
加解密函数缺陷第四发,注入 任意用户登录 有点类似http://wooyun.org/bugs/wooyun-2014-062391 使用不安全的“随机数”实例2详细说明
CmsEasy中使用了一个cookie_password值 用来给cookie和一些其他的值做加密 先来看这个值的来源 lib/admin/install_act.php 行35config::modify(array('cookie_password' => md5(rand() . time())));
可以看到 这个值是由一个随机数rand()拼接安装时的时间戳time()来生成的
同样 看起来很随机 其实很脆弱
- 两个函数返回的都是数字
- 两个函数返回值都可以预测(?)
int rand ( void ) int rand ( int min , intmax ) 如果没有提供可选参数 min 和 max,rand() 返回 0 到 getrandmax() 之间的伪随机整数。例如想要 5 到 15(包括 5 和 15)之间的随机数,用 rand(5, 15)。 Note: 在某些平台下(例如 Windows)getrandmax() 只有 32767。如果需要的范围大于 32767,那么指定 min 和 max 参数就可以生成更大的数了,或者考虑用 mt_rand() 来替代之。也就是说 在windows下,rand()返回的最长位数就只有5位而已 再来看time()
这个函数返回一个10位的数字 表示从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数看起来很长但实际上基于现在的GPU能力,一个10位的纯数字MD5的破解基本上是以秒为单位的 而且更悲剧的是最前面的3位基本上可以确定 比如今年2015年 最前面的3位就一定是142 143 144 145 所以在windows下 rand().time() 就是11~15个数字(1~5位的rand() 10位的time()) 这点范围的计算量对gpu来说就是分分钟的事 好了下面来看看这个cookie_password在哪里会用到 lib/tool/front_class.php 行650
static function cookie_encode($_password)
{
return md5($_password . config::get('cookie_password'));
}
lib/default/user_act.php 行200
function login_action()
{
//省略部分登录过程
233行:
cookie::set('login_username', $user['username']);
cookie::set('login_password', front::cookie_encode($user['password']));
}
可以看到 登录成功后,设置cookie的时候用了cookie_encode函数 把密码加密后返回
实际上cookie中的login_password如下
login_password = md5($password,config::get('cookie_password'));
$password 是明文密码的一次md5()值
如果这里把我们的明文密码看成是salt的话 其实加密的函数就是
md5(md5($salt).md5(cookie_password));
这种加密格式在oclHashCat里面的编号是 2811
知道了流程 就可以构造数据来解密了
首先注册一个账号 密码比如说是wooyun 然后登录 查看cookie的 cookie_password 值记下来
b57a6043a1c3c623a8d72b479f1367c7:wooyun:24481449722857rand() =2448 time()= 1449722857 图上可以看到 从17:53:32开始 到17:54:54跑出结果 总共82秒 尝试了96531382272次 拿到这个之后 我们就能随意伪造cookie的值了 这次主要是说key的脆弱性,所以注入部分就简单说了 lib/admin/admin_act.php 行76
function remotelogin_action() {
cookie::del('passinfo');
$this->view->loginfalse=cookie::get('loginfalse'.md5($_SERVER['REQUEST_URI']));
if (front::$args) { //这个值来GET self::$args = $_GET['args'];
$user=new user();
$args = xxtea_decrypt(base64_decode(front::$args), config::get('cookie_password'));
$user=$user->getrow(unserialize($args)); //解密并unserialize之后进入getrow
if (is_array($user)) {
if ($user['groupid'] == '888')
front::$isadmin=true;
cookie::set('login_username',$user['username']);
cookie::set('login_password',front::cookie_encode($user['password']));
$_GET['args']解密之后进了sql查询 导致注入 因为参数经过加密 所以可以无视360waf
再加上此处注入点比较不常见
select * from cmseasy_user where [inject]
内置的sql检查也可以无视了 具体的注入方法exp看一眼就懂
写了个exp 效果如图
漏洞证明
注册了一个官方demo站的账号 然后跑出了加密keya1b10aeff60a21f67d5fefc7e5b33e20:111111:77891440761707
所以demo站的cookie_password 就是
md5('77891440761707')= e11e37974049bbe1d21c11c67a30fd2a
修复方案
加密key还是复杂点吧关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 一图读懂新成立的信息支援部队 4983012
- 2 男子给27万彩礼订婚后准新娘自尽 4906130
- 3 多名中国移动用户未欠费被迫停机 4802965
- 4 乡村产业发展态势良好 4737896
- 5 伊朗外长:“袭击”伊朗武器像玩具 4695469
- 6 新人结婚当天邻居播放哀乐 4588547
- 7 乘客遗落电脑致飞机延误?国航回应 4455777
- 8 厦门一年轻妈妈买下2700多元海鲜 4322684
- 9 淄博赵大爷辟谣收徒弟要收钱 4280938
- 10 加沙妇女抱侄女尸体照片获摄影大奖 4124590