CWE-269

Improper Privilege Management. [Improper-Access-Control, Top25-2024-15]

Required inputs: IR

The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
Demonstrative Examples
Example 1

This code temporarily raises the program's privileges to allow creation of a new user folder.

Example Language:Python (Unsupported language for documentation only)
    def makeNewUserDir(username):
        if invalidUsername(username):
            #avoid CWE-22 and CWE-78
            print('Usernames cannot contain invalid characters')
            return False

        try:
            raisePrivileges()
            os.mkdir('/home/' + username)
            lowerPrivileges()

        except OSError:
            print('Unable to create new user directory for user:' + username)
            return False

        return True

While the program only raises its privilege level to create the folder and immediately lowers it again, if the call to os.mkdir() throws an exception, the call to lowerPrivileges() will not occur. As a result, the program is indefinitely operating in a raised privilege state, possibly allowing further exploitation to occur.

Example 2

The following example demonstrates the weakness.

Example Language:C
    seteuid(0);
    /* do some stuff */

    seteuid(getuid());
Example 3

The following example demonstrates the weakness.

Example Language:Java (Unsupported language for documentation only)
    AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            // privileged code goes here, for example:
            System.loadLibrary("awt");
            return null;
            // nothing to return
        }
Example 4

This code intends to allow only Administrators to print debug information about a system.

Example Language:Java (Unsupported language for documentation only)
    public enum Roles {
        ADMIN,USER,GUEST
    }

    public void printDebugInfo(User requestingUser){
        if(isAuthenticated(requestingUser)){
            switch(requestingUser.role){
                case GUEST:
                    System.out.println("You are not authorized to perform this command");
                    break;

                default:
                    System.out.println(currentDebugState());
                    break;
            }
        }
        else{
            System.out.println("You must be logged in to perform this command");
        }
    }

While the intention was to only allow Administrators to print the debug information, the code as written only excludes those with the role of "GUEST". Someone with the role of "ADMIN" or "USER" will be allowed access, which goes against the original intent. An attacker may be able to use this debug information to craft an attack on the system.

Example 5

This code allows someone with the role of "ADMIN" or "OPERATOR" to reset a user's password. The role of "OPERATOR" is intended to have less privileges than an "ADMIN", but still be able to help users with small issues such as forgotten passwords.

Example Language:Java (Unsupported language for documentation only)
    public enum Roles {
        ADMIN,OPERATOR,USER,GUEST
    }

    public void resetPassword(User requestingUser, User user, String password ){
        if(isAuthenticated(requestingUser)){
            switch(requestingUser.role){
                case GUEST:
                    System.out.println("You are not authorized to perform this command");
                    break;

                case USER:
                    System.out.println("You are not authorized to perform this command");
                    break;

                default:
                    setPassword(user,password);
                    break;
                }
            }

        else{
            System.out.println("You must be logged in to perform this command");
        }
    }

This code does not check the role of the user whose password is being reset. It is possible for an Operator to gain Admin privileges by resetting the password of an Admin account and taking control of that account.

Excerpts from CWE [https://cwe.mitre.org], Copyright (C) 2006-2026, the MITRE Corporation. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

check_privilege_drop

setuid(getuid()) call must be followed by a setuid(0) != -1 check.

None

False

chroot_without_setuid

The chroot() call should be followed by a setuid() call to drop privileges.

None

False

discarded_return_with_entity

Return value of function discarded.

None

False

setuid_zero

Setuid should not be called with 0 as argument, as this grants root privileges.

None

False

unhandled_return_value

Return value of function call not properly checked.

None

False

Options

allow_assignment_to_globals

allow_assignment_to_globals : bool = False

Whether assignment to global / static variables should be allowed. If set to false, an error will be reported if the returned value is assigned to a global variable and any call is performed before checking the return (i.e., some other routine could access the return value before checking it).
 

allow_assignment_to_variables_with_pointers

allow_assignment_to_variables_with_pointers : bool = True

Whether assignment to variables of which the address has been taken somewhere should be allowed. If set to false, an error will be reported if the return value is assigned to such a variable, to ensure that the return value is checked locally, before any access from outside is possible.
 

allowed_functions

allowed_functions : set[bauhaus.analysis.config.FunctionName] = {'memcpy', 'memmove', 'memset', 'strcat', 'strcpy', 'strncat', 'strncpy'}

Calls to these functions are ignored.
 

check_operators

check_operators : bool = False

Also check operator calls. Unused return values of assignment operators are only reported if given in function style syntax.
 

functions

functions

Type: dict[bauhaus.analysis.config.QualifiedName, bauhaus.ir.common.algorithms.matchers.Matcher]

Default:

{
   'ImpersonateNamedPipeClient': <bauhaus.rules.axivion.expressions.calls.unhandled_return_value.BinaryRelationAnyMatcher object at 0x7f6f1b83a0b0>
}
Allows to declare function names for which a check must exist. The check is expressed as an IR pattern.
 

known_check_functions

known_check_functions : set[bauhaus.analysis.config.FunctionName] = set()

Collection of functions which are known to test return values of functions under test.
 

report_references

report_references : bool = False

Report returned references. For operators, unused returned references are only reported if given in function style syntax.