
Signal-Server v20261007.0.0 - Alta - Remoto - Privilegio residuo - admin Dropwizard non autenticato :8081
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · signal-server-dropwizard-admin
Write-up: https://abraxaslabs.tech/research/signal-server-dropwizard-admin
Classe: Privilegio residuo Portata: Remota
Signal-Server v20261007.0.0 (a15d5cd) - Signal Messenger, LLC
Dropwizard 5.0.2 DefaultServerFactory fornisce un connettore HTTP di amministrazione sulla porta 8081 con bindHost non impostato (tutte le interfacce) e senza autenticazione per l'amministrazione. Signal-Server non lo sovrascrive mai. service/config/sample.yml non ha alcun blocco server:. Un YAML che elenca solo applicationConnectors TLS eredita comunque la 8081 in chiaro su 0.0.0.0. server insieme ai tre worker ServerCommand lo avvia. ExternalRequestFilter è presente solo nel contesto dell'applicazione.
HTTP non autenticato su :8081 è il piano di amministrazione operativo. Non è RCE. Non è account takeover. Non è lettura di messaggi sigillati.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo (amministrazione Dropwizard non autenticata) |
| Portata | Remota (:8081 su tutte le interfacce, nessuna autenticazione) |
| CWE | CWE-306, CWE-1188 |
| CVSS | Alto: 7.3 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L |
| Prodotto | Signal-Server |
| Affetto | v20261007.0.0 (a15d5cd) Dropwizard 5.0.2. Esempio in-tree / adminConnectors omesso. |
| Autenticazione | nessuna sul connettore di amministrazione |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Chiunque possa aprire una connessione TCP verso la porta di amministrazione (predefinita 0.0.0.0:8081, nessuna configurazione aggiuntiva, nessun header Authorization) ottiene ogni servlet di amministrazione standard di Dropwizard 5 più il task aggiuntivo di Signal. Questo è l'intero insieme di privilegi. Nulla in questo elenco è RCE, ATO o lettura dei corpi dei messaggi sigillati.
| Metodo | Percorso | Privilegio |
|---|---|---|
| GET | /ping | Conferma che il listener di amministrazione è attivo. Il corpo è pong. |
| GET | /metrics | Legge l'intero registry Codahale come JSON: heap e non-heap della JVM, conteggi GC, conteggi dei thread, meter dei connettori Jetty, gauge 4xx/5xx, timer. Usalo per fare fingerprinting del processo, stimare il carico e osservare l'effetto dei task successivi. |
| GET | /threads | Thread dump completo della JVM: nome, id, stato e frame di stack di ogni thread. Nel lab questo mostrava dw-admin-* più frame nio di java.base. Su un nodo Signal attivo lo stesso dump può includere nomi di classi, nomi di logger e qualsiasi stringa che si trovi sullo stack (percorsi di file, hostname, toString di argomenti in transito). Non è un heap dump e non è un dump della coda dei messaggi. |
| GET | /healthcheck | Esegue i controlli di salute registrati. Questo albero non registra extra, quindi il corpo è il controllo di deadlock predefinito (deadlocks.healthy). Un 200 rispetto a un 500 ti dice se la JVM ritiene di essere in deadlock. |
| GET | /tasks | Elenca i task di amministrazione. Su questo pin: gc, log-level, set-request-logging-enabled. |
| Metodo | Percorso | Privilegio |
|---|---|---|
| POST | /tasks/log-level?logger=<name>&level=<LEVEL> | Imposta qualsiasi logger Logback su TRACE, DEBUG, INFO, WARN, ERROR o OFF. TRACE può far sì che i logger dell'applicazione stampino di più (inclusi i valori registrati da uno sviluppatore). OFF su un logger di sicurezza o di accesso lo rende cieco. L'attaccante non riceve il flusso di log tramite questo HTTP. Modifica ciò che il processo scrive su disco o su stdout. Oracolo di laboratorio: nome del logger SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS impostato su TRACE. |
| POST | /tasks/gc | Chiama System.gc(). La risposta è Running GC... / Done!. Si tratta di una sollecitazione stop-the-world, non della morte del processo. |
| POST | /tasks/set-request-logging-enabled?enabled=true | Attività solo di segnalazione registrata in WhisperServerService.run. Abilita il filtro di access-log delle richieste (RequestLogManager). Dopo di che, l'HTTP verso il connettore dell'applicazione può scrivere metodo, URI e header (incluso Authorization Basic) nell'access log su disco. Il client admin non riceve indietro quelle righe. Su message-persister-service / APN / worker idle-job la porta dell'applicazione non ha risorse Signal Jersey, quindi questa attività è rilevante su server. enabled=false la disattiva di nuovo. |
ProcessBuilder, nessun Runtime.exec.GET /heapdump restituisce 404.sample.yml o agli indirizzi di bind.Un container gemello sulla stessa rete Docker ha raggiunto http://vuln:8081/ping (200 pong) e non è riuscito a raggiungere http://patched:8081/ping quando bindHost era 127.0.0.1. Questa è la metà Remote.
Ho fissato signalapp/Signal-Server v20261007.0.0. Diciotto ricerche nel codice sorgente. Chat, chiavi, messaggi, backup, donazioni, chiamate, MFA, gRPC omnibus e HTTP in uscita sono risultati vuoti a livello Critical/High. La ricerca su worker/admin no. Dropwizard 5.0.2 HttpConnectorFactory.admin() usa ancora la porta 8081 e un bind host nullo. Signal non imposta mai adminConnectors. L'admin predefinito di Caddy è localhost. Questo no.
Falsa pista: provare ad avviare l'intero Signal-Server. sample.yml supera check e richiede comunque FoundationDB, Dynamo, Redis e un bundle di segreti per run. Il residuo è il connettore del framework che ServerCommand avvia prima di tutto ciò. Il laboratorio è Dropwizard 5.0.2 con lo stesso YAML server: vuoto e il nome di attività extra di Signal.
cd lab
./run.sh
Loopback 127.0.0.1:19010. Progetto Compose signal-server-dropwizard-admin. Witness SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS. Il gadget YAML non ha un blocco server:. Lo YAML negativo imposta bindHost: 127.0.0.1. Ultima riga:
SUCCESS signal-server-dropwizard-admin how=unauth-admin-8081 ping=200 metrics=200 threads=200 healthcheck=200 tasks=200 log-level=TRACE gc=200 set-log=enabled bind=* remote-vuln=200 remote-patched=fail SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS