
Exploit pour CVE-2022-46169
Exploit pour CVE-2022-46169 versions de Cacti antérieures à 1.2.3
Ici, remote_client_authorized vérifie le nom d'hôte du client dans la table poller pour une entrée
function remote_client_authorized() {
// ...
$client_addr = get_client_addr();
// ...
$client_name = gethostbyaddr($client_addr);
// ...
$pollers = db_fetch_assoc('SELECT * FROM poller', true, $poller_db_cnn_id);
foreach($pollers as $poller) {
if (remote_agent_strip_domain($poller['hostname']) == $client_name) {
return true;
// ...
La fonction get_client_addr est utilisée pour obtenir l'adresse du client, qui peut être modifiée par l'attaquant lors de la détermination de l'adresse IP. Elle utilise l'IP pour la résoudre en nom d'hôte correspondant et vérifie si la table poller contient une entrée avec ce nom d'hôte, autorisant ainsi le client.
<?php
// ...
function get_client_addr($client_addr = false) {
$http_addr_headers = array(
// ...
'HTTP_X_FORWARDED',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'HTTP_CLIENT_IP',
'REMOTE_ADDR',
);
$client_addr = false;
foreach ($http_addr_headers as $header) {
// ...
$header_ips = explode(',', $_SERVER[$header]);
foreach ($header_ips as $header_ip) {
// ...
$client_addr = $header_ip;
break 2;
}
}
return $client_addr;
}
donc modifier l'en-tête de la requête nous permet de contourner l'authentification
Et ici, une entrée utilisateur non nettoyée est utilisée pour exécuter une commande externe
// ... retrieve poller items from database ...
foreach($items as $item) {
switch ($item['action']) {
// ...
case POLLER_ACTION_SCRIPT_PHP: /* script (php script server) */
// ...
$cactiphp = proc_open(read_config_option('path_php_binary') . ' -q ' . $config['base_path'] . '/script_server.php realtime ' . $poller_id, $cactides, $pipes);
configurer les en-têtes HTTP à utiliser lors de la détermination de l'IP d'un client
étant donné que la valeur de poller_id doit être un entier, la valider avant de la passer à proc_open