GHSA-q4w7-56hr-83rm: Nginx-UI Settings API Exposes Protected Secrets
SummaryThe `GetSettings` API handler (`api/settings/settings.go:24-65`) serializes all settings structs to JSON and returns them to authenticated users. Many sensitive fields are tagged with `protected:"true"` - however, this tag is only enforced during writes (via `ProtectedFill` in `SaveSettings`) and is completely ignored during reads. This exposes 40+ protected fields including `JwtSecret` (enabling auth token forgery), `NodeSecret` (enabling cluster node impersonation), OIDC `ClientSecret` (enabling OAuth account takeover), and the IP whitelist configuration.DetailsVulnerable Code**`api/settings/settings.go:49-64` - GetSettings serializes all fields**Go's `json.Marshal` serializes all exported fields with `json:` tags. The `protected:"true"` struct tag is a custom tag - it has no effect on JSON serialization.Protection is Write-Only**`api/settings/settings.go:126-135` - ProtectedFill only used during saves**`ProtectedFill` prevents overwriting protected fields during `SaveSettings`, but `GetSettings` has no corresponding filter. The protection is asymmetric - secrets can be read but not overwritten.Exposed Protected Fields**`settings/node.go`:**`Secret` (protected) - used for cluster node authentication`SkipInstallation` (protected), `Demo` (protected)**`settings/oidc.go` (all protected):**`ClientId`, `ClientSecret`, `Endpoint`, `RedirectUri`, `Scopes`, `Identifier`**`settings/casdoor.go` (all protected):**`Endpoint`, `ExternalUrl`, `ClientId`, `ClientSecret`, `CertificatePath`, `Organization`, `Application`, `RedirectUri`**`settings/auth.go`:**`IPWhiteList` (protected) - exposes security configurationAttack ScenarioLow-privilege authenticated user calls `GET /api/settings`Response includes `NodeSecret` - attacker can impersonate cluster nodesResponse includes OIDC `ClientSecret` - attacker can perform OAuth flows as the applicationResponse includes `IPWhiteList` - attacker learns network security configurationIf `JwtSecret` is in app settings (via cosy framework), attacker can forge authentication tokens for any userPoC**1. `GetSettings` serializes all fields** without filtering `protected:"true"` tags. From `api/settings/settings.go:49-64`:Go's `json.Marshal` serializes all exported fields. The custom `protected:"true"` tag has no effect on serialization.**2. Protected secrets are defined** across `settings/*.go`. High-impact examples:**3. `ProtectedFill` is write-only.** It appears 10 times in `SaveSettings` (lines 126-135) but 0 times in `GetSettings`:**4. Exploit request.** Any authenticated user can retrieve all secrets:Response includes (among 45 protected fields):Impact**Authentication bypass via JwtSecret**: An attacker who obtains the `JwtSecret` can forge valid JWT tokens for any user, including admin accounts. This provides permanent, independent access that survives password changes and session revocations.**Cluster compromise via NodeSecret**: The `NodeSecret` is used for inter-node authentication in nginx-ui clusters. An attacker can impersonate any cluster node, push malicious configurations to all nodes, and intercept cluster synchronization traffic.**Third-party OAuth takeover**: Leaked OIDC `ClientSecret` and Casdoor `ClientSecret` allow the attacker to perform OAuth flows as the nginx-ui application, potentially gaining access to user accounts on the identity provider.**Security configuration disclosure**: The `IPWhiteList`, `ReloadCmd`, `RestartCmd`, `ConfigDir`, `SbinPath`, and other protected fields reveal the security posture and infrastructure layout, enabling more targeted attacks.**Low barrier to exploitation**: Any authenticated user (not just admins) can access `GET /api/settings`. In multi-user deployments, a low-privilege operator can escalate to full admin access.RemediationFilter out `protected:"true"` fields before serialization.
CVSS v3.1: 6.5