Skip to content

Commit 505cc0c

Browse files
1 parent c0f5c04 commit 505cc0c

2 files changed

Lines changed: 145 additions & 0 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-m468-xcm6-fxg4",
4+
"modified": "2026-03-30T16:34:35Z",
5+
"published": "2026-03-30T16:34:35Z",
6+
"aliases": [
7+
"CVE-2026-33028"
8+
],
9+
"summary": "nginx-ui has Race Condition that Leads to Persistent Data Corruption and Service Collapse",
10+
"details": "### Summary\nThe `nginx-ui` application is vulnerable to a **Race Condition**. Due to the complete absence of synchronization mechanisms (Mutex) and non-atomic file writes, concurrent requests lead to the severe corruption of the primary configuration file (`app.ini`). This vulnerability results in a persistent Denial of Service (DoS) and introduces a non-deterministic path for **Remote Code Execution (RCE)** through configuration cross-contamination.\n\n### Details\nThe vulnerability exists because the settings update pipeline does not implement any synchronization primitives. When multiple requests reach the handler simultaneously:\n1. **Memory Corruption**: `ProtectedFill()` modifies shared global singleton pointers without thread-safety, leading to inconsistent states in memory.\n2. **File Corruption**: The underlying library (`gopkg.in/ini.v1`) performs direct overwrites. Concurrent write operations interleave at the OS level, resulting in `app.ini` files with empty leading lines, truncated fields, or partially overwritten configuration keys.\n3. **State Persistent Failure**: Depending on which bytes are corrupted, the application either fails its \"is-installed\" check (redirecting to `/install`) or encounters a fatal error during boot/runtime that prevents the process from responding to any further requests.\n\n**Environment:**\n- **OS**: Kali Linux 6.17.10-1kali1 (6.17.10+kali-amd64)\n- **Application Version**: nginx-ui v2.3.3 (513) e5da6dd (go1.26.0)\n- **Deployment**: Docker Container\n\n### PoC\n0. Check original app.ini file valid state:\n<img width=\"524\" height=\"367\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d9688f76-7fe7-46ea-9eb9-c55bf40918a6\" />\n\n1. Log in to the `nginx-ui` dashboard.\n2. Navigate to Preferences and update settings. Capture a `POST /api/settings` request and send it to **Burp Suite Intruder**.\n3. Configure the attack with **Null payloads** (to test basic concurrency) or a **Fuzzing list** (to test data-driven corruption).\n4. Set the **Resource Pool** to 20-50 concurrent requests.\n<img width=\"1188\" height=\"776\" alt=\"image\" src=\"https://github.com/user-attachments/assets/403eef43-2bc6-4651-8802-15ddcb4f7631\" />\n\n5. **Observation (In-flight corruption)**: Monitor the `app.ini` file. You will observe the file being written with empty leading lines or incomplete key-value pairs. \n\n- <img width=\"1316\" height=\"390\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d99553f7-d253-4525-9b45-f59994e69180\" />\n------------------------------------------------\n\n- <img width=\"1368\" height=\"709\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7522ba29-39f1-4c22-88f2-8e859cdb1984\" />\n\n6. **Observation (Recovery Failure)**: If the service redirects to `/install`, attempting to complete the setup again often fails because the underlying configuration state is too corrupted to be reconciled by the installer logic.\n7. **Observation (Total Service Collapse)**: When the corruption in `app.ini` becomes so severe, the Go runtime or the INI parser encounters a fatal error, causing the Nginx-UI service to stop responding entirely (Hard DoS).\n\n<img width=\"1344\" height=\"542\" alt=\"image\" src=\"https://github.com/user-attachments/assets/da4b99dc-ddce-4b79-b0bb-2d634bdd3bf7\" />\n\n8. **Observation (Cross-Section Contamination)**: During testing, it was observed that sometimes INI sections become interleaved. For example, fields belonging to the `[nginx]` section (like `ConfigDir` or `ReloadCmd`) were erroneously written under the `[webauthn]` section.\n \n **Example of corrupted output observed:**\n```\n[webauthn]\nRPDisplayName = \nRPID = \nRPOrigins = \ngDirWhiteList = \nConfigDir = /etc/nginx\nConfigPath = \nPIDPath = /run/nginx.pid\nSbinPath = \nTestConfigCmd = \nReloadCmd = nginx -s reload\nRestartCmd = nginx -s stop\nStubStatusPort = 51820\nContainerName = \n```\n\n### Impact\nThis is a **High** security risk (CWE-362: Race Condition).\n- **Integrity**: Permanent corruption of application settings and system-level configuration.\n- **Availability**: High. The attack results in a persistent Denial of Service that cannot be recovered via the web UI.\n- **Remote Code Execution (RCE)** Risk: Since the application allows updating certain fields (like Node Name) and uses others as shell commands (like ReloadCmd or RestartCmd), the observed \"cross-contamination\" of INI values means an attacker could potentially force a user-controlled string into a command execution field. If ReloadCmd is overwritten with a malicious payload provided in another field, the next nginx reload will execute that payload. While highly impactful, this specific exploit path is non-deterministic and depends on the precise interleaving of thread execution, making targeted exploitation difficult.\n\n### Recommended Mitigation\n1. **Implement Mutex Locking**: Wrap the `ProtectedFill` and `settings.Save()` calls in a `sync.Mutex` to serialize access to global settings.\n2. **Atomic File Writes**: Implement a \"write-then-rename\" strategy. Write the new configuration to `app.ini.tmp` and use `os.Rename()` to replace the original file atomically, ensuring the configuration file is always in a valid state.\n\nA patched version of nginx-ui is available at https://github.com/0xJacky/nginx-ui/releases/tag/v2.3.4.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/0xJacky/Nginx-UI"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "1.99"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "Go",
40+
"name": "github.com/uozi-tech/cosy"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"fixed": "1.30.1"
51+
}
52+
]
53+
}
54+
],
55+
"database_specific": {
56+
"last_known_affected_version_range": "<= 1.30.0"
57+
}
58+
}
59+
],
60+
"references": [
61+
{
62+
"type": "WEB",
63+
"url": "https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-m468-xcm6-fxg4"
64+
},
65+
{
66+
"type": "PACKAGE",
67+
"url": "https://github.com/0xJacky/nginx-ui"
68+
},
69+
{
70+
"type": "WEB",
71+
"url": "https://github.com/0xJacky/nginx-ui/releases/tag/v2.3.4"
72+
}
73+
],
74+
"database_specific": {
75+
"cwe_ids": [
76+
"CWE-362"
77+
],
78+
"severity": "HIGH",
79+
"github_reviewed": true,
80+
"github_reviewed_at": "2026-03-30T16:34:35Z",
81+
"nvd_published_at": null
82+
}
83+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-m8p8-53vf-8357",
4+
"modified": "2026-03-30T16:33:00Z",
5+
"published": "2026-03-30T16:33:00Z",
6+
"aliases": [
7+
"CVE-2026-33027"
8+
],
9+
"summary": "Nginx Configuration Directory Vulnerable to Recursive Deletion via Improper Path Validation",
10+
"details": "## Summary\nThe nginx-ui configuration improperly handles URL-encoded traversal sequences. When specially crafted paths are supplied, the backend resolves them to the base Nginx configuration directory and executes the operation on the base directory (/etc/nginx). In particular, this allows an authenticated user to remove the entire `/etc/nginx` directory, resulting in a partial Denial of Service.\n\n## Details\nThe file deletion logic fails to correctly validate and normalize paths containing URL-encoded traversal sequences such as `..%252F`.\n\nWhen such input is processed, the internal path resolution logic attempts to clamp the path into the allowed configuration directory. Instead of rejecting the traversal attempt, the clamping mechanism resolves the path to the base Nginx configuration directory itself.\n\nBecause the deletion handler invokes `os.RemoveAll`, which recursively removes directories, this results in the deletion of the entire `/etc/nginx` directory.\n\nThis behavior creates a dangerous interaction between path normalization and deletion logic:\n\n- Traversal sequences are not rejected.\n- Double-encoding (`..%252F`) is used to bypass initial shallow filters.\n- The clamping mechanism resolves malicious paths to the base configuration directory.\n- The deletion handler recursively deletes the resolved path.\n\nAs a result, an attacker can trigger deletion of the entire Nginx configuration directory instead of being blocked by path validation logic.\n\n### Root Cause\n\nThe vulnerability results from a combination of design flaws:\n\n- **Improper Path Canonicalization**: URL-encoded traversal sequences are not properly rejected.\n- **Unsafe Fallback Logic**: The `GetConfPath` clamping mechanism returns the base configuration directory when traversal is detected instead of rejecting the request.\n- **Unsafe Deletion Primitive**: The deletion handler invokes `os.RemoveAll`, which recursively deletes directories without additional safeguards. (delete.go)\n```\n\t// Delete the file or directory\n\terr = os.RemoveAll(fullPath)\n\tif err != nil {\n\t\tcosy.ErrHandler(c, err)\n\t\treturn\n\t}\n```\nThis interaction causes the deletion operation to target the most sensitive directory when a traversal attempt occurs.\n\n### Environment\n- **Server OS**: Kali Linux 6.17.10-1kali1 (6.17.10+kali-amd64)\n- **Nginx UI Version**: nginx-ui v2.3.3\n- **Deployment**: Docker / Default installation\n\n\n## Proof of Concept\n### Steps to Reproduce\n1. Log into nginx-ui.\n\n2. Go to Manage Configs and create a Folder named *..%252F..%252F..%252F..%252Ftest*\n<img width=\"1608\" height=\"559\" alt=\"image\" src=\"https://github.com/user-attachments/assets/738d7d65-7e13-48fa-affc-d5509c43900f\" />\n\n3. Observe that the backend resolves the path to /etc/nginx.. \n\n4. Now lets create a file called *testing*. \n\n5. Save it and rename it to *..%252F..%252F..%252F..%252Ftest* (It is not possible to create it directly with the payload name so we have to rename it)\n\n6. Go back to manage configs and Click Delete to remove the file we just created. \n\n7. Check that there is an error: \n<img width=\"1578\" height=\"696\" alt=\"image\" src=\"https://github.com/user-attachments/assets/51a36310-0676-4fe5-b80c-e0199498efbf\" />\n\n8. Reload the website and check that the /etc/nginx folder has been completely removed: \n<img width=\"1313\" height=\"722\" alt=\"image\" src=\"https://github.com/user-attachments/assets/0a9ddd1b-786b-4cf2-8abd-1dc6f3a77807\" />\n\n\n## Impact\n\nAn authenticated user capable of invoking the configuration deletion endpoint can trigger the recursive deletion of the entire Nginx configuration directory (`/etc/nginx`).\n\nThis results in:\n- Immediate failure of the Nginx service due to missing configuration files.\n- Loss of all Nginx configuration managed by nginx-ui.\n- Denial of Service for all web services relying on the affected Nginx instance.\n\nAs the deletion operation uses a recursive filesystem call, the entire configuration directory is removed, leaving the system unable to restart Nginx until the configuration is manually restored.\n\nA patched version is available at https://github.com/0xJacky/nginx-ui/releases/tag/v2.3.4.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/0xJacky/Nginx-UI"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "1.99"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/0xJacky/nginx-ui/security/advisories/GHSA-m8p8-53vf-8357"
42+
},
43+
{
44+
"type": "PACKAGE",
45+
"url": "https://github.com/0xJacky/nginx-ui"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/0xJacky/nginx-ui/releases/tag/v2.3.4"
50+
}
51+
],
52+
"database_specific": {
53+
"cwe_ids": [
54+
"CWE-22",
55+
"CWE-73"
56+
],
57+
"severity": "MODERATE",
58+
"github_reviewed": true,
59+
"github_reviewed_at": "2026-03-30T16:33:00Z",
60+
"nvd_published_at": null
61+
}
62+
}

0 commit comments

Comments
 (0)