Privilege Chaining

Description

Privilege Chaining is a vulnerability that occurs when two distinct privileges, roles, capabilities, or rights can be combined in a way that allows an entity to perform unsafe actions that would not be allowed if each privilege were exercised individually. The vulnerability arises not from any single privilege being excessive, but from the interaction between multiple privileges when held by the same entity. This can occur when privilege systems are designed without considering the cumulative effect of combining permissions, when role-based access control allows dangerous role combinations, or when capability inheritance creates unintended privilege escalation paths.

Risk

Privilege chaining creates significant security risks because each individual privilege may appear safe when analyzed in isolation, but their combination creates dangerous capabilities. Users or processes with multiple legitimate roles may inadvertently gain access to functionality or data that should require higher authorization. Attackers who can obtain or manipulate multiple privileges can chain them together for privilege escalation. The risk is particularly acute in complex systems with numerous roles and permissions where the interaction matrix is difficult to fully analyze. Administrative oversights in role assignment can create dangerous combinations that go undetected until exploited.

Solution

Implement privilege analysis that considers the cumulative effect of multiple privileges when assigned to the same entity. Create a privilege incompatibility matrix that identifies dangerous combinations and prevents their simultaneous assignment. Apply the principle of separation of duties to ensure critical actions require multiple independent actors rather than multiple privileges held by one actor. Implement runtime checks that detect and prevent dangerous privilege combinations. Use role hierarchy analysis tools to identify potential chaining vulnerabilities. Design privilege systems with minimal overlap between capabilities. Conduct regular audits of privilege assignments to detect dangerous combinations. Document expected privilege combinations and implement technical controls to enforce these constraints.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Attackers or legitimate users who hold multiple privileges can combine them to perform actions beyond the intended authorization scope. This can include accessing restricted data, performing administrative operations, or bypassing security controls through the cumulative effect of individually safe privileges.

Example Code

Vulnerable Code (Python)

The following examples demonstrate privilege chaining vulnerabilities:

# Vulnerable: Privileges that combine unsafely
class VulnerablePrivilegeSystem:

    def __init__(self):
        self.privileges = {
            'view_audit_log': {'view_logs', 'read_user_ids'},
            'manage_user_profiles': {'read_user_profiles', 'write_user_profiles'},
            'run_reports': {'execute_queries', 'export_data'},
            'debug_system': {'read_memory', 'attach_debugger'}
        }

    def check_permission(self, user, action):
        # Check each privilege independently
        for privilege in user.privileges:
            if action in self.privileges.get(privilege, set()):
                return True
        return False

    def perform_action(self, user, action, target):
        if self.check_permission(user, action):
            # Vulnerable: No check for dangerous privilege combinations
            # User with 'view_audit_log' + 'manage_user_profiles' can:
            # 1. Read user IDs from audit log
            # 2. Modify those user profiles
            # Combined effect: Track and modify any user
            return self.execute_action(action, target)
        return False


class VulnerableDocumentSystem:

    def __init__(self):
        # Individual privileges seem safe
        self.role_permissions = {
            'document_viewer': ['read_documents', 'list_documents'],
            'template_manager': ['read_templates', 'modify_templates'],
            'workflow_admin': ['modify_workflow', 'assign_workflow']
        }

    def can_access(self, user, action):
        for role in user.roles:
            if action in self.role_permissions.get(role, []):
                return True
        return False

    def process_document(self, user, document_id, action):
        # Vulnerable privilege chain:
        # 1. template_manager can modify templates
        # 2. workflow_admin can assign templates to workflows
        # 3. Combining both: Create malicious template, assign to critical workflow
        #    -> Affects all documents processed through that workflow

        if self.can_access(user, action):
            # No detection of dangerous role combination
            self.execute_action(document_id, action)
// Vulnerable: Database privilege chaining
public class VulnerableDatabasePrivileges {

    public void grantPrivileges(User user, List<String> requestedPrivileges) {
        for (String privilege : requestedPrivileges) {
            // Each privilege checked independently
            if (isValidPrivilege(privilege)) {
                user.addPrivilege(privilege);
            }
        }

        // Vulnerable: No check for dangerous combinations
        // User with SELECT + TRIGGER privileges can:
        // 1. SELECT from sensitive tables (allowed)
        // 2. Create trigger that executes on their SELECT
        // 3. Trigger runs with definer privileges, not invoker
        // Combined effect: Privilege escalation through trigger exploitation
    }
}

Fixed Code (Python)

