Safeguard
Application Security•

CWE-696 Incorrect Behavior Order: Right Steps, Wrong Sequence

Drop privileges in the wrong order, initialize too late, enforce a limit after the work is done. CWE-696 is about sequence mistakes and the setuid classic.

Safeguard Security Team
3 min read

CWE-696, Incorrect Behavior Order, covers a product that performs several related behaviors in the wrong order. Each step is present and correct on its own. The sequence is what breaks. MITRE lists web based, not language specific and not technology specific as platforms, and records altered execution logic as the consequence.

How it happens

The record's examples are a good tour.

Dropping privileges. CVE-2007-1588: a C++ web server calls Process::setuid before Process::setgid, which prevents it from dropping privileges and potentially lets CGI programs run with higher privileges than intended. CVE-2007-5191: file system management programs call setuid and setgid in the wrong order and do not check the return values, letting attackers gain unintended privileges.

Using before ready. CVE-2019-9805: creation of a packet client occurs before initialization is complete, resulting in a read from uninitialized memory and memory corruption.

Limits that arrive late. CVE-2022-37734: the lexer in a Java based GraphQL server does not enforce a maximum number of tokens early enough, allowing excessive CPU consumption.

The setuid case is worth spelling out. Once a process gives up root by changing its user ID, it may no longer be allowed to change its group ID. So the group must be dropped first.

// Vulnerable: after setuid, the process can no longer change its group
setuid(unprivileged_uid);
setgid(unprivileged_gid);   // may fail, and the failure is ignored

// Fixed: drop group first, then user, and check both
if (setgid(unprivileged_gid) != 0) { abort(); }
if (setuid(unprivileged_uid) != 0) { abort(); }

What an attacker gains

MITRE lists integrity impact through altered execution logic. In the examples that means retained privileges, memory corruption or a CPU exhausting request. The attacker needs no special trick beyond supplying the input that reaches the misordered code.

How to find it

The record names no detection methods. Review sequences where safety depends on order: privilege changes, initialization, validation and then use, limit and then work. Ask for each one what happens if the first step is late or fails. Test privilege dropping by checking the process identity afterwards, not by trusting the calls.

How to fix it

  1. Put validation and limits before the expensive or dangerous work.
  2. Finish initialization before publishing an object to other code.
  3. Drop group privileges, then user privileges, and check every return value.
  4. Write a test that verifies the end state, such as the effective user and group.

Quick check

Why must setgid come before setuid when dropping root?

After the user ID is changed the process may lack the right to change its group ID, leaving it with the privileged group.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.