HACK80 首页  立即注册  登录
现在注册
已注册用户请  登录
HACK80    技术文档

zabbix高危SQL注入漏洞分析

  •   djg222000 ·2018-2-9 19:14:36·999 次点击 ·阅读模式     

    马上注册,加入HACK80!与我们一起交流。

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    0x01 漏洞概述
    zabbix是一个开源的企业级性能监控解决方案。近日,zabbix的jsrpc的profileIdx2参数存在insert方式的SQL注入漏洞,攻击者无需授权登陆即可登陆zabbix管理系统,也可通过script等功能轻易直接获取zabbix服务器的操作系统权限。 但是无需登录注入这里有个前提,就是zabbix开启了guest权限。而在zabbix中,guest的默认密码为空。需要有这个条件的支持才可以进行无权限注入。
    0x02 影响程度
    • 攻击成本:低
    • 危害程度:高
    • 是否登陆:不需要
    • 影响版本:2.2.x,3.0.0-3.0.3
    0x03 漏洞测试
    在zabbix的地址后面添加:
    • 利用方式一
    如果出现下列代码则证明漏洞存在
    • 利用方式二
    如果出现下列代码则证明漏洞存在
    0x04 实战测试
    测试的一个Japan站
    可获得最高权限
    0x05 代码分析
    zabbix 2.2.14
    • 首先从poc中的jsrpc.php文件入手,找到profileIdx2参数
    case 'screen.get': $options = array( 'pageFile' => !empty($data['pageFile']) ? $data['pageFile'] : null, 'mode' => !empty($data['mode']) ? $data['mode'] : null, 'timestamp' => !empty($data['timestamp']) ? $data['timestamp'] : time(), 'resourcetype' => !empty($data['resourcetype']) ? $data['resourcetype'] : null, 'screenitemid' => !empty($data['screenitemid']) ? $data['screenitemid'] : null, 'groupid' => !empty($data['groupid']) ? $data['groupid'] : null, 'hostid' => !empty($data['hostid']) ? $data['hostid'] : null, 'period' => !empty($data['period']) ? $data['period'] : null, 'stime' => !empty($data['stime']) ? $data['stime'] : null, 'profileIdx' => !empty($data['profileIdx']) ? $data['profileIdx'] : null, 'profileIdx2' => !empty($data['profileIdx2']) ? $data['profileIdx2'] : null, 'updateProfile' => isset($data['updateProfile']) ? $data['updateProfile'] : null ); if ($options['resourcetype'] == SCREEN_RESOURCE_HISTORY) { $options['itemids'] = !empty($data['itemids']) ? $data['itemids'] : null; $options['action'] = !empty($data['action']) ? $data['action'] : null; $options['filter'] = !empty($data['filter']) ? $data['filter'] : null; $options['filter_task'] = !empty($data['filter_task']) ? $data['filter_task'] : null; $options['mark_color'] = !empty($data['mark_color']) ? $data['mark_color'] : null; } elseif ($options['resourcetype'] == SCREEN_RESOURCE_CHART) { $options['graphid'] = !empty($data['graphid']) ? $data['graphid'] : null; $options['profileIdx2'] = $options['graphid']; }$screenBase = CScreenBuilder::getScreen($options); if (!empty($screenBase)) { $screen = $screenBase->get(); }if (!empty($screen)) { if ($options['mode'] == SCREEN_MODE_JS) { $result = $screen; } else { if (is_object($screen)) { $result = $screen->toString(); } } } else { $result = ''; } break;省略部分代码require_once dirname(__FILE__).'/include/page_footer.php';
    在看这段代码的时候各种跑偏,一度追着
    $screenBase = CScreenBuilder::getScreen($options); if (!empty($screenBase)) { $screen = $screenBase->get(); }
    这几句代码死磕,看到zabbix-2.2.14/frontends/php/include/classes/screens/CScreenBuilder.php,在public static function getScreen(array $options = array())函数中没有找到可以造成漏洞的交互点,太菜了!!!
    然后去请教表哥,表哥提示问题出现在flush中
    根据表哥的提示,在page_footer.php中发现CProfile类的flush方法
    // last pageif (!defined('ZBX_PAGE_NO_MENU') && $page['file'] != 'profile.php') { CProfile::update('web.paging.lastpage', $page['file'], PROFILE_TYPE_STR);}CProfile::flush();// end transactions if they have not been closed alreadyif (isset($DB) && isset($DB['TRANSACTIONS']) && $DB['TRANSACTIONS'] != 0) { error(_('Transaction has not been closed. Aborting...')); DBend(false);}
    在profiles.inc.php中找到了flush函数
    public static function flush() { // if not initialised, no changes were made if (is_null(self::$profiles)) { return true; }if (self::$userDetails['userid'] <= 0) { return null; }if (!empty(self::$insert) || !empty(self::$update)) { DBstart(); foreach (self::$insert as $idx => $profile) { foreach ($profile as $idx2 => $data) { self::insertDB($idx, $data['value'], $data['type'], $idx2); } }ksort(self::$update); foreach (self::$update as $idx => $profile) { ksort($profile); foreach ($profile as $idx2 => $data) { self::updateDB($idx, $data['value'], $data['type'], $idx2); } } DBend(); } }
    参数传入下面的insertDB函数,从而导致了注入的产生
    private static function insertDB($idx, $value, $type, $idx2) { $value_type = self::getFieldByType($type);$values = array( 'profileid' => get_dbid('profiles', 'profileid'), 'userid' => self::$userDetails['userid'], 'idx' => zbx_dbstr($idx), $value_type => zbx_dbstr($value), 'type' => $type, 'idx2' => zbx_dbstr($idx2) ); return DBexecute('INSERT INTO profiles ('.implode(', ', array_keys($values)).') VALUES ('.implode(', ', $values).')'); }0x06 漏洞修复
    • 版本升级
    • 打补丁
    • 关闭guest
    0x07 后记
    这里还有好多东西没有搞懂,毕竟太菜了
    注:部分漏洞信息收集自网络

    999 次点击  
    收藏  转播  分享
    添加一条新回复
    您需要登录后才可以回帖 登录 | 立即注册

    本节点积分规则
    QQ
    小黑屋   ·   手机版   ·   376 人在线 最高记录 5500   ·   TOP
    我们很年轻,但我们有信念、有梦想!

      我们坚信只有今天付出了,才有机会看到明天的太阳!现在!加入我们,给你一个气氛优秀的技术圈子。  
    GMT+8, 2018-8-21 14:05, Processed in 0.047851 second(s), 18 queries .