MCADDF

[IOT-EDGE-002]: Azure IoT Hub Connection String Theft

Metadata

Attribute Details
Technique ID IOT-EDGE-002
MITRE ATT&CK v18.1 T1552.001 - Unsecured Credentials: Credentials in Files
Tactic Credential Access
Platforms Azure IoT Hub, Azure IoT Edge, M365, Containers
Severity Critical
Technique Status ACTIVE
Last Verified 2026-01-10
Affected Versions Azure IoT Hub (all versions), Azure IoT Edge 1.0+, Azure SDK 2.0+
Patched In N/A (Design issue, requires secure credential management)
Author SERVTEPArtur Pchelnikau

1. EXECUTIVE SUMMARY

Concept: Azure IoT Hub connection strings are high-privilege credentials that grant full access to IoT devices, device twins, and message queues. These strings are frequently hardcoded in application source code, stored in unencrypted configuration files, embedded in Docker images, or left in environment variables. Attackers who extract connection strings gain the ability to authenticate to Azure IoT Hub as the legitimate owner, read all device telemetry, modify device configurations, send cloud-to-device commands, and establish persistent access. Connection strings often contain Shared Access Keys valid for years, making them extremely valuable targets.

Attack Surface: Configuration files (appsettings.json, web.config, .env, terraform files), Docker image layers, Git repositories, CI/CD pipeline logs, environment variables in container runtimes, and application binaries (embedded via compiler optimizations).

Business Impact: Complete Compromise of IoT Infrastructure. Stolen connection strings grant unauthorized parties the ability to spoof legitimate devices, inject false sensor data, disable legitimate devices, and exfiltrate confidential telemetry data. In critical infrastructure (utilities, healthcare, manufacturing), this can lead to operational disruption, data breaches, and loss of customer trust.

Technical Context: Connection strings follow the pattern HostName=<hub>.azure-devices.net;SharedAccessKeyName=<key-name>;SharedAccessKey=<base64-key>. Extraction typically takes <5 minutes if credentials are in plaintext. Detection likelihood is Low if Git history is not monitored and High if Azure Activity Logs are configured for connection string pattern detection.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark CIS Azure Foundations Benchmark 2.3 Credentials must not be hardcoded in code repositories
DISA STIG AP-2.a Ensure cryptographic mechanisms are used to protect sensitive data
CISA SCuBA ID.BE-1 Organizational risk management strategy must address credential storage
NIST 800-53 SA-3 (System Development Life Cycle), SC-7 (Boundary Protection) Secure credential management throughout development lifecycle
GDPR Art. 25 (Data Protection by Design) Credentials must be protected by default
DORA Art. 11 Critical incidents from credential theft must be reported
NIS2 Art. 21 Credential theft is a reportable cybersecurity incident
ISO 27001 A.6.2.1 (Personnel screening), A.8.2.4 (User responsibilities) Developers must follow secure credential practices
ISO 27005 Risk assessment for credential theft Identify and mitigate risks from hardcoded credentials

2. TECHNICAL PREREQUISITES

Supported Versions:

Tools:


3. ENVIRONMENTAL RECONNAISSANCE

Management Station / PowerShell Reconnaissance

# Search for connection strings in Azure Key Vault (if available)
az keyvault secret list --vault-name myKeyVault --query "[].{name:name, id:id}"

# Retrieve all IoT Hub connection strings (requires IoT Hub Owner role)
az iot hub connection-string show --hub-name myIoTHub

# Check for connection strings in application configuration
Get-Content "C:\app\appsettings.json" | Select-String -Pattern "HostName" | Select-Object Line

What to Look For:

Linux/Bash / CLI Reconnaissance

# Search for connection strings in common code locations
grep -r "HostName.*azure-devices.net" /home /opt /var/www 2>/dev/null | head -10

# Search Git history for connection strings
cd /path/to/repo && git log -p --all -S "SharedAccessKey" | grep -B 2 -A 2 "SharedAccessKey"