# Fixed: Detect and prevent dangerous privilege combinations
class SecurePrivilegeSystem:

    def __init__(self):
        self.privileges = {
            'view_audit_log': {'view_logs', 'read_user_ids'},
            'manage_user_profiles': {'read_user_profiles', 'write_user_profiles'},
            'run_reports': {'execute_queries', 'export_data'},
            'debug_system': {'read_memory', 'attach_debugger'}
        }

        # Define incompatible privilege combinations
        self.incompatible_privileges = [
            # Cannot have both audit viewing and profile management
            {'view_audit_log', 'manage_user_profiles'},
            # Cannot have both debug and data export
            {'debug_system', 'run_reports'},
            # Cannot have both memory access and network access
            {'debug_system', 'network_admin'},
        ]

        # Actions requiring separation of duties
        self.dual_control_actions = {
            'delete_audit_log': ['audit_admin', 'security_officer'],
            'modify_security_policy': ['security_admin', 'compliance_officer'],
            'emergency_access': ['admin', 'manager_approval']
        }

    def validate_privilege_assignment(self, user, new_privilege):
        """Check if adding privilege creates dangerous combination"""
        proposed_privileges = user.privileges | {new_privilege}

        for incompatible_set in self.incompatible_privileges:
            if incompatible_set.issubset(proposed_privileges):
                raise PrivilegeConflictError(
                    f"Cannot combine {incompatible_set} - security violation"
                )

        return True

    def check_permission(self, user, action, require_dual_control=True):
        # Check for dual control requirements
        if action in self.dual_control_actions and require_dual_control:
            required_roles = self.dual_control_actions[action]
            if not self._has_dual_authorization(user, required_roles):
                raise DualControlRequired(
                    f"Action {action} requires approval from: {required_roles}"
                )

        # Standard permission check
        for privilege in user.privileges:
            if action in self.privileges.get(privilege, set()):
                return True
        return False

    def _has_dual_authorization(self, user, required_roles):
        """Ensure action is authorized by multiple independent parties"""
        # User cannot self-authorize dual control actions
        authorizations = self.pending_authorizations.get(user.id, {})

        for role in required_roles:
            if role in user.roles:
                # User has the role, need authorization from someone else
                if not authorizations.get(role):
                    return False

        return True

    def assign_privilege(self, assigner, target_user, privilege):
        """Assign privilege with chaining detection"""

        # Validate the assignment won't create dangerous chains
        self.validate_privilege_assignment(target_user, privilege)

        # Log for audit
        self.audit_log.record(
            action='privilege_assigned',
            assigner=assigner.id,
            target=target_user.id,
            privilege=privilege,
            resulting_privileges=list(target_user.privileges | {privilege})
        )

        target_user.privileges.add(privilege)


class SecureDocumentSystem:

    # Role incompatibility matrix
    INCOMPATIBLE_ROLES = {
        frozenset(['template_manager', 'workflow_admin']),
        frozenset(['document_approver', 'document_creator']),
        frozenset(['security_auditor', 'system_admin']),
    }

    def assign_role(self, user, role):
        proposed_roles = set(user.roles) | {role}

        for incompatible in self.INCOMPATIBLE_ROLES:
            if incompatible.issubset(proposed_roles):
                raise RoleConflictError(
                    f"Cannot assign {role}: conflicts with existing roles. "
                    f"Incompatible combination: {incompatible}"
                )

        user.roles.append(role)
        self.audit_log.record('role_assigned', user.id, role)

    def analyze_privilege_chains(self, user):
        """Detect potential privilege chaining risks"""
        warnings = []

        # Analyze transitive capabilities
        all_capabilities = set()
        for role in user.roles:
            all_capabilities.update(self.get_role_capabilities(role))

        # Check for dangerous capability combinations
        dangerous_combos = [
            ({'read_sensitive_data', 'export_data'}, 'Can exfiltrate sensitive data'),
            ({'modify_templates', 'auto_approve'}, 'Can approve own changes'),
            ({'create_users', 'assign_admin'}, 'Can create admin accounts'),
        ]

        for combo, risk in dangerous_combos:
            if combo.issubset(all_capabilities):
                warnings.append(f"Warning: {risk}")

        return warnings

The fix implements privilege incompatibility checking, dual control for sensitive actions, role conflict detection, and privilege chain analysis to prevent dangerous combinations.


Exploited in the Wild

Database Trigger Privilege Escalation (Multiple DBMS, Ongoing)

Combinations of seemingly safe database privileges like SELECT and CREATE TRIGGER have been exploited for privilege escalation. Attackers with limited query access create triggers that execute with elevated definer privileges, effectively escalating their access beyond what either privilege alone would allow.

AWS IAM Role Chaining (Cloud Environments, Ongoing)

AWS IAM role assumption chains have been exploited where users with limited roles can assume intermediate roles that can assume more privileged roles. The combination of iam:PassRole and other permissions creates escalation paths not obvious from individual privilege analysis.

Active Directory ACL Chaining (Enterprise Environments, Ongoing)

Active Directory environments have been compromised through ACL privilege chaining where users with write access to certain objects and membership in specific groups can modify security descriptors to gain domain admin access through a chain of permission manipulations.


Tools to Test/Exploit

  • BloodHound — Identifies Active Directory privilege escalation paths through permission chaining.

  • PMapper — AWS IAM analysis tool that identifies privilege chaining and escalation paths.

  • Prowler — Cloud security tool that identifies dangerous IAM privilege combinations.


CVE Examples

  • CVE-2005-1736 — Combination of debug and file access privileges allowed privilege escalation.

  • CVE-2002-1772 — Multiple privilege combination enabled unauthorized access.

  • CVE-2005-1973 — Privilege chaining in web application led to administrator access.

  • CVE-2003-0640 — Combined privileges allowed bypass of intended access restrictions.


References

  1. MITRE Corporation. "CWE-268: Privilege Chaining." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/268.html

  2. OWASP Foundation. "Broken Access Control." OWASP Top 10. https://owasp.org/Top10/A01_2021-Broken_Access_Control/

  3. NIST. "Role-Based Access Control." NIST RBAC. https://csrc.nist.gov/projects/role-based-access-control