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
| Impact | Details |
|---|---|
| Access Control | Scope: 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
-
MITRE Corporation. "CWE-268: Privilege Chaining." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/268.html
-
OWASP Foundation. "Broken Access Control." OWASP Top 10. https://owasp.org/Top10/A01_2021-Broken_Access_Control/
-
NIST. "Role-Based Access Control." NIST RBAC. https://csrc.nist.gov/projects/role-based-access-control