The current state of password spraying Office 365 accounts could benefit from new approaches to bypassing Azure AD conditional access policies and other techniques that make it difficult to detect password spraying techniques. Built with Python 3 using Microsoft's Authentication Library (MSAL), Spray365 makes password spraying more effective by identifying insecure conditional access policies and allows for randomized password spraying operations that are resilient to network failures. Spray365 is easy to use and is extendable by generating "execution plans" with third party tooling.
It's no secret that attackers look to gain their initial foothold on networks by gaining authenticated access to poorly protected accounts. One way they often accomplish this is by "spraying" or guessing common passwords against user accounts. In fact, a recent post by Microsoft's Detection and Response Team (DART) indicates that attackers are increasingly relying on password spraying to gain an "initial foothold" on victim networks. Historically these attacks have been most effective when they are performed using a "low and slow" approach where few passwords are tried for many user accounts.
Password Spraying: Identifying Target Users
However, launching even the most basic password spraying attack takes work. The first step is usually building a list of target user accounts. Perhaps the simplest approach leverages the often predictable format of usernames (e.g., firstname.lastname, <firstname-initial>lastname) to generate likely combinations using the most common first names and surnames. Those who prefer a more surgical approach may scrape employee details from company directories, search engines (see theHarvester), third-party services like LinkedIn (see LinkedInt) or from metadata associated with documents indexed on search engines (see Pymeta). Once a list of target users is identified, the noise of the forthcoming password spraying attack can be reduced by validating the list of usernames using a well-known user enumeration issue in Office 365. Interestingly enough, Microsoft doesn't consider techniques "used to enumerate or confirm the existence of users or tenants" a vulnerability (see Out of Scope Submissions and Vulnerabilities in their bounty guidelines for Microsoft Online Services).
Password Spraying: Building a Password List
After building a list of target users (and optionally, validating them), a list of passwords (or a single password) is usually selected from credentials leaked in public data breaches. According to NordPass' 2020 analysis of public breach data containing over 275 million passwords, the top 200 worst passwords include "123456", "password", and "welcome". Attackers often use these bad passwords in their initial password list, and later augment it with company-specific passwords like "CompanyName123", or seasonal passwords like "Fall2021!". As a side note: it's astonishing how often we see user accounts configured with seasonal passwords or default passwords like "Welcome2021", which is why we recommend that security administrators consider configuring Azure AD with a custom list of banned passwords to restrict users from choosing these weak passwords.
Password Spraying: Some Challenges
With a list of usernames and passwords in hand, the password spraying attack is ready. However, many Office 365 tenants are configured with additional protection that reduces the effectivity of password spraying attacks. Since late 2018, Microsoft has provided users of their Azure AD and ADFS services the ability to detect and prevent password spraying attacks through their "Smart Lockout" technology. While Microsoft doesn't disclose all the technical inter-workings of this technology, they do mention that it tracks login attempts by user account across all their data centers. It also considers the location of these attempts to determine whether the authentication attempt was made by a genuine user based on their sign-in history. In addition, Azure AD has supported "Conditional Access" since late 2016. In their simplest form, conditional access "policies" can be configured to restrict access to apps and other resources based on user and device status. Device "user agents" are one common (and insecure) way that Microsoft supports restricting access to certain resources based on device type. Several years after their initial release, Microsoft extended conditional access to support Office 365 apps, which allows for greater control over information protection. While the relevance of Office 365 to penetration testing should be left for a different post, encountering restrictive conditional access policies is becoming increasingly common, which often prevents attackers from accessing valuable Azure AD-federated resources like Outlook, OneDrive or SharePoint Online.
Password Spraying: A New Approach
So far in this post we've discussed how to prepare a password spraying attack and what defensive measures may attempt to limit the scope of compromise. However, we haven't discussed how we can use this knowledge to effectively execute a password spraying operation. Many of the existing Office 365 password spraying tools are becoming less effective (even when configured with modest spraying throughput) and are more prone to reporting false-positive account lockouts (Microsoft's default response when they detect password spraying). Not only is this frustrating, but it also could lead to inaccurate password spraying results that may make it more difficult to identify weak credentials that could be used to remotely compromise an Active Directory network. Having recognized this problem, we developed a new password spraying tool that addresses many of the pain points in the existing Office 365 password spraying tools.
Spray 365: Introduction and Usage
Built with Python 3 using the Microsoft Authentication Library (MSAL), Spray365 helps penetration testers and network defenders alike run effective password spraying operations. Spray365 is highly configurable, and its two-step password spraying approach allows for predictable and resilient password spraying not found in any of the other open source spraying tools available today. Spray365's "generate" mode accepts a list of usernames, passwords, a target domain, and other optional parameters, and outputs an "execution plan". At a high level, an execution plan is a simple JSON structure that represents each planned authentication attempt. While the default values for Spray365-generated execution plans are a great start, users can customize the following additional generate-mode options:
- Delay: time in seconds to wait after an authentication attempt before spraying the next credential
- Azure AD Client ID: Self-reported client identifier sent during the authentication workflow (useful for identifying some insecure conditional access policies that allow access to certain clients)
- Azure AD Endpoint ID: Self-reported resource the user is trying to access after the authentication workflow (useful for identifying some insecure conditional access policies that allow access to certain resources)
- Shuffle Authentication Order Flag: Instructs Spray365 to generate an execution plan where the order of usernames and passwords are randomized. Users should note that this option may reduce the time of successive authentication attempts for a given user to "delay" seconds apart (back-to-back authentication attempts). Consider specifying a value for the minimum credential loop delay parameter to enforce a minimum duration that should elapse before consecutive authentication attempts for a given user are permitted
- Shuffle Authentication Order Attempts: Number of possible execution plans to generate before identifying the fastest one. When the shuffle authentication order flag is enabled and a minimum credential loop delay value is provided, Spray365 by default will generate 10 possible execution plans and pick the fastest one. This is useful because shuffling the order of authentication attempts with a minimum delay constraint requires Spray365 to introduce additional delays in the execution plan. This non-deterministic behavior makes some execution plans faster than others, and spending some additional processing time upfront often results in Spray365 identifying an optimal an execution plan with fewer delays that will save time during the spraying operation
- Minimum Credential Loop Delay: Time in seconds that should elapse before consecutive authentication attempts for a given user should occur. See more about how this value affects password spraying in the previous two parameters
- Custom User Agent: Mutually exclusive to Randomize User Agent Flag that forces a specific user agent to be sent during the authentication workflow (useful for bypassing some insecure conditional access policies that restrict access to some user agents)
- Randomize User Agent Flag: Mutually exclusive to Custom User Agent that instructs Spray365 to present a random user agent during the authentication workflow
Users can optionally develop their own tooling (or customize Spray365) to build execution plans that meet their specific needs as long as their output is compatible with Spray365's execution plan JSON structure.
Once an execution plan is created, users can prepare to launch the password spraying attack using Spray365's "spray" mode. This mode expects an execution plan file and supports a few optional parameters:
- Lockout Threshold: number of lockout responses to observe before aborting the password spray
- Proxy: HTTP/HTTPS proxy address (scheme://address:port) that will be used when making requests with MSAL. See below for more on how this value is useful.
- Resume Index: Optional value that can be used to start spraying an execution plan from a specific position (useful for restarting a password spraying operation after it is interrupted)
With these options in mind, let's try give Spray365 a try! Before password spraying, remember that attacking targets without mutual consent is illegal, and may violate service terms or acceptable use policies. It is the end user's responsibility to make sure they are not violating any laws or agreements.
Spray 365: Password Spraying Office 365
- Build a list of usernames (see Password Spraying: Identifying Target Users above) Figure 1: Building a List of Usernames
- Build a list of passwords (see Password Spraying: Building a Password List above) Figure 2: Building a List of Passwords
- Generate an Execution Plan with Spray365 Figure 3: Generating an Execution Plan
- Review the Execution Plan Figure 4: Reviewing the Execution Plan
- Spray the execution plan using Spray365! Figure 5: Password Spraying Office 365 from a Spray365 Execution Plan
- Review the Spray365 results Figure 6: Reviewing Spray365 Password Spraying Results
Spray 365: Using a Proxy to Rotate Source IP Addresses
Spraying credentials against Office 365 without implementing countermeasures such as those found in Spray365 often results in a high number of false positives of account lockouts. While it is likely that Azure AD / ADFS's Smart Lockout likely contributes to this additional protection, it is possible that Microsoft has some other logic that detects brute force authentication attempts originating from a single IP address.
Many talented folks have written about how Amazon AWS API gateways can be used to randomize source IP addresses on a per-request basis, so we won't go over those details here. However, it is worth noting that Spray365 supports proxying over HTTP/HTTPS out of the box! One of the easier ways to integrate behavior that rotates source IP addresses on a per-request basis involves using Burp Suite and the IP Rotate extension with Spray365. The IP Rotate extension integrates Amazon's AWS API Gateway resources in Burp Suite to transparently proxy requests made to "login.microsoftonline.com" over API gateways located in several AWS regions. Setup is simple, and only requires six steps:
- Locate (or create) an IAM user account with the "AmazonAPIGatewayAdministrator" permission policy. Figure 7: Locating an AWS IAM User with the AmazonAPIGatewayAdministrator Role
- Identify (or create) AWS security credentials (access key and secret) for the appropriate IAM user. Figure 8: Locating AWS Security Credentials
- Open a Burp Suite Project and enable (or install) the IP Rotate extension under Burp Suite's Extender tab. Figure 9: Enabling the IP Rotate Extension in Burp Suite
- Navigate to the IP Rotate tab and configure the extension with your AWS security credentials. Also set the "Target Host" to "login.microsoftonline.com" so requests intercepted with Burp Suite are proxied through an AWS API Gateway. Once the credentials and proxy target are configured, click "Enable". Beware of which AWS regions you choose to enable. Authentication attempts made from unusual locations may trigger alerts from Azure Active Directory (AD) Identity Protection and Microsoft Defender for Cloud Apps, both of which support raising alerts based on "atypical travel" or "impossible travel". Figure 10: Enabling IP Rotate to Redirect Traffic Through AWS API Gateways
- On recent versions of Burp Suite, new projects are configured with a project option that prefers HTTP/2 for outgoing TLS connections. This behavior is incompatible with Python's Request library (used by Microsoft Authenticator Library), which as of late 2021, does not support HTTP/2. Consider disabling HTTP/2 in Burp Suite's project options if you encounter an error message in Spray365 that indicates the server responded with an unknown protocol. Figure 11: Disabling HTTP/2 Support in Burp Suite
- Run Spray365 with an execution plan and proxy-specific options that will proxy all traffic through Burp Suite and will ignore SSL validation errors. Figure 12: Password Spraying with Spray365 through Burp Suite + IP Rotate
If Spray365 has improved your Office 365 password spraying workflow, consider giving the GitHub project a star! If there are features that you'd like to see in Spray365, consider opening a detailed issue on GitHub (pull requests are also welcomed!).
Mark Hedrick is a Senior Offensive Security Consultant with Depth Security, a Konica Minolta Service. If you'd like to stay up to date with Mark and his work, you can find him on GitHub or on LinkedIn. If you're interested in hiring Depth Security for our Penetration Testing services, please visit our contact page, or email firstname.lastname@example.org.