Azure App Registrations should be anchored in production evidence, clear ownership, and a review process that survives the next infrastructure change.
What Are Azure App Registration Risks?
App registrations in Azure Entra ID allow applications to authenticate and access Microsoft Graph, Azure resources, and other APIs. They are the identity layer for every custom application, automation script, integration, and third-party SaaS tool connected to your Microsoft 365 environment.
App registrations accumulate over time just like user accounts. Shadow IT creates them without governance. Developers register apps for quick testing and never remove them. Third-party integrations request more permissions than needed. The result is an environment full of applications holding privileged access to mailboxes, SharePoint, Teams data, and Azure resources — often with credentials (client secrets) that never expire and no one monitors.
Compromising an app registration with high Microsoft Graph permissions is equivalent to compromising a privileged user account — often with fewer detection signals.
How It Works
App registrations authenticate to Entra ID using one of two methods:
- Client secrets — passwords for the app, often with long expiry dates or no expiry
- Certificates — X.509 certificates used for app authentication
Once authenticated, the app acts according to its API permissions. Two permission types exist:
- Delegated permissions — app acts on behalf of a signed-in user
- Application permissions — app acts as itself, without a user context
Application permissions are the dangerous ones. An app with Mail.ReadWrite application permission can read and write every mailbox in the tenant without any user interaction. An app with Directory.ReadWrite.All can modify any object in Entra ID — including creating new admin accounts.
When these permissions are granted to poorly secured or forgotten app registrations, attackers who obtain the client secret gain persistent, privileged API access to the entire tenant.
The Attack Chain
Step 1 - Enumerate App Registrations and Permissions
Connect-MgGraph -Scopes "Application.Read.All"
# List all app registrations with their permissions
Get-MgApplication | ForEach-Object {
$app = $_
$sp = Get-MgServicePrincipal -Filter "appId eq '$($app.AppId)'"
$appRoles = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.Id
[PSCustomObject]@{
AppName = $app.DisplayName
AppId = $app.AppId
Created = $app.CreatedDateTime
SecretExpiry = ($app.PasswordCredentials | Sort-Object EndDateTime | Select-Object -Last 1).EndDateTime
Permissions = ($appRoles.AppRoleId | ForEach-Object { $_.ToString() }) -join ", "
}
} | Where-Object {$_.Permissions -ne ""}
Step 2 - Target Apps With High Permissions and Weak Secrets
Priority targets:
- Apps with
Mail.ReadWrite,Files.ReadWrite.All, orDirectory.ReadWrite.Allapplication permissions - Apps with client secrets expiring in years or never
- Apps with secrets that have not been rotated in 12+ months
Step 3 - Extract or Brute-Force Client Secret
Client secrets are often stored insecurely — in code repositories, CI/CD pipelines, configuration files, or developer machines. Attackers scan GitHub and public repos for leaked Azure app credentials.
# Scan GitHub for leaked Azure client secrets
# Pattern: "client_secret" + Azure tenant domain in same file
# Tools: truffleHog, git-secrets, GitHub Advanced Security
Step 4 - Authenticate as the App and Exfiltrate
import msal
app = msal.ConfidentialClientApplication(
client_id="APP_CLIENT_ID",
client_credential="STOLEN_SECRET",
authority="https://login.microsoftonline.com/TENANT_ID"
)
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
token = result["access_token"]
# With Mail.ReadWrite.All — dump all mailboxes
import requests
r = requests.get("https://graph.microsoft.com/v1.0/users", headers={"Authorization": f"Bearer {token}"})
Detection
Microsoft Entra Audit Logs
| Event | What to Look For |
|---|---|
| Add application | New app registrations — especially outside change windows |
| Add password credential | New client secret added to existing app |
| Add service principal | New enterprise app added to tenant |
| Consent to application | User or admin consent to third-party app permissions |
SIEM Detection Query (Elastic KQL)
azure.auditlogs.operation_name: "Add password credential to service principal" AND
NOT azure.auditlogs.properties.initiated_by.user.roles: "*Admin*"
# Detect app authentication from unusual IPs
azure.signinlogs.properties.app_display_name: (* AND NOT "Microsoft*") AND
azure.signinlogs.properties.user_type: "servicePrincipal" AND
azure.signinlogs.properties.risk_level_during_sign_in: ("high" OR "medium")
💡 Tip: Enable Microsoft Graph activity logs and route them to your SIEM. App-based API access — especially bulk mailbox reads or user enumeration — is a strong data exfiltration indicator.
Remediation
💡 Quick Win: Run the PowerShell audit above and identify any app with Directory.ReadWrite.All or Mail.ReadWrite application permissions. Each one is a potential full-tenant compromise vector.
1. Audit and Remove Unused App Registrations
# Find apps with no sign-in activity in 90+ days
$cutoff = (Get-Date).AddDays(-90)
Get-MgApplication | Where-Object {$_.CreatedDateTime -lt $cutoff} | ForEach-Object {
$sp = Get-MgServicePrincipal -Filter "appId eq '$($_.AppId)'"
$lastSignIn = (Get-MgServicePrincipalSignInActivity -ServicePrincipalId $sp.Id).LastSignInDateTime
if ($lastSignIn -lt $cutoff -or $lastSignIn -eq $null) {
[PSCustomObject]@{App=$_.DisplayName; LastSignIn=$lastSignIn}
}
}
2. Rotate Expiring and Old Client Secrets
# Find client secrets expiring within 30 days or already expired
Get-MgApplication | ForEach-Object {
$_.PasswordCredentials | Where-Object {$_.EndDateTime -lt (Get-Date).AddDays(30)} |
Select-Object @{N="App";E={$_.DisplayName}}, EndDateTime
}
# Rotate via: Add-MgApplicationPassword / Remove-MgApplicationPassword
3. Replace Secrets With Certificates
Client secrets are more easily leaked than certificates. Migrate high-privilege apps to certificate-based authentication:
# Generate a self-signed certificate
$cert = New-SelfSignedCertificate -Subject "CN=AppName" -CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy Exportable -KeySpec Signature -NotAfter (Get-Date).AddYears(2)
# Upload certificate to app registration
$certData = [Convert]::ToBase64String($cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert))
$keyCredential = @{Type="AsymmetricX509Cert"; Usage="Verify"; Key=[Convert]::FromBase64String($certData)}
Update-MgApplication -ApplicationId $appId -KeyCredentials @($keyCredential)
4. Apply Least Privilege to App Permissions
Review every app registration and replace broad permissions with scoped alternatives:
- Replace
Mail.ReadWritewithMail.Readif write is not needed - Replace
Directory.ReadWrite.Allwith specific read permissions - Use delegated permissions instead of application permissions where user context is available
How EtcSec Detects This
EtcSec audits all app registrations and service principals in your Azure tenant.
The Applications category checks include: apps with overly broad application permissions (Directory.ReadWrite.All, Mail.ReadWrite.All, Files.ReadWrite.All), apps with expired or expiring client secrets, apps with no recent sign-in activity, and apps with admin consent granted to sensitive permissions without review.
ℹ️ Note: EtcSec audits all Azure app registrations and permissions automatically. Run a free audit to discover over-privileged and forgotten app registrations in your tenant.
Review Priorities
Azure App Registrations: The Over-Privileged Applications Hiding in Your Tenant should be handled as a real exposure inside your Entra ID and Azure tenant, not as a single isolated setting. Start by defining the review perimeter: which admins, guests, service principals, app registrations, policy exclusions, and break-glass accounts are affected, which business workflows depend on them, which privileges they expose, and which emergency exceptions were added over time. That scoping step prevents shallow remediation, because the technical symptom is often smaller than the operational blast radius. By documenting the full path from configuration to privilege, the team can prioritize changes that reduce risk quickly without breaking production access. This also creates a defensible baseline for later validation and gives leadership a clear explanation of why the issue matters now.
Adjacent Controls to Review
When attackers reach your Entra ID and Azure tenant, they rarely stop at the first weak point. Around Azure App Registrations: The Over-Privileged Applications Hiding in Your Tenant, they normally test whether the exposed path can be chained with legacy authentication, weak guest governance, broad app consent, stale emergency accounts, and roles that were never reviewed. That means defenders should review not just the headline weakness but every nearby dependency that turns access into persistence or privilege escalation. Confirm which identities, roles, permissions, and trust assumptions can be reused by a motivated operator. If a fix closes only one object while leaving adjacent privilege paths untouched, the effective risk barely changes. A disciplined review of chaining opportunities is what turns this article topic into a practical hardening exercise rather than a one-time checkbox.
Evidence and Telemetry to Pull
A strong response to Azure App Registrations: The Over-Privileged Applications Hiding in Your Tenant needs evidence that can be reviewed by both engineering and detection teams. Pull sign-in logs, audit logs, role assignment changes, consent events, application credential changes, and risky sign-in signals, compare recent changes with known maintenance windows, and isolate accounts or systems that changed behavior without a clear business reason. Use that evidence to answer three questions: when the risky path appeared, who can still use it, and whether similar exposure exists elsewhere in your Entra ID and Azure tenant. Good telemetry review also helps you separate inherited technical debt from active misuse. That distinction matters, because the remediation plan for stale misconfiguration is different from the plan for a path that already shows attacker-like activity or repeated policy exceptions.
Adjacent Weaknesses Worth Reviewing
Very few environments contain Azure App Registrations: The Over-Privileged Applications Hiding in Your Tenant alone. In practice, the same tenant or directory segment often contains legacy authentication, weak guest governance, broad app consent, stale emergency accounts, and roles that were never reviewed, and those neighboring weaknesses decide whether the issue is merely noisy or truly critical. Review shared owners, inherited permissions, duplicated exceptions, and long-lived administrative shortcuts. Check whether the same team approved similar risky patterns in multiple places, because repeated decisions usually point to a process gap rather than a single technical bug. This broader review prevents partial cleanup and gives you a better chance of removing the entire attack path. It also improves audit readiness, because the final state is easier to explain and easier to monitor over time.
Remediation Order That Lowers Risk Fast
For Azure App Registrations: The Over-Privileged Applications Hiding in Your Tenant, remediation should follow an order that reduces exposure before it chases perfection. First remove the easiest privilege expansion paths, then lock down the highest-value identities or objects, and only after that clean up secondary hygiene gaps. Use Conditional Access, PIM, least privilege, access reviews, application ownership checks, approval workflows, and strong MFA as the control set that defines the target state. Each change should have an owner, a rollback note, and a validation step. This prevents long projects from stalling after the first technical fix. If a full redesign is not immediately possible, document interim controls that reduce abuse potential today and schedule the structural work inside the next weekly operational review and monthly hardening review. The important point is measurable risk reduction, not cosmetic compliance.
Azure App Registrations: Validation Before Sign-Off
A strong review of Azure App Registrations should end with production evidence, not with an assumption that the risky path disappeared. Before you close the finding, recheck role assignments, policy scope, app permissions, or guest settings, sign-in, audit, or risk evidence from the real tenant, and the exception path that could silently recreate the exposure. Confirm that the safer state applies to the scope that actually matters: the production OU, the effective role assignment, the application path, or the trust and delegation path an attacker would really abuse. Record the technical owner, the business dependency, and the rollback condition so the next review can tell whether the safer state was maintained.
Use a short sign-off checklist:
- verify the risky state is gone from the attacker's point of view, not only from an admin screenshot
- keep one before/after export or log sample that proves the affected scope changed
- document the owner and the exception decision if the control could not be fully enforced
For adjacent exposure, cross-check the result with AD and Azure Compliance: NIS2, ISO 27001, CIS Controls, Stale Privileged Accounts: Hidden Risk in Active Directory, Azure Privileged Access: Too Many Global Admins, and GPO Misconfigurations: How Group Policy Becomes an Attack Vector. The same control gap often reappears in nearby identity paths, logging gaps, or delegated permissions, which is why the final validation step matters as much as the initial finding.
Azure App Registrations: Evidence to Keep for the Next Review Cycle
The next reviewer should not have to rebuild the case from memory. Keep the evidence that originally justified the finding, the proof that the change was applied, and the note that explains why the final state is acceptable. For this topic, the most useful evidence usually combines the tenant export or screenshot that shows the affected scope, the sign-in, audit, or policy evidence proving the control now applies, and the owner, approval, and exception note for the final state. That compact pack makes quarterly or post-change reviews much faster and helps explain whether the issue was removed, reduced, or formally accepted.
| Keep | Why it matters |
|---|---|
| Tenant scope and assignment evidence | Shows the affected scope and the objects that changed |
| Sign-in, audit, or policy proof | Proves the control was applied in production |
| Owner, approval, and exception record | Preserves ownership and the business rationale |
If a later admin, policy, or application change reopens the path, this historical evidence also makes it easier to prove what drifted. That is what turns Azure App Registrations from a one-time check into a repeatable assurance process.
Related Reading
Review this topic together with Azure Tenant Hardening: Fix Insecure Default Settings, Azure Privileged Access: Too Many Global Admins, Azure Conditional Access: MFA Bypass With Stolen Passwords, Azure Guest Accounts: The Forgotten Attack Surface in Your Tenant, and Azure Identity Protection: Blocking Leaked Credentials. Those adjacent posts show how the same identity weaknesses usually chain together in a real assessment instead of appearing as isolated findings.
- Azure Tenant Hardening: Fix Insecure Default Settings
- Azure Privileged Access: Too Many Global Admins
- Azure Conditional Access: MFA Bypass With Stolen Passwords
- Azure Guest Accounts: The Forgotten Attack Surface in Your Tenant
- Azure Identity Protection: Blocking Leaked Credentials
Using those references keeps the remediation discussion focused on the full attack path rather than a single control gap.
Review Owners, Consent Paths, and Exceptions
Hardening app registrations requires more than deleting a few risky permissions. Teams should confirm who can create new applications, who can grant tenant-wide consent, how privileged permissions are reviewed before approval, and how inactive or abandoned apps are retired. Those governance decisions are usually what determines whether over-privileged applications disappear for good or quietly return through the next project team.