# Check environment variables
env | grep -i "connection\|iot\|azure"

# Search Docker compose files and Dockerfiles
find . -name "docker-compose.yml" -o -name "Dockerfile" | xargs grep -i "HostName\|SharedAccessKey"

What to Look For:


4. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Extracting Connection Strings from Git History

Supported Versions: Git 2.0+, all code repositories

Step 1: Clone or Access Target Repository

Objective: Gain access to the Git repository containing IoT Hub configuration

Command:

# Clone the repository (if attacker has read access)
git clone https://github.com/target/iot-app.git
cd iot-app

Expected Output:

Cloning into 'iot-app'...
remote: Counting objects: 1234, done.
remote: Compressing objects: 100% (567/567), done.
remote: Receiving objects: 100% (1234/1234), 123.45 MiB | 5.67 MiB/s
Unpacking objects: 100% (1234/1234), done.

What This Means:

Step 2: Search Git History for Connection Strings

Objective: Identify commits containing Azure IoT Hub connection strings

Command:

git log -p --all -S "HostName" | grep -B 5 -A 5 "SharedAccessKey"

Expected Output:

commit abc123def456
Author: Developer <dev@example.com>
Date:   2024-12-15 10:30:00 +0000

    Update IoT Hub configuration

- "ConnectionString": "HostName=myhub.azure-devices.net;SharedAccessKeyName=owner;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdefgh="

What This Means:

OpSec & Evasion:

Troubleshooting:

References & Proofs:

Step 3: Extract and Parse Connection String

Objective: Parse the connection string to identify individual credential components

Command:

# Extract the full connection string from git log
CONNECTION_STRING=$(git log -p --all -S "HostName" | grep "SharedAccessKey" | head -1 | sed 's/.*HostName/HostName/' | sed 's/".*//g')
echo "$CONNECTION_STRING"

# Parse individual components
IFS=';' read -ra PARTS <<< "$CONNECTION_STRING"
for part in "${PARTS[@]}"; do
  echo "$part"
done

Expected Output:

HostName=myhub.azure-devices.net;SharedAccessKeyName=owner;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdefgh=
HostName=myhub.azure-devices.net
SharedAccessKeyName=owner
SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdefgh=

What This Means:

References & Proofs:

METHOD 2: Extracting Connection Strings from Configuration Files

Supported Versions: All versions

Step 1: Identify Configuration Files

Objective: Locate configuration files that may contain connection strings

Command:

find . -name "appsettings.json" -o -name "web.config" -o -name ".env" -o -name "*.conf" | head -20

Expected Output:

./appsettings.json
./appsettings.Development.json
./src/config/.env
./docker-compose.yml

What This Means:

Step 2: Search for Connection Strings

Command:

# Search JSON files
jq '.["ConnectionStrings"]["IoTHub"]' appsettings.json

# Search .env files
grep "IOT_HUB_CONNECTION_STRING\|HostName" .env

# Search web.config
grep -i "connectionstring" web.config

Expected Output:

"HostName=myhub.azure-devices.net;SharedAccessKeyName=owner;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdefgh="

References & Proofs:

METHOD 3: Extracting Connection Strings from Docker Images

Supported Versions: Docker 18.0+

Step 1: Export Docker Image

Objective: Extract Docker image layers to analyze for connection strings

Command:

# Save image to tar file
docker save myregistry.azurecr.io/iot-app:latest -o iot-app.tar

# Extract layers
tar -xf iot-app.tar -C extracted-layers/

Expected Output:

extracted-layers/
├── blobs/
│   └── sha256/
│       ├── abc123... (base OS layer)
│       ├── def456... (dependencies layer)
│       └── ghi789... (application layer)
└── manifest.json

Step 2: Search Layers for Connection Strings

Command:

# Extract and search all layers
for layer in extracted-layers/blobs/sha256/*; do
  tar -xf "$layer" -O 2>/dev/null | strings | grep -i "HostName.*azure-devices"
done

Expected Output:

HostName=myhub.azure-devices.net;SharedAccessKeyName=owner;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz1234567890abcdefgh=

References & Proofs:


5. ATTACK SIMULATION & VERIFICATION

Atomic Red Team

Reference: Atomic Red Team T1552.001


6. TOOLS & COMMANDS REFERENCE

TruffleHog (Secrets Scanner)

Version: 3.0+ Minimum Version: 2.0 Supported Platforms: Linux, Windows, macOS

Installation:

pip install truffleHog

Usage:

# Scan Git repository for secrets
truffleHog git https://github.com/target/repo.git

# Scan local filesystem
truffleHog filesystem /path/to/code

# Scan with custom regex for IoT Hub connection strings
truffleHog filesystem /path/to/code --regex "HostName=.*SharedAccessKey=.*"

Grep + Sed Pipeline

Native Tools

Usage:

# Search for IoT Hub connection strings
grep -r "HostName.*azure-devices" /path/to/code

# Extract just the SharedAccessKey
grep -oP 'SharedAccessKey=\K[^=]*' config.json

7. MICROSOFT SENTINEL DETECTION

Query 1: Detect Connection String Access in Audit Logs

Rule Configuration:

KQL Query:

AuditLogs
| where OperationName in ("Get IoT Hub ConnectionString", "List IoT Hub Keys", "Regenerate IoT Hub Key")
| where Result == "Success"
| summarize Count = count() by InitiatedBy.user.userPrincipalName, OperationName, TimeGenerated
| where Count > 0
| sort by TimeGenerated desc

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select your workspace → Analytics+ CreateScheduled query rule
  3. General Tab:
    • Name: Detect IoT Hub Connection String Theft
    • Severity: High
  4. Set rule logic Tab:
    • Paste the KQL query above
    • Run query every: 15 minutes
    • Lookup data from the last: 1 hour
  5. Incident settings Tab:
    • Enable Create incidents
  6. Click Review + createCreate

Query 2: Detect Git Repository Access for Secrets

KQL Query:

AuditLogs
| where OperationName == "Get git log" or OperationName == "Clone repository"
| where UserType == "User"
| summarize AccessCount = count() by UserPrincipalName, OperationName, TimeGenerated
| where AccessCount > 3

8. WINDOWS EVENT LOG MONITORING

Event ID: 4662 (An operation was performed on an object)

Manual Configuration Steps (Group Policy):

  1. Open Group Policy Management Console (gpmc.msc)
  2. Navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsAdvanced Audit Policy Configuration
  3. Enable: Audit Object Access
  4. Set to: Success and Failure
  5. Run gpupdate /force

9. SYSMON DETECTION PATTERNS

Minimum Sysmon Version: 13.0+ Supported Platforms: Linux (auditbeat), Windows

Sysmon Config Snippet:

<Sysmon schemaversion="4.30">
  <EventFiltering>
    <!-- Detect git log commands searching for secrets -->
    <ProcessCreate onmatch="include">
      <CommandLine condition="contains">git log -p</CommandLine>
      <CommandLine condition="contains">SharedAccessKey</CommandLine>
      <CommandLine condition="contains">HostName</CommandLine>
    </ProcessCreate>
    
    <!-- Detect grep on config files -->
    <ProcessCreate onmatch="include">
      <Image condition="contains">grep</Image>
      <CommandLine condition="contains">appsettings.json</CommandLine>
      <CommandLine condition="contains">.env</CommandLine>
    </ProcessCreate>
    
    <!-- Detect Docker save operations -->
    <ProcessCreate onmatch="include">
      <Image condition="contains">docker</Image>
      <CommandLine condition="contains">save</CommandLine>
    </ProcessCreate>
  </EventFiltering>
</Sysmon>

10. MICROSOFT DEFENDER FOR CLOUD

Detection Alert: Credentials Detected in Code Repository

Alert Name: Sensitive Credentials Found in Code Repository

Manual Configuration Steps:

  1. Navigate to Azure PortalMicrosoft Defender for Cloud
  2. Go to DevOps Security (if available)
  3. Select repository → Scan Results
  4. Filter by severity: Critical
  5. Identify detected connection strings
  6. Take immediate action: Rotate the key in IoT Hub

11. MICROSOFT PURVIEW (UNIFIED AUDIT LOG)

Query: Monitor Azure IoT Hub Key Retrieval

Search-UnifiedAuditLog -Operations "Get Azure IoT Hub Key", "Generate SAS Token" `
  -StartDate (Get-Date).AddDays(-7) `
  -ResultSize 5000 | Select-Object UserIds, Operations, CreationDate, ClientIP, RecordType | Sort-Object CreationDate -Descending

Manual Configuration Steps:

  1. Navigate to Microsoft Purview Compliance Portal (compliance.microsoft.com)
  2. Go to AuditSearch
  3. Set Date range and filter by Operations: Get Azure IoT Hub Key
  4. Review results for unauthorized access
  5. Export: ExportDownload all resultsaudit-log.csv

12. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH

Access Control & Policy Hardening

Validation Command (Verify Fix)

# Verify no connection strings in Git history
git log -p --all | grep -c "SharedAccessKey"
# Expected Output: 0 (no matches)

# Verify Key Vault contains the connection string
az keyvault secret show --vault-name myKeyVault --name "iot-hub-connection-string" --query "value"
# Expected Output: <connection-string-value>

# Verify application uses Key Vault reference
grep -r "DefaultAzureCredential\|@Microsoft.KeyVault" src/
# Expected Output: References to secure credential retrieval

What to Look For:


13. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

  1. Isolate:
    # Regenerate IoT Hub keys immediately
    az iot hub policy key renew --hub-name myIoTHub --policy-name "owner" --regen-primary
       
    # Revoke all devices (if compromise is widespread)
    az iot hub device-identity delete --hub-name myIoTHub --device-id "*"  # Use with caution
    
  2. Collect Evidence:
    # Export Azure Activity Log
    az monitor activity-log list --resource-group myResourceGroup --output json > activity-log.json
       
    # Export Git history
    git log -p --all > git-history.txt
       
    # Export Key Vault audit logs
    az monitor log-analytics query --workspace myWorkspace --analytics-query "AuditLogs | where OperationName contains 'IoT' | top 1000 by TimeGenerated"
    
  3. Remediate:
    # Rotate key in Key Vault
    $newKey = "$(az iot hub policy show --hub-name myIoTHub --name owner --query primaryKey -o tsv)"
    az keyvault secret set --vault-name myKeyVault --name iot-hub-connection-string --value $newKey
       
    # Restart all applications to reload new key
    # (application-specific restart commands)
    

Step Phase Technique Description
1 Initial Access [IOT-EDGE-002] Attacker extracts Azure IoT Hub connection string
2 Credential Access [IOT-EDGE-001] IoT Device Credential Extraction Attacker uses connection string to enumerate device credentials
3 Lateral Movement [IOT-EDGE-004] Device Provisioning Service Abuse Attacker registers rogue devices using stolen connection string
4 Persistence [IOT-EDGE-003] Edge Module Compromise Attacker deploys malicious modules to IoT Hub
5 Impact Data Exfiltration Attacker exfiltrates telemetry data from all devices

15. REAL-WORLD EXAMPLES

Example 1: Exposed Azure Storage Connection Strings in GitHub (2021)

Example 2: Azure DevOps Pipeline Secret Exposure (2023)


SUMMARY

IOT-EDGE-002 represents a critical and pervasive vulnerability in IoT application development. Connection strings are frequently mishandled, exposed in code repositories, hardcoded in applications, and embedded in Docker images. Organizations must implement secret management solutions (Key Vault, managed identities), automated secret scanning, and secure development practices to defend against this threat. Regular audits of codebases and remediation of exposed credentials are essential.