CWE-705, Incorrect Control Flow Scoping, describes a product that does not return control to the proper location after finishing a task or detecting an unusual condition. The consequence MITRE records is altered execution logic. It is not language specific.
Two things can go wrong. Control can skip past code that should have run, or land somewhere it should never have been.
How it happens
CVE-2014-1266 is Apple's well known "goto fail" bug. An incorrect goto in an SSL product bypassed certificate validation, enabling an adversary-in-the-middle attack. MITRE shows it as a chain from this weakness into the weakness of an unintended path.
The shape was a duplicated line. An illustration of the pattern, not the original source:
// Vulnerable: the second goto is outside the if, so it always runs
if ((err = check_hash(ctx)) != 0)
goto fail;
goto fail; // always taken
if ((err = check_signature(ctx)) != 0) // never reached
goto fail;
fail:
return err; // err is still 0 here: success
The skipped signature check leaves err at zero, so the function returns success.
CVE-2023-21087 is a different flavor: Java code in a smartphone OS can encounter a boot loop due to an uncaught exception. An error was detected, control went to no handler, and the system restarted over and over.
What an attacker gains
Altered logic means whatever the skipped or misdirected code protected. In one case, a trusted connection with an unverified peer. In the other, a device that will not start.
How to find it
MITRE notes static analysis can find some instances by modelling data and control flow. Unreachable code warnings and misleading indentation warnings catch the goto fail shape. Test failure paths so that each check is shown to fail when it should.
How to fix it
- Always use braces on conditionals so an added line cannot slip out of the block.
- Turn on warnings for unreachable code and misleading indentation, and fail the build on them.
- Initialize result variables to failure, not success.
- Catch exceptions at a boundary that decides what the failure means.
- Write a test per check that proves a bad input is rejected.
int err = -1; // default is failure
if ((err = check_hash(ctx)) != 0) { goto fail; }
if ((err = check_signature(ctx)) != 0) { goto fail; }
err = 0;
fail:
return err;
Quick check
Why does initializing to failure help?
If control skips a check, the function still returns failure instead of a stale success value.
What caused the boot loop in CVE-2023-21087?
An uncaught exception in Java code, so control had no proper place to return to.