Password Spraying Azure and O365

A go-to technique for both red teamers and APTs alike is password spraying. It can be particularly effective again Azure and O365 accounts. Especially when MFA is not enabled.

In this article I’ll break down how MSOLSpray by @dafthack works and how it can be used not only for password spraying but also to gather useful information about the accounts in scope of the attack.  

You can find the tool here: https://github.com/dafthack/MSOLSpray

If you’re not familiar with what password spraying is, it’s when an attacker attempts a very limited set of passwords across all accounts. For example, the attacker will try password: Passw0rd! against all discovered accounts.

And this is what a successful password spraying against Azure Active Directory accounts using MSOLSpray looks like

You might notice something interesting here. Although the tool found the password, it was also able to identify that the password has expired.

How is that possible?

And are we able to get other juicy information about the accounts?

To understand how the tool works, let’s take a look under the hood and have a quick read through the source code. We can see that authentication attempts happen on the following URL:

https://login.microsoft.com/common/oauth2/token

This however is an API endpoint that will require properly formatted request to elicit a proper response. For this I opt to use Postman.

Reading a bit more through the tool source code, we can see the Body Parameters that go with the POST request. It includes: resource, client_id, client_info, grant_type, username, password, scope.

For this test, I minimized the request to the parameters in the screenshot below, including a description for each key. Of course, depending on the app, additional body parameters could be required when sending the request.

We can then go ahead and submit the request. If our password spray is successful, the response will be an HTTP 200.

Where it gets interesting however, is with the additional information we can get with the verbose error messages returned.

For example, we can use the same tool for username enumeration before launching the password spray attack.

If we see error code AADSTS50034, this indicates that the user doesn’t exist. And based on these responses, we could construct a list of valid usernames to attack.

Other helpful error messages could be

·       AADSTS50126: Error validating credentials due to invalid username or password = Invalid password 

·       AADSTS50079 or AADSTS50076: MFA response 

·       AADSTS50057: Disabled account 

·       AADSTS50055: Password is expired 

 As we can see, password spraying is an effective technique not just for password guessing, but for username enumeration, in addition to gleaning other useful information about the accounts in scope for attack.

Needless to say, never perform such activity without proper authorization and always be careful of account lockouts.