Skip to content

Latest commit

 

History

History
296 lines (217 loc) · 14.7 KB

readme.md

File metadata and controls

296 lines (217 loc) · 14.7 KB

This tool is not maintained anymore, please consider using https://github.com/jsa2/AADAppAudit

License

READ HERE


⚠ Only use this tool if you know what you are doing and have reviewed the code

⚠ Always test the tool first in test environments, with non-sensitive data


As the licenses says, 0% Liability 0% Warranty


This tool is not maintained anymore, please consider using https://github.com/jsa2/AADAppAudit

Consent and Azure AD application Analytics solution

This tool is not maintained anymore, please consider using https://github.com/jsa2/AADAppAudit

Azure AD consent framework analysis is important step to strengthen security posture in every organization that is using Azure Active Directory. This tool was initially developed to analyze possible illicit consent grant attacks & in help of analyzing Azure AD consent grant framework but has been developed further since to provide answers to the most typical security related questions around Azure AD integrated apps and permissions.

Illicit Consent Grant

During Covid-19 there has been huge increase in consent phishing emails where the idea is to abuse OAuth request links to trick recipients into granting attacker owned apps permission to access sensitive data. Consent grant is perfect tool to create backdoor, and MFA bypasses in the victim’s environment. After the illicit application has been granted consent, it has account-level access to data without the need for an organizational account.

There are two scenarios for attacker to pursue targeting individual users:

Use cases

Use Case Name Notes
✅ Inventory of apps and permissions All Azure AD apps and the apps registered permissions including Workload Identities
✅ Detect applications that share app and user permissions / scopes By default Apps that have delegated permissions should not include Application permissions
✅ Detect password use on applications, and expiring/expired passwords Two types of credentials available: password-based or certificate-based authentication
✅ Detect AppType (Managed, Multi, single etc) Tenancy in Azure AD
✅ Review replyURLs Verify are there any malicious reply URLs used in the apps
✅ Detect recent sign-ins Get insights on how apps are used in the organization (this API is setting not enabled by default)
✅ Detect servicePrincipals in admin roles It is in most cases recommended to use API permissions instead of AAD roles
✅ Detect dangling redirect_uri If the app service is deleted, but redirect_uri is not deleted from the Azure AD app registration, attacker could register the App Service instance for malicious intent.
✅ User assignment review if app has user assigment enabled
✅ HasPublicClient review if app allows public client flows (non redirect uri based flows)
✅ WarningAppPrivs is multitenant application with app permissions
this permission type is very potent for the attacker, because the app owner does not needed signed-in user content (delegation) in the victim tenant to access services granted to the app
✅ expiration Detect SAML certificate and client credential
✅ Owners review app owners
✅ audit app proxy applications this one requires further permissions:
microsoft.directory/connectors/allProperties/read - Read all properties of application proxy connectors
✅Check permissionless use of possibly malicious multitenant ServicePrincipals Check permissionless use of possibly malicious multitenant ServicePrincipals
✅ Check for plaintext redirectURI's Check for plaintext redirectURI's

./Pictures/Results-2-1.jpg

Intentional gaps

⚠️ There are also occurences where required ResourceAccess are configured on the apps, but no permissions are granted to users via user consent, or admin consent. These occurences do not show on the report. While they also have potential for abuse, they have no active permissions granted. (this does not concern app permissions)

Prerequisites

Requirement description
✅ Access to Azure Cloud Shell Bash Uses pre-existing software on Azure CLI, Node etc
✅ Permissions to Azure subscription to create needed resources Tool creates a storage account and a resource group. Possible also to use existing storage account. In both scenarios tool generates short lived read-only shared access links (SAS) for the externalData() -operator
✅ User is Azure AD member Cloud-only preferred with read-only Azure AD permissions. More permissions are needed if sign-in events are included
✅ Existing Log Analytics Workspace This is where you paste the output from this tool

About the generated KQL

  • The query is valid for 10 minutes, as SAS tokens are only generated for 10 minutes
  • If you want to regenerate the query follow these steps

Running the tool

  • Log in to Azure Cloud Shell (BASH ) and paste following line to the shell
curl -o- https://raw.githubusercontent.com/jsa2/CloudShellAadApps/public/remote.sh | bash

Once complete you should see following screen, which includes that you can paste to Log Analytics space image

After initial run with main.js

  • nvm use 14, is only needed in cloud shell
  • If you are having problems with the tool start by ensuring, that existing installation of the tool does on exist in cloudShell: admin@Azure:~$ rm CloudShellAadApps/ -r -f

without autoRun

curl -o- https://raw.githubusercontent.com/jsa2/CloudShellAadApps/public/remoteInit.sh | bash

Each of this step requires that you then copy the query kql/runtime.kql and paste it in log analytics

As pointed out earlier, these can be run, once you've run the initial run with main.js


Checking results again

cd Cloud CloudShellAadApps
nvm use 14; node main.js

Check App Proxy Apps

  • Requires further permissions like the sign-in logs query (while all other checks here work with reader)
cd Cloud CloudShellAadApps
node main --appProxyApps
nvm use 14; node schemaForAppProxyApps.js --appProxyApps

image

Check Saml App expiration

Checks for email addresses and time till SAML certificate expires.

cd Cloud CloudShellAadApps
nvm use 14; node schemaForSaml.js 

image

Use existing storage account

rg=queryStorage-23428
storageAcc=storagehowrjcehuw
git clone https://github.com/jsa2/CloudShellAadApps
cd CloudShellAadApps
az storage account show-connection-string -g $rg  -n  $storageAcc -o json  > src/config.json
npm install
nvm use 14; node main.js

Use with different context after setting up the needed storage account

az account clear
az login --use-device-code --allow-no-subscriptions

Use existing account with IP limitations

az account set --name "scan"

storageAcc=dogs
rg=queryStorage-29991
location=westeurope
net=$(curl a.dewi.red)

az storage account show-connection-string -g $rg  -n  $storageAcc -o json  > src/config.json

#Add cloud shell IP
az storage account network-rule add -g $rg --account-name $storageAcc --ip-address $net

# Remove the storage account rule for Cloud shell
az storage account network-rule remove -g $rg --account-name $storageAcc --ip-address $net

Regenerate SAS tokens for existing data

cd Cloud CloudShellAadApps
nvm use 14; node schemaForExternalData.js
code kql/runtime.kql

Alternative Sorting (per API)

cd Cloud CloudShellAadApps
nvm use 14; node schemaForAPIdriven.js 
code kql/runtime.kql

image

With SignInLogs (only shows apps that have sign-in data - requires workspace with signins)

Requires following sources (AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs, AADManagedIdentitySignInLogs, SigninLogs)

cd Cloud CloudShellAadApps
nvm use 14; node schemaForExternalDataLAsignins.js 
code kql/runtime.kql

With SignIn and auditLogs (only shows apps that have sign-in data - requires workspace with signins)

cd Cloud CloudShellAadApps
nvm use 14; node schemaForExternalDataLAsignisAndAudit.js 
code kql/runtime.kql

Check permissionless use of possibly malicious multitenant ServicePrincipals

  • Checks if possibly malicious multitenant SPN's with no app permissions present are using client credentials based flows against apps in your tenant
cd Cloud CloudShellAadApps
nvm use 14; node schemaForMaliciousMultiTenant.js
code kql/runtime.kql

Check for plaintext redirectURI's

  • append this part to runtime.kql after node schemaForExternalData.js is run
nvm use 14; node schemaForExternalData.js
code kql/runtime.kql;
final
| mv-apply url = set_replyUrls to typeof(string) on (
where (url contains "http://" and url !contains "http://localhost") 
)

image

Example of insecure non localhost redirectURI:

image

Update log

  • 19.05.2022 SAML App Expiration checking
  • 15.05.2022 added AppProxy auditing
  • 15.03.2022 added alternative sorting (per API) and with LA

Previously

⚠️ Dangling redirect URI

  • Malicious use case: If the app service is deleted, but redirect_uri is not deleted from the Azure AD app registration, attacker could register the App Service instance for malicious intent. After registering the App Service instance Attacker would then redirect user sessions authorization codes/tokens to attacker controlled service.

⚠️ Multi-tenant app with app permissions.

⚠️ Device Code Flow enabled for app that has redirect URI's

  • This enables the attacker to phish for access tokens without having control of the redirect URI as the attacker is able to set up an page asking for the device code.
    • Users are likely less susceptible to device code based phishing * compared to pure SSO based phishing with seamless redirect to attacker controlled service) - Nonetheless public client on a redirect enabled application presents a valid attack vector.

Known issues

Continous Access Evaluation

Azure CLI is unable to obtain new access tokens for sessions, that rely on IP restrictions and are targeteted by strict enforcement az account get-access-token --resource=https://graph.microsoft.com --query accessToken --output json image

Multiple tenants

If the identity you are using doesn't have Azure subscription access or has access to multiple tenants use

az login --allow-no-subscriptions ## (no access to Azure subscriptions)
az login --tenant <tenant id>  ## (If user has identity in multiple tenants)

./Pictures/Login-3.JPG