
Signal-Server v20261007.0.0 - Hoch - Remote - Privilegien-Rest - unauth Dropwizard-Admin :8081
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · signal-server-dropwizard-admin
Klasse: Privilegien-Überbleibsel Reichweite: Remote
Signal-Server v20261007.0.0 (a15d5cd) - Signal Messenger, LLC
Dropwizard 5.0.2 DefaultServerFactory liefert einen HTTP-Admin-Connector auf Port 8081 mit nicht gesetztem bindHost (alle Interfaces) und ohne Admin-Authentifizierung. Signal-Server überschreibt das nie. service/config/sample.yml hat keinen server:-Block. Eine YAML, die nur TLS-applicationConnectors auflistet, erbt trotzdem den Klartext-Port 8081 auf 0.0.0.0. server plus die drei ServerCommand-Worker starten ihn. ExternalRequestFilter liegt nur im Application-Kontext.
Unauth HTTP auf :8081 ist die operative Admin-Ebene. Kein RCE. Keine Account-Übernahme. Kein Lesen versiegelter Nachrichten.
| ID | noch keine CVE |
| Klasse | Privilegien-Überbleibsel (unauthentifizierter Dropwizard-Admin) |
| Reichweite | Remote (alle Interfaces :8081, keine Auth) |
| CWE | CWE-306, CWE-1188 |
| CVSS | High: 7.3 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L |
| Produkt | Signal-Server |
| Betroffen | v20261007.0.0 (a15d5cd) Dropwizard 5.0.2. In-Tree-Sample / ausgelassene adminConnectors. |
| Auth | keine am Admin-Connector |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Jeder, der TCP zum Admin-Port öffnen kann (Standard 0.0.0.0:8081, keine zusätzliche Konfiguration, kein Authorization-Header), erhält jedes Standard-Dropwizard-5-Admin-Servlet plus Signals zusätzliche Task. Das ist die vollständige Privilegienmenge. Nichts in dieser Liste ist RCE, ATO oder ein Lesen versiegelter Nachrichteninhalte.
| Methode | Pfad | Privileg |
|---|---|---|
| GET | /ping | Bestätigt, dass der Admin-Listener läuft. Body ist pong. |
| GET | /metrics | Liest die vollständige Codahale-Registry als JSON: JVM-Heap und Non-Heap, GC-Zähler, Thread-Zähler, Jetty-Connector-Meter, 4xx/5xx-Gauges, Timer. Damit lässt sich der Prozess fingerprinten, die Last schätzen und die Wirkung späterer Tasks beobachten. |
| GET | /threads | Vollständiger JVM-Thread-Dump: jeder Thread-Name, ID, Status und Stack-Frames. Im Lab zeigte dies dw-admin-* plus java.base-nio-Frames. Auf einem Live-Signal-Node kann derselbe Dump Klassennamen, Logger-Namen und jeden String enthalten, der zufällig auf einem Stack liegt (Dateipfade, Hostnamen, In-Flight-Argument-toString). Es ist kein Heap-Dump und kein Message-Queue-Dump. |
| GET | /healthcheck | Führt registrierte Health-Checks aus. Dieser Tree registriert nie Extras, daher ist der Body der Standard-Deadlock-Check (deadlocks.healthy). Ein 200 vs. 500 sagt, ob die JVM glaubt, in einem Deadlock zu sein. |
| GET | /tasks | Listet Admin-Tasks auf. Bei diesem Pin: gc, log-level, set-request-logging-enabled. |
| Methode | Pfad | Privileg |
|---|---|---|
| POST | /tasks/log-level?logger=<name>&level=<LEVEL> | Setzt jeden Logback-Logger auf TRACE, DEBUG, INFO, WARN, ERROR oder OFF. TRACE kann Application-Logger dazu bringen, mehr auszugeben (einschließlich Werten, die ein Entwickler geloggt hat). OFF bei einem Security- oder Access-Logger macht diesen dunkel. Der Angreifer erhält den Log-Stream nicht über dieses HTTP. Er ändert, was der Prozess auf Disk oder stdout schreibt. Lab-Oracle: Logger-Name SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS auf TRACE. |
| POST | /tasks/gc | Ruft System.gc() auf. Antwort ist Running GC... / Done!. Das ist ein Stop-the-World-Anstoß, kein Prozessende. |
| POST | /tasks/set-request-logging-enabled?enabled=true | Signal-spezifische Task, registriert in WhisperServerService.run. Aktiviert den Request-Access-Log-Filter (RequestLogManager). Danach kann HTTP zum Application-Connector Methode, URI und Header (einschließlich Authorization Basic) in das Access-Log auf Disk schreiben. Der Admin-Client erhält diese Zeilen nicht zurück. Bei message-persister-service / APN / Idle-Job-Workern hat der Application-Port keine Signal-Jersey-Ressourcen, daher ist diese Task auf server relevant. enabled=false schaltet sie wieder aus. |
ProcessBuilder, kein Runtime.exec.GET /heapdump ist 404.sample.yml oder an Bind-Adressen.Ein Schwester-Container im selben Docker-Netzwerk erreichte http://vuln:8081/ping (200 pong) und konnte http://patched:8081/ping nicht erreichen, als bindHost 127.0.0.1 war. Das ist die Remote-Hälfte.
Ich habe signalapp/Signal-Server v20261007.0.0 gepinnt. Achtzehn Source-Hunts. Chat, Keys, Messages, Backups, Donations, Calling, MFA, gRPC-Omnibus und Outbound-HTTP kamen bei Critical/High leer zurück. Die Worker-/Admin-Hunt nicht. Dropwizard 5.0.2 HttpConnectorFactory.admin() verwendet weiterhin Port 8081 und einen Null-Bind-Host. Signal setzt nie adminConnectors. Caddys Standard-Admin ist localhost. Dieser nicht.
Fehlversuch: den vollständigen Signal-Server booten zu wollen. sample.yml besteht check und benötigt trotzdem FoundationDB, Dynamo, Redis und ein Secrets-Bundle, um run auszuführen. Das Überbleibsel ist der Framework-Connector, den ServerCommand vor all dem startet. Das Lab ist Dropwizard 5.0.2 mit derselben leeren server:-YAML und Signals zusätzlichem Task-Namen.
cd lab
./run.sh
Loopback 127.0.0.1:19010. Compose-Projekt signal-server-dropwizard-admin. Witness SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS. Gadget-YAML hat keinen server:-Block. Negative YAML setzt bindHost: 127.0.0.1. Letzte Zeile:
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
Admin an 127.0.0.1 binden, adminConnectors: [] setzen oder Authentifizierung / mTLS im Admin-Kontext einrichten. Keine YAML ausliefern, die nur Application-Connectors auflistet und annimmt, dass 8081 aus bleibt.
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]