Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2023-39361 — Análise passo a passo e configuração de laboratório para CVE-2023-39361, uma injeção SQL não autenticada no Cacti v1.2.24, com exploração e guia de mitigação. | Kitploit
Ferramentas/GitHubGitHub/hpt-intern-task-submission/cve-2023-39361
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebAprendizado e EducaçãoLabs e Prática
GitHubhpt-intern-task-submission/cve-2023-39361

CVE-2023-39361

Análise passo a passo e configuração de laboratório para CVE-2023-39361, uma injeção SQL não autenticada no Cacti v1.2.24, com exploração e guia de mitigação.

Ver Repositório
10há 2 anosAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

[CVE-2023-39361] Injeção SQL não autenticada no Cacti v1.2.24

Visão Geral

Cacti é uma ferramenta de monitoramento operacional de código aberto escrita em PHP, MySQL/MariaDB, que fornece uma interface amigável. A vulnerabilidade foi encontrada em 2023 e afetou todas as versões anteriores à 1.2.24. A falha de segurança reside na implementação inadequada ao inserir valores em consultas SQL. Esta é uma vulnerabilidade crítica de injeção SQL que permite que atacantes modifiquem o banco de dados e também executem código remotamente.

Configuração do Laboratório:

Nesta análise, executarei o Cacti no Docker por simplicidade. Primeiro, criaremos o arquivo docker-compose.yml como abaixo e executaremos o comando docker-compose up -d.

version: '3.5'

services:

  
  

cacti:

image: "smcline06/cacti"

container_name: CVE-2023-39361

domainname: example.com

hostname: cacti

ports:

- "80:80"

- "443:443"

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: CVE-2023-39361_db

domainname: example.com

hostname: db

ports:

- "3306:3306"

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=rootpassword

- TZ=America/Los_Angeles

volumes:

- cacti-db:/var/lib/mysql

  
  

volumes:

cacti-db:

cacti-data:

cacti-spine:

cacti-backups:

Após construir o container, podemos acessar o Cacti navegando para http://localhost:80. O próximo passo é atualizar o Cacti para a versão 1.2.24. Você pode baixar o script de atualização aqui: https://pastebin.com/NfRiHLjR. Salve o arquivo no mesmo diretório do arquivo docker-compose.yml e renomeie-o para upgrade_cacti.sh. Em seguida, execute estes 2 comandos:

docker cp upgrade_cacti.sh CVE-2023-39361:/tmp/upgrade_cacti.sh && docker exec -it CVE-2023-39361 bash -c "bash /tmp/upgrade_cacti.sh"

Agora estamos prontos, vamos mergulhar no código para ver o que aconteceu que nos permite ter um ataque de injeção SQL. O arquivo vulnerável é graph_view.php e precisamos apenas do usuário convidado para acessar este arquivo, permitindo que qualquer pessoa explore esta vulnerabilidade. Neste arquivo, a função insegura é grow_right_pane_tree().

grow_right_pane_tree

Antes de mergulharmos profundamente nesta função, precisamos rastrear para trás para saber como as funções são executadas.

<?php
switch (get_nfilter_request_var('action')) {
//.... 
// Many other cases
case  'tree_content':
	//..... Some code here
	// ---------
	if (isset_request_var('node')) {
		$parts = explode('-', sanitize_search_string(get_request_var('node')));
		// Check for tree anchor
		if (strpos(get_nfilter_request_var('node'), 'tree_anchor') !== false) {
			$tree_id = $parts[1];
			$node_id = 0;
		} 
	//..... Some code here

	if ($tree_id > 0) {
		if (!is_tree_allowed($tree_id)) {
			header('Location: permission_denied.php');
			exit;
		}
		// Vulnerable function is called here
		grow_right_pane_tree($tree_id, $node_id, $hgdata);
	}

A partir do trecho de código acima, podemos ver que a função será executada se $tree_id > 0. Todos os passos podem ser explicados abaixo:

  • Primeiro, o programa pegará o valor do parâmetro action da entrada do usuário e entrará em uma estrutura switch/case.

  • No caso tree_content, o código pegará o parâmetro de requisição node do usuário. Em seguida, dividirá a entrada pelo caractere -, salvará em $part e finalmente verificará se tree_anchor aparece em node. Se todas as condições corresponderem, $tree_id será atribuído como o segundo elemento em $part. Por exemplo, tree_content-1 ou 1-2-tree_content serão válidos e o valor de $tree_id será respectivamente.

A partir deste ponto, nossa URL será assim: http://localhost:80?action=tree_content&node=tree_anchor-1. Agora é hora de analisar a função grow_right_pane_tree() para explorar o bug.

grow_right_pane_tree_analyze

O parâmetro vulnerável é rfilter que é passado diretamente para o operando RLIKE dentro da cláusula WHERE. O que o torna vulnerável é que rfilter é envolvido entre aspas duplas ", porém o parâmetro é verificado pela função html_validate_tree_vars(), que se parece com isso:

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');
	/* ================= input validation ================= */
	// ........
}

O tipo de filtro de rfilter está definido como FILTER_VALIDATE_IS_REGEX e armazenado dentro de $filters, então $filter é passado para a função validate_store_request_vars(). Vamos mergulhar nesta função, isso revelará o restante da nossa análise:

function validate_store_request_vars($filters, $sess_prefix = '') {
	// .......
	if (cacti_sizeof($filters)) {
		foreach($filters as $variable => $options) {
		// ....
		elseif ($options['filter'] == FILTER_VALIDATE_IS_REGEX) {
					if (is_base64_encoded($_REQUEST[$variable])) {
						$_REQUEST[$variable] = base64_decode($_REQUEST[$variable]);
					}
					$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;
	}

A função validate_store_request_vars() é responsável por validar a entrada do usuário. Quando o tipo de filter é FILTER_VALIDATE_IS_REGEX, a função chama a função validate_is_regex() com a função preg_match para verificar se nossa entrada é válida. De acordo com a documentação do PHP:

preg_match() retorna 1 se o pattern corresponder ao subject fornecido, 0 se não corresponder, ou false em caso de falha.

A instrução if usa comparação estrita, o que significa que apenas quando ocorre um erro não podemos entrar na instrução if. O $regex, que é nossa entrada, é envolvido entre duas aspas simples '. A intenção dos desenvolvedores é evitar que o usuário injete aspas simples ', que são frequentemente usadas para iniciar um ataque de injeção SQL. Isso parece ser uma implementação de segurança robusta, mas vamos dar uma olhada novamente em como o rfilter é passado para a cláusula WHERE:

$sql_where  .=  ' (gtg.title_cache RLIKE "'  .  get_request_var('rfilter') .  '" OR gtg.title RLIKE "'  .  get_request_var('rfilter') .  '")';

Ah-oh, o esforço de validar a entrada do usuário se torna inútil, pois o rfilter é envolvido entre aspas duplas ", o que permite que atacantes injetem facilmente " para escapar da declaração.

Baixar ferramenta