Vuln #1: Hijack accounts with “Forgot Password” token prediction
You don’t have to be Nate Lawson to discover this obvious security flaw, which may from a blind test may appear secure.
The “forgot password” feature suffers from a critical design error. The application allows users to automatically reset their password through a “lost password” form. That form only requires a user to enter an email address or username. When the form is submitted, the application sends an email containing a token to the associated user’s email address. When the user clicks on the link with the token in it from the email, the server will then allow the user to reset their password through a form. In this design, the token is acting as a temporary password for the user. Therefore, if an attacker can predict the value of the token the application will generate, they will be able to reset account passwords for other users.
Unfortunately, this scenario is possible. The following code is from UserAction.java, starting at line 671:
<code>public User prepareLostPassword(String username, String email) ... String hash = MD5.crypt(user.getEmail() + System.currentTimeMillis()); ... um.writeLostPasswordHash(user.getEmail(), hash); user.setActivationKey(hash);</code>
As can be seen in the code snippet, the secret token is an unsalted hash of the user’s email address and the number of milliseconds since the epoch. Neither of these pieces of information qualify as secrets in a strong cryptosystem. All that is needed to reset a user’s password to a password of the attacker’s choosing is the email address of the victim and the ability to generate a few thousand requests.
Vuln #2: The first and last interesting XSS flaw in the world
JForum has a reflected XSS flaw whose exploitation is uniquely non-trivial. To start: in my development environment, this URL causes an alert box to pop up, containing my session cookies:
http://localhost:8080/JForum/nonexistent.page?module=js&action=list&js=../admin/admin_welcome.htm%00<script>alert(1)</script>
This is an interesting story, and the reason this fires is complex, as far as XSS goes. First, that type of URL won’t normally be found in JForum. The typical URL structure is RESTful. For example, the URL to list the recent posts in a category would look something like this:
http://localhost:8080/JForum/recentTopics/list.page
This is parsed by JForum into a “module” and an “action”. The “recentTopics” substring represents the “module” of this URL, and “list”, the “action.” However, there is an alternative and possibly legacy representation for URLs that is honored by JForum, where URLs look like this:
http://localhost:8080/JForum/servlet.page?module=recentTopics&action=list
The “servlet” substring in this URL is arbitrary, since JForum’s main engine catches all requests aimed at “*.page” and handles them identically based on parameters. This will end up making an attack signature difficult, as will be shown later.
Note: One might guess that the ability to specify arbitrary template constitutes an elevation of privileges. The templates are read-only and are publicly available, since the forum software is OSS. For it to be useful, the application would first have to queue the relevant admin information into memory before processing the template. This would require a separate vulnerability.
For giggles, though, there are other XSS flaws that are much more vanilla:
http://localhost:8080/JForum/jforum.page?module=user&action=recoverPassword&hash=foo%22%3E%3Cscript%3Ealert%28document.cookie%29%3C/script%3E%3Ca
Now, how do we fix these in the ESAPI WAF?
These were not the vulnerabilities I used in my demo because they were not very clean to fix with a WAF (of any kind, not just mine). Unfortunately, they were two of the most serious vulnerabilities.
The account hijacking vulnerability is not possible to stop with a WAF without IP-based throttling, which is butthurt. This is the case because the attack is possible unauthenticated, so there’s no way to differentiate between legitimate “forgot password” resets and attacks. Come to think of it, the WAF could also just prevent all access to that feature until you get the code fix in. Does that count?
It’s possible but annoyingly inefficient to signature the complicated XSS with a simple virtual patch rule. First you’d have to signature a substring of the URI to detect that particular module being executed and then also signature the “js” parameter to detect non-alphanumerics. Given the fact that JForum can have multiple URLs for executing the same functionality, this protection doesn’t give a whole lot of assurance.
But wait, there’s less (security)