Threat Level: green Handler on Duty: Didier Stevens

SANS ISC: InfoSec Handlers Diary Blog - Internet Storm Center Diary 2015-04-23 InfoSec Handlers Diary Blog

Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!

When automation does not help

Published: 2015-04-23
Last Updated: 2015-04-23 19:04:11 UTC
by Bojan Zdrnja (Version: 1)
0 comment(s)

In a lot of web application penetration tests that I’ve done in last couple of years I noticed that the amount of technical vulnerabilities (i.e. XSS or SQL injection) is slowly declining. Of course, this depends on developers’ awareness but also on frameworks that are used for development of such applications. One of the best (or worst, depending on the point of view) is definitely .NET (yeah, I know, it feels weird to say that Microsoft is best in something security related).

With .NET applications, a whole range of security vulnerabilities is actually eliminated by default. For example, XSS vulnerabilities are prevented by default (the infamous “A potentially dangerous Request.Form value was detected from the client” error), CSRF will not work (or will be very difficult to exploit) due to __EVENTVALIDATION and __VIEWSTATE parameters and so on.
That being said, while frameworks are getting increasingly better at stopping technical vulnerabilities, they utterly fail with logical vulnerabilities.

I found such a semi-logical vulnerability recently that demonstrates how complex backend environments, where multiple teams of developers have to work together, can be very error prone to correct handling of “weird” situations. The same example also shows why an automated web application vulnerability scanner cannot replace a human penetration tester – this category of vulnerabilities will always be very difficult to find automatically, if not impossible.

The application I tested used very complex workflows (which are a pretty huge obstacle for automated vulnerability scanners). When the user wanted to change some of his security settings, the application used two factor authentication (2FA) and through a series of challenge/response screens the user had to confirm his actions. Looks good so far.

The last step in this complex workflow was a POST HTTP request, where the user submitted the calculated response back to the server for validation. If the submitted response was OK, the activity was approved, otherwise an error was given.

This is what the request looked like:

POST /Configuration.asmx/SecureAuthenticator HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: application/json, text/javascript, */*; q=0.01
{"changemail":"| … "reponseOtpCode":"313371","authenticator":"Google"}

As you can see in the requests’ body, a JSON structure is being sent with the desired parameter. Besides testing for XSS and SQL Injection vulnerabilities in various parameters, the last two parameters look interesting.
The typical testing went like this:

  • Check if an incorrect response OTP code can be submitted: no, the application correctly catches this and prints an error,
  • Check if we can completely delete the last two parameters (responseOtpCode and authenticator): nope, the application says it’s missing required parameters,
  • Check what happens if we change the value of the authenticator parameter to “hacked”: BINGO, the request went straight through!

So easy! What was the error here? After talking to the developers, the error happened when the front end sent a request to the authentication component. The front end correctly validated if the responseOtpCode and authenticator parameters exist, but didn’t check their contents (at the end of the day, it’s the authentication component’s job).

Now, the authentication component tried to match the value of the authenticator parameter to one of the supported mechanisms (apparently it supported more mechanisms and not only “Google”). When this failed, the authentication component returned back an error value: 255. However, the front end expected only 0 or 1 (successful or failed authentication) and somehow didn’t catch this properly.

At the end, we can see that this simple, half-logical vulnerability lead to a catastrophic scenario. Luckily, the fix was easy, but this once again showed that due to the vulnerability and the complex workflow, we must not rely only on automated vulnerability scanners. 


0 comment(s)
Diary Archives