VNX-269: Improper Privilege Management
Privileges are dropped in the wrong order: the user ID is changed to a non-root user before the group ID or the supplementary groups, so the later call fails and the process keeps root's groups.
| Field | Value |
|---|---|
| Rule ID | VNX-269 |
| Severity | High |
| SARIF level | error |
| Kind | sast |
| Languages | C, C++, Python |
| CWE | CWE-269 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:H/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H |
| Tags | privilege-mgmt privilege-drop cwe-269 |
| Source | internal/sast/rules/vnx-269.rego |
Overview
VNX-269 maps to CWE-269: Improper Privilege Management. It reports a group change (setgid, setegid, setregid, setresgid, setgroups, initgroups) that comes after the user ID was already dropped to a non-root user in the same function.
Why This Matters
Changing the group ID and the supplementary group list requires root. A daemon that calls setuid(pw->pw_uid) first has already given root up, so its following setgid() or setgroups() fails with EPERM. If the result is not checked, or is checked by a branch that carries on, the process runs as the intended user but still in group 0 and in every supplementary group root had, which often means read access to /etc/shadow-adjacent files, log directories and sockets meant only for administrators.
What Gets Flagged
if (setuid(pw->pw_uid) != 0) exit(1);
if (setgid(pw->pw_gid) != 0) exit(1); /* flagged: too late */
setresuid(uid, uid, uid);
setgroups(0, NULL); /* flagged */
if (::seteuid(uid) == -1) throw std::runtime_error("seteuid");
if (::setegid(gid) == -1) throw std::runtime_error("setegid"); // flagged
os.setuid(pw.pw_uid)
os.setgid(pw.pw_gid) # flagged
os.setgroups([]) # flagged
Not flagged: the correct order (setgroups/initgroups, then setgid, then setuid); a regain of root (seteuid(0)) between the two calls; setgid(0) after the drop, which is the check that root cannot be regained; calls in different functions; and the names in comments or string literals.
Remediation
- Drop in this order: clear or set the supplementary groups (
setgroups(0, NULL)orinitgroups), thensetgid(gid), thensetuid(uid). - Check every return value and stop on failure.
- After the drop, verify it:
setuid(0)andsetgid(0)must now fail.
References
- CWE-269: Improper Privilege Management
- SEI CERT POS36-C: Observe correct revocation order while relinquishing privileges
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-269
// nosec vnx-269
Or record an ignore rule: vulnetix ignore add --rule vnx-269 --reason "...". See Suppressing findings.