There are a lot of useful implementations of AJAX, for example in web forms where the user can put their ZIP code and it obtains the State and City of the address automatically, saving the user a couple of clicks. Even popular features like Google Instant run with AJAX.
However, AJAX should not be used everywhere. Web pages should be designed and restricted so that confidential information like usernames or other sensitive data is not exposed to malicious agents.
In this post, I will discuss how AJAX use on a university webpage led to an account enumeration vulnerability. Account or username enumeration is an attack where possible accounts are either brute-force or guessed, and the system confirms the existence or non-existence of such accounts.
I stumbled across a university page that uses AJAX to fill a form. When a user types in their account number it gives information about the active students enrolled. However, this feature could be exploited by an attacker.
The AJAX flow is the following:
- The user must input the Account number (6 digits).
- Based on the answer the form gets filled (valid account number) or the user gets an error (invalid account number).
The POST request is the following:
Figure 1. Example of POST request
As we can see only one parameter is used: "txtCuentaAlumno".
Since only 6 digits are required, we could do a simple brute-force attack to enumerate the active users. I use Burp to launch the attack.
First, we configure the payload position:
Figure 2. Payload position
Then we configure the payload. In this case, we will use numbers:
Figure 3. Payload configuration
Then we configure a Grep Extract from the payload:
Figure 4. Grep Extract for the response
After we execute the attack, we can see we obtained some information:
Figure 5. Results of the attack
We can see that the page has two possible answers:
- In case we give an invalid account number it responds: "No encontrado" (translates to "Not Found")
- In case we give a valid account number it responds with the details about the student: Account digit, Last name, etc.
Finally, a small Ruby script that does the same attack:
Figure 6. Simple PoC in Ruby
There is no simple solution to enumeration attacks. If possible, no information should be revealed to the user unless they have already proven they are authorized to do so (for example via authentication) or in cases where the information provided is already 100% public (for example the state of a zip code).
In some cases, businesses want to make things more efficient and faster to give the user benefits in terms of numbers of clicks or time to fill a form. However, sometimes they do so by risking information leakage. In such cases, a CAPTCHA may make things more difficult for an automated attacker, but even that won't stop a determined attacker. It's important to know that the analysis must be done carefully since revealing private information is a very sensitive situation and may even result in legal liability.
Additional solutions that may help (and raise the general security of any website) include:
- Log every request and monitor the logs to detect attacks like brute force, enumeration, and Password Spraying.
- Implement a WAF to detect and stop attacks in real time. A great and easy to implement open-source WAF is ModSecurity.
Note: The screenshots were edited to omit the information about the vulnerable website and any other information that we consider sensitive.