Signal-Server v20261007.0.0 - 高危 - 远程 - 权限残留 - 未授权 Dropwizard 管理端 :8081
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · signal-server-dropwizard-admin
类别: 权限残留 可达性: 远程
Signal-Server v20261007.0.0(a15d5cd)- Signal Messenger, LLC
Dropwizard 5.0.2 的 DefaultServerFactory 在端口 8081 上附带了一个 HTTP 管理连接器,bindHost 未设置(监听所有接口),且没有管理认证。Signal-Server 从未覆盖该配置。service/config/sample.yml 中没有 server: 块。一个只列出 TLS applicationConnectors 的 YAML 仍然会继承 0.0.0.0 上的明文 8081。server 加上三个 ServerCommand worker 会启动它。ExternalRequestFilter 仅作用于应用上下文。
对 :8081 的未认证 HTTP 就是运维管理平面。 不是 RCE。不是账户接管。不是读取密封消息。
| ID | 暂无 CVE |
| 类别 | 权限残留(未认证的 Dropwizard 管理端) |
| 可达性 | 远程(全接口 :8081,无认证) |
| CWE | CWE-306、CWE-1188 |
| CVSS | 高危:7.3 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L |
| 产品 | Signal-Server |
| 受影响版本 | v20261007.0.0(a15d5cd)Dropwizard 5.0.2。仓库内示例 / 省略 adminConnectors。 |
| 认证 | 管理连接器上无认证 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
任何能够对管理端口建立 TCP 连接的人(默认 0.0.0.0:8081,无需额外配置,无需 Authorization 头)都能访问 Dropwizard 5 自带的全部管理 servlet,外加 Signal 的额外任务。这就是完整的权限集合。此列表中没有一项是 RCE、ATO 或读取密封消息正文。
| 方法 | 路径 | 权限 |
|---|---|---|
| GET | /ping | 确认管理监听器已启动。响应体为 pong。 |
| GET | /metrics | 以 JSON 读取完整的 Codahale 注册表:JVM 堆与非堆、GC 次数、线程数、Jetty 连接器计量器、4xx/5xx 仪表、计时器。用它来对进程进行指纹识别、估算负载,并观察后续任务的效果。 |
| GET | /threads | 完整的 JVM 线程转储:每个线程的名称、id、状态和栈帧。在实验环境中,这显示了 dw-admin-* 以及 java.base nio 帧。在真实的 Signal 节点上,同样的转储可能包含类名、日志记录器名称,以及任何恰好位于栈上的字符串(文件路径、主机名、进行中参数的 toString)。它不是堆转储,也不是消息队列转储。 |
| GET | /healthcheck | 运行已注册的健康检查。此代码树从不注册额外检查,因此响应体是默认的死锁检查(deadlocks.healthy)。200 与 500 告诉你 JVM 是否认为自身已死锁。 |
| GET | /tasks | 列出管理任务。在此版本上:gc、log-level、set-request-logging-enabled。 |
| 方法 | 路径 | 权限 |
|---|---|---|
| POST | /tasks/log-level?logger=<name>&level=<LEVEL> | 将任意 Logback 日志记录器设置为 TRACE、DEBUG、INFO、WARN、ERROR 或 OFF。TRACE 可以让应用日志记录器输出更多内容(包括开发者记录的某些值)。对安全或访问日志记录器设置 OFF 会使其静默。攻击者不会通过此 HTTP 接收日志流。他们改变的是进程写入磁盘或 stdout 的内容。实验验证点:日志记录器名称 SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS 设置为 TRACE。 |
| POST | /tasks/gc | 调用 System.gc()。响应为 Running GC... / Done!。这是一次 stop-the-world 触发,而非进程终止。 |
| POST | /tasks/set-request-logging-enabled?enabled=true | 在 WhisperServerService.run 中注册的 Signal 专属任务。启用请求访问日志过滤器(RequestLogManager)。此后,对应用连接器的 HTTP 请求可以将方法、URI 和头(包括 Authorization Basic)写入磁盘上的访问日志。管理客户端不会收到这些日志行。在 message-persister-service / APN / idle-job worker 上,应用端口没有 Signal Jersey 资源,因此此任务只在 server 上有意义。enabled=false 会再次将其关闭。 |
ProcessBuilder,无 Runtime.exec。GET /heapdump 返回 404。sample.yml 或绑定地址。同一 Docker 网络上的兄弟容器可以访问 http://vuln:8081/ping(200 pong),而当 bindHost 为 127.0.0.1 时无法访问 http://patched:8081/ping。这就是远程的那一半。
我固定了 signalapp/Signal-Server v20261007.0.0。进行了十八次源码搜寻。聊天、密钥、消息、备份、捐赠、通话、MFA、gRPC omnibus 和出站 HTTP 在 Critical/High 级别均无发现。worker/管理端的搜寻则不然。Dropwizard 5.0.2 的 HttpConnectorFactory.admin() 仍然使用端口 8081 和空绑定主机。Signal 从未设置 adminConnectors。Caddy 的默认管理端是 localhost。这个不是。
错误方向:尝试启动完整的 Signal-Server。sample.yml 能通过 check,但 run 仍然需要 FoundationDB、Dynamo、Redis 和一个密钥包。该残留权限是 ServerCommand 在这一切之前启动的框架连接器。实验环境是 Dropwizard 5.0.2,使用相同的空 server: YAML 和 Signal 的额外任务名称。
cd lab
./run.sh
回环地址 127.0.0.1:19010。Compose 项目 signal-server-dropwizard-admin。验证点 SIGNAL-SERVER-DROPWIZARD-ADMIN-WITNESS。Gadget YAML 没有 server: 块。Negative YAML 设置 bindHost: 127.0.0.1。最后一行:
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
将管理端绑定到 127.0.0.1,设置 adminConnectors: [],或在管理上下文上添加认证 / mTLS。不要发布一个只列出应用连接器并假设 8081 已关闭的 YAML。
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]