← voltar
CVE-2022-46169criticalsob ataqueCWE-74

Unauthenticated Command Injection

100Vexday Risk Score

Corrija agora. Ela está sob exploração confirmada pelo CISA e tem exploit funcional público.

ssvc Actcvss 9.8epss 100%
da publicação à arma2 dias
Publicada no NVD5 de dez.
1ª PoC+2d
metasploit5 de dez.
CISA KEV+73d
probabilidade de exploração
100%top 1% das CVEs
exploração observada
simCISA + VulnCheck
73 exploit(s) público(s)
Ação exigida pela CISAprazo federal: 2023-03-09

Apply updates per vendor instructions.

Resumo

Falha de authentication bypass encadeada com command injection no remote_agent.php do Cacti, atingindo instâncias até a versão 1.2.22. Qualquer atacante não autenticado com acesso de rede ao endpoint consegue executar comandos arbitrários no servidor, desde que exista pelo menos um poller_item com ação POLLER_ACTION_SCRIPT_PHP — condição comum porque templates padrão do Cacti (como Device - Uptime e Device - Polling Time) criam esse tipo de item. É por isso que o CVSS 9.8 não é exagero: a barreira de autenticação é falsa e o pré-requisito de configuração é praticamente universal em instalações reais.

Detalhamento técnico

O arquivo remote_agent.php normalmente serve apenas os pollers remotos do Cacti, mas não exige autenticação — em vez disso, chama remote_client_authorized() para decidir se o requisitante é um poller legítimo. Essa função pega o IP do cliente via get_client_addr() (lib/functions.php), resolve esse IP para hostname via gethostbyaddr() e compara contra os hostnames cadastrados na tabela poller. Se bater, o acesso é liberado.

O problema (CWE-290, authentication bypass by spoofing) está em get_client_addr(): a função itera por uma lista de cabeçalhos HTTP — X-Forwarded-For, X-Client-IP, X-Real-IP, CF-Connecting-IP, True-Client-IP, entre outros — e usa o primeiro valor válido como IP do cliente, sem verificar se a requisição de fato passou por um proxy confiável. Como esses cabeçalhos (HTTP_*) são inteiramente controlados pelo atacante via requisição HTTP, basta enviar um cabeçalho tipo Forwarded-For com o próprio IP do servidor Cacti. gethostbyaddr() resolve esse IP para o hostname do servidor, e como existe uma entrada padrão na tabela poller com esse hostname (o poller local), o cheque passa e remote_client_authorized() retorna true.

Com o bypass feito, o atacante aciona action=polldata, que chama poll_for_data(). Essa função lê os parâmetros host_id, local_data_id e poller_id da requisição e busca em poller_item a linha correspondente. Se a ação cadastrada for POLLER_ACTION_SCRIPT_PHP (execução de script PHP via script_server.php), o código monta uma string de comando e a passa para proc_open(), concatenando o valor de poller_id sem sanitização — esse parâmetro é obtido via get_nfilter_request_var(), que não filtra caracteres especiais de shell. Isso é injeção de comando clássica (CWE-78): qualquer metacaractere de shell no valor de poller_id é interpretado pelo interpretador de comandos do sistema.

O atacante controla, portanto, dois pontos: o cabeçalho HTTP usado para falsificar o IP (autenticação) e o valor de poller_id (execução). host_id e local_data_id são inteiros pequenos e sequenciais, facilmente bruteforçáveis até encontrar uma combinação com ação POLLER_ACTION_SCRIPT_PHP configurada.

Como é explorada

O vetor é HTTP direto contra remote_agent.php, sem necessidade de conta, sessão ou qualquer interação de usuário — só acesso de rede ao endpoint (geralmente exposto junto com a interface web do Cacti). O atacante envia uma requisição com um cabeçalho de IP forjado (por exemplo Forwarded-For apontando para o IP do próprio servidor Cacti) para passar o cheque de remote_client_authorized(), depois envia action=polldata com host_id e local_data_id — que podem exigir algumas tentativas de bruteforce até acertar um poller_item cuja ação seja script PHP — e injeta o payload de comando no parâmetro poller_id.

Complexidade de exploração é baixa: não há proteção CSRF relevante no endpoint (ele nem deveria precisar de sessão), a superfície de bruteforce é pequena (IDs numéricos baixos em instalações típicas) e o cabeçalho de spoofing de IP não exige nada além de escolher, entre a lista suportada, um que o servidor não filtre por vir de proxy confiável. O resultado final é execução de comando arbitrário com os privilégios do processo web/PHP do Cacti — RCE completo, não apenas leitura de dados.

A vulnerabilidade está no catálogo KEV da CISA, confirmando exploração ativa em produção, e existem módulo Metasploit, template Nuclei e PoCs públicas circulando — ou seja, o custo de exploração para um atacante oportunista é baixo e a varredura em massa de instâncias Cacti expostas é esperada.

Versões

Afetadas
Cacti até e incluindo a versão 1.2.22 (linha 1.2.x anterior ao patch).
Corrigidas em
1.2.23 e 1.3.0.

Como se proteger

A correção do fornecedor está nas versões 1.2.23 e 1.3.0: o patch reescreve get_client_addr() para não confiar ciegamente em cabeçalhos HTTP_* como fonte de IP do cliente e introduz a opção de configuração $proxy_headers (em include/config.php.dist), que permite desabilitar totalmente a leitura de cabeçalhos de proxy (false, usando só REMOTE_ADDR) ou restringir a uma lista explícita de cabeçalhos confiáveis, em vez do comportamento anterior que aceitava qualquer um dos cabeçalhos listados. Atualizar para 1.2.23 ou 1.3.0 é a mitigação real; o patch por si só não neutraliza o command injection em poller_id — a correção completa depende dos três commits referenciados, que tratam tanto o bypass de autenticação quanto o saneamento da chamada a proc_open.

Se a atualização não for possível de imediato: restrinja o acesso de rede a remote_agent.php para apenas os pollers legítimos (via regra de firewall, controle de acesso no servidor web, ou bloqueio do path inteiro se pollers remotos não forem usados) — isso remove a exposição do endpoint a qualquer origem não confiável. Definir $proxy_headers = false manualmente em include/config.php em versões que já suportam a variável reduz a superfície de spoofing de IP, mas não corrige o command injection subjacente se o endpoint ainda for alcançável por um poller malicioso ou comprometido.

Não funciona como mitigação: confiar em WAF genérico para filtrar cabeçalhos X-Forwarded-For — a lista de cabeçalhos aceitos pela função vulnerável é ampla (inclui CF-Connecting-IP, True-Client-IP, X-Real-IP etc.), então um WAF que bloqueie só um ou dois cabeçalhos deixa outros vetores abertos. A única mitigação equivalente a corrigir é isolar o endpoint na rede até a atualização.

Como detectar

Em logs de aplicação do Cacti (tabela de log / cacti.log), procure por mensagens de erro do tipo "Unauthorized remote agent access attempt from ()" seguidas de tentativas repetidas — indicam bypasses que falharam e podem revelar tentativas anteriores de acerto. No tráfego HTTP, sinal forte é a combinação de requisições para /remote_agent.php?action=polldata com cabeçalhos como Forwarded-For, X-Forwarded-For, X-Client-IP, CF-Connecting-IP ou True-Client-IP contendo o próprio IP do servidor Cacti, e parâmetros host_id/local_data_id variando sequencialmente (padrão de bruteforce). Valores do parâmetro poller_id contendo metacaracteres de shell (;, |, `, $(), &&) são evidência direta de tentativa de injeção — não há uso legítimo desses caracteres nesse campo.

Como o endpoint normalmente não gera logs de autenticação de usuário (é tráfego de poller, não de sessão web), ambientes sem logging de aplicação detalhado ou sem captura de cabeçalhos HTTP completos no proxy/WAF podem não deixar rastro algum — a ausência de sinal não indica ausência de exploração.

Pesquisado e redigido com IA a partir do advisory do fornecedor e de análises públicas, com as fontes acima. Confira sempre a versão corrigida no advisory oficial antes de agir.
Cacti is an open source platform which provides a robust and extensible operational monitoring and fault management framework for users. In affected versions a command injection vulnerability allows an unauthenticated user to execute arbitrary code on a server running Cacti, if a specific data source was selected for any monitored device. The vulnerability resides in the `remote_agent.php` file. This file can be accessed without authentication. This function retrieves the IP address of the client via `get_client_addr` and resolves this IP address to the corresponding hostname via `gethostbyaddr`. After this, it is verified that an entry within the `poller` table exists, where the hostname corresponds to the resolved hostname. If such an entry was found, the function returns `true` and the client is authorized. This authorization can be bypassed due to the implementation of the `get_client_addr` function. The function is defined in the file `lib/functions.php` and checks serval `$_SERVER` variables to determine the IP address of the client. The variables beginning with `HTTP_` can be arbitrarily set by an attacker. Since there is a default entry in the `poller` table with the hostname of the server running Cacti, an attacker can bypass the authentication e.g. by providing the header `Forwarded-For: <TARGETIP>`. This way the function `get_client_addr` returns the IP address of the server running Cacti. The following call to `gethostbyaddr` will resolve this IP address to the hostname of the server, which will pass the `poller` hostname check because of the default entry. After the authorization of the `remote_agent.php` file is bypassed, an attacker can trigger different actions. One of these actions is called `polldata`. The called function `poll_for_data` retrieves a few request parameters and loads the corresponding `poller_item` entries from the database. If the `action` of a `poller_item` equals `POLLER_ACTION_SCRIPT_PHP`, the function `proc_open` is used to execute a PHP script. The attacker-controlled parameter `$poller_id` is retrieved via the function `get_nfilter_request_var`, which allows arbitrary strings. This variable is later inserted into the string passed to `proc_open`, which leads to a command injection vulnerability. By e.g. providing the `poller_id=;id` the `id` command is executed. In order to reach the vulnerable call, the attacker must provide a `host_id` and `local_data_id`, where the `action` of the corresponding `poller_item` is set to `POLLER_ACTION_SCRIPT_PHP`. Both of these ids (`host_id` and `local_data_id`) can easily be bruteforced. The only requirement is that a `poller_item` with an `POLLER_ACTION_SCRIPT_PHP` action exists. This is very likely on a productive instance because this action is added by some predefined templates like `Device - Uptime` or `Device - Polling Time`. This command injection vulnerability allows an unauthenticated user to execute arbitrary commands if a `poller_item` with the `action` type `POLLER_ACTION_SCRIPT_PHP` (`2`) is configured. The authorization bypass should be prevented by not allowing an attacker to make `get_client_addr` (file `lib/functions.php`) return an arbitrary IP address. This could be done by not honoring the `HTTP_...` `$_SERVER` variables. If these should be kept for compatibility reasons it should at least be prevented to fake the IP address of the server running Cacti. This vulnerability has been addressed in both the 1.2.x and 1.3.x release branches with `1.2.23` being the first release containing the patch.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Produtos afetados
Cacti · cacti
PoCs públicas encontradas73
exploitdbwww.exploit-db.com/exploits/51166não verificadogithubgithub.com/0xf4n9x/CVE-2022-4616947githubgithub.com/FredBrave/CVE-2022-46169-CACTI-1.2.2242githubgithub.com/sAsPeCt488/CVE-2022-4616929githubgithub.com/ariyaadinatha/cacti-cve-2022-46169-exploit15githubgithub.com/c3rrberu5/CVE-2022-461699githubgithub.com/ruycr4ft/CVE-2022-461693githubgithub.com/SystemVll/CVE-2022-461693githubgithub.com/icebreack/CVE-2022-461693githubgithub.com/N1arut/CVE-2022-46169_POC3githubgithub.com/sh4den/CVE-2022-461693githubgithub.com/taythebot/CVE-2022-461691githubgithub.com/Safarchand/CVE-2022-461691githubgithub.com/0x0Jackal/CVE-2022-461691githubgithub.com/Habib0x0/CVE-2022-461691githubgithub.com/m3ssap0/cacti-rce-cve-2022-46169-vulnerable-application1githubgithub.com/0xN7y/CVE-2022-461691githubgithub.com/lof1sec/CVE-2022-461690githubgithub.com/devAL3X/CVE-2022-46169_poc0githubgithub.com/svchost9913/CVE-2022-46169_unauth_remote_code_execution0githubgithub.com/devilgothies/CVE-2022-461690githubgithub.com/yassinebk/CVE-2022-461690githubgithub.com/r1nzleer/RCE-Cacti-1.2.220githubgithub.com/BKreisel/CVE-2022-461690githubgithub.com/antisecc/CVE-2022-461690githubgithub.com/RdBBB3/SHELL-POC-CVE-2022-461690githubgithub.com/alv-david/CVE-2022-46169-Cacti-1.2.220githubgithub.com/nicostan15/CVE-2022-461690githubgithub.com/imjdl/CVE-2022-461690githubgithub.com/miko550/CVE-2022-461690githubgithub.com/Rickster5555/EH2-PoC0githubgithub.com/nou-man/CVE-2022-461690githubgithub.com/dawnl3ss/CVE-2022-461690githubgithub.com/a1665454764/CVE-2022-461690githubgithub.com/0xZon/CVE-2022-46169-Exploit0githubgithub.com/mind2hex/CVE-2022-46169-Cacti-v1.2.22-RCE0githubgithub.com/HPT-Intern-Task-Submission/CVE-2022-461690vulncheckvulncheck.com/xdb/564568ef13c1não verificadovulncheckvulncheck.com/xdb/42e7e3d26487não verificadovulncheckvulncheck.com/xdb/5c3c4797be34não verificadovulncheckvulncheck.com/xdb/d6bfae898370não verificadovulncheckvulncheck.com/xdb/9cc18470fe06não verificadovulncheckvulncheck.com/xdb/1ea0dc48f935não verificadovulncheckvulncheck.com/xdb/de179daeb01fnão verificadovulncheckvulncheck.com/xdb/4eaa363922b4não verificadovulncheckvulncheck.com/xdb/34a258cbb84enão verificadovulncheckvulncheck.com/xdb/033e24c697acnão verificadovulncheckvulncheck.com/xdb/1f8fe00d0251não verificadovulncheckvulncheck.com/xdb/ab7dd53a6032não verificadovulncheckvulncheck.com/xdb/e1a4679413d3não verificadovulncheckvulncheck.com/xdb/12bb415c1fc2não verificadovulncheckvulncheck.com/xdb/8ef8e9059276não verificadovulncheckvulncheck.com/xdb/7e40710254danão verificadovulncheckvulncheck.com/xdb/8b4444ba432dnão verificadovulncheckvulncheck.com/xdb/82a30062e410não verificadovulncheckvulncheck.com/xdb/adcb07c757a5não verificadovulncheckvulncheck.com/xdb/62e4658694fenão verificadovulncheckvulncheck.com/xdb/77058a66967dnão verificadovulncheckvulncheck.com/xdb/678315c2b725não verificadovulncheckvulncheck.com/xdb/18c497dc094dnão verificadovulncheckvulncheck.com/xdb/ced8bc131b4anão verificadovulncheckvulncheck.com/xdb/b42b36e9f070não verificadovulncheckvulncheck.com/xdb/a131913950fbnão verificadovulncheckvulncheck.com/xdb/a55dda03e4e8não verificadovulncheckvulncheck.com/xdb/fe2d74ab12b3não verificadovulncheckvulncheck.com/xdb/8889d02a2c92não verificadovulncheckvulncheck.com/xdb/1f2f47fde662não verificadovulncheckvulncheck.com/xdb/76e9d4feab18não verificadovulncheckvulncheck.com/xdb/c3426a18652bnão verificadovulncheckvulncheck.com/xdb/e0af26285da6não verificadovulncheckvulncheck.com/xdb/6281e1eb6950não verificadovulncheckvulncheck.com/xdb/f6ffcfbeab8cnão verificadovulncheckvulncheck.com/xdb/4174b70e7788não verificado
⚠ Recursos públicos, para você avaliar a exposição de sistemas que controla ou está autorizado a testar. Teste apenas com autorização.