This website uses cookies

To provide the highest level of service we use cookies on this site.
Your continued use of the site means that you agree to their use in accordance with our terms and conditions.

Insights

Filter Injection via Microsoft Graph API in a Custom Application: From Verbose Errors to Account Takeover

Grzegorz Bronka

August 01, 2025

Introduction During a recent security assessment, it was identified that a client web application integrating Microsoft Entra through the Microsoft Graph API was vulnerable to a novel form of filter injection. This flaw originated in the password reset functionality, where user-supplied input was incorporated directly into Graph API queries without adequate sanitization or validation. Exploiting this weakness allowed bypassing password reset token validation, ultimately enabling unauthorized password resets for arbitrary user accounts. This article details the discovery process and demonstrates practical payloads used to exploit the issue. Technical description The story begins with the typical functionality of a web application – password reset. Commonly, password resets are done with a URL token (https://cheatsheetseries.owasp.org/cheatsheets/Forgot_Password_Cheat_Sheet.html#url-tokens) as it was in this case. During the password change, the application sent a POST request with the following content: The token looked like a good place to try an injection attack. A modified payload was submitted: The value ' or 1=1-- is a classic SQL injection test payload. Instead of some generic error, the application returned an unusual and verbose response: Further investigation revealed that this syntax corresponded to Microsoft Graph API query filters (https://learn.microsoft.com/en-us/graph/use-the-api). No prior references to similar “Microsoft Graph API injection” behavior could be found, suggesting this was a novel case, likely due to the client application’s custom integration with Microsoft Entra.

After analysing the above error and documentation of Graph API it was found out that logical operators can be used in the queries. The following payload gave a promising result: This resulted in error: The injected ') closed the original function call, and startswith(employeeid,'a began a new one. The query was now syntactically valid, but ineffective, as the system still required a match with the provided username (test@example.com).

Additional operators were tested to further understand the behavior. For example: This was rejected, but confirmed usage of Microsoft Graph API (with Microsoft Entra): The next objective was to craft a payload that evaluated the entire filter expression to true. This was achieved with: This payload can be broken down into:

• notimportant') - closed the initial, unseen portion of the query; evaluates to false.
• startswith(userPrincipalName,'test') - matched the login test@example.com; evaluates to true.
• startswith(employeeid,'notimportant - closed the final part of the query evaluates to false.
• The OR operator is used in between so: "false" or "true" or "false" gives true - the query is evaluated to true.

As a result, it became possible to reset the password for any user account without knowing the valid token, provided the attacker knew the username or email.

However, the attack could be further optimized. One limitation was that usernames and email addresses did not always match, as users could configure them independently. In this case, error messages also helped. When changing email address in the account it was possible to trigger following error: This indicated otherMails is the property holding the email address information and can be used in queries. A new payload was constructed: With this query it was possible to reset user password just by knowing their email. The same behaviour also enabled user enumeration. Another endpoint that was used to update email address was found to be also vulnerable. In this case it returned different error responses based on whether a query matched: This allowed incremental, character-by-character enumeration of email addresses. There was no rate limiting so to confirm this scenario several email addresses were recovered this way. Thus, it was possible to find any user, then gain access to their account. The only downside of this attack was the necessity to send email to the target – victim could get alerted that something happened. Conclusions This assessment uncovered a previously undocumented filter injection vulnerability in a custom Microsoft Graph API integration. Verbose error messages made it possible to identify the issue, ultimately leading to full account takeover. By manipulating the queries used in the password reset process, token validation could be bypassed and passwords for arbitrary users could be changed. The same issue also allowed user enumeration, with no rate limiting in place. These findings underline the need for robust input validation, careful query handling, and generic error messaging when working with Microsoft Graph API to prevent similar high-impact vulnerabilities.






Next Pentest Chronicles

When Usernames Become Passwords: A Real-World Case Study of Weak Password Practices

Michał WNękowicz

9 June 2023

In today's world, ensuring the security of our accounts is more crucial than ever. Just as keys protect the doors to our homes, passwords serve as the first line of defense for our data and assets. It's easy to assume that technical individuals, such as developers and IT professionals, always use strong, unique passwords to keep ...

SOCMINT – or rather OSINT of social media

Tomasz Turba

October 15 2022

SOCMINT is the process of gathering and analyzing the information collected from various social networks, channels and communication groups in order to track down an object, gather as much partial data as possible, and potentially to understand its operation. All this in order to analyze the collected information and to achieve that goal by making …

PyScript – or rather Python in your browser + what can be done with it?

michał bentkowski

10 september 2022

PyScript – or rather Python in your browser + what can be done with it? A few days ago, the Anaconda project announced the PyScript framework, which allows Python code to be executed directly in the browser. Additionally, it also covers its integration with HTML and JS code. An execution of the Python code in …

Any questions?

Happy to get a call or email
and help!