Tuesday, May 18, 2010

Code So Bad, It's ...Secure?

This past weekend a friend called me up and said he was doing a security assessment of a web site that was put together by a 3rd party he had no faith in - and wanted to know if I was interested in spending some time channeling my evil (long story...read Twitter more if you don't get it) into this site's lack-luster security.

Not being one to turn down a good site-bashing I accepted and took out some of the tools that had been rusting in the back of the shed for a while, sharpened some utensils, and updated some software to modern versions ...and got ready.  I figured we'd drink some beers, have a little fun, ravage a database or two and call it an afternoon.  Little did I know what we were in for.

Todd showed up about 2'ish in the afternoon, and we quickly went to work.  Beers in hand we did some recon on the site, and without even needing more than 10 minutes we found several injection points, where the database was being directly exposed.

Here's where things get ...interesting.

Let me first say that we employed the flow-based methodology I've been talking about lately (video on my HP blog here) and quickly noticed that the site was all kinds of broken.  It became obvious when Todd pasted me one of the URLs he was working on via AIM that there was no regard for flow in the application.  One could go directly to a page deep within one of the registration flows without start to submit it without any of the hidden variables carried through ...that was indicative of what would soon prove to be a tragic, steaming pile of web code.

Another thing I quickly noticed is that I could change the POST requests to the server to GET requests, at will, and the server would process them as long as I included the appropriate parameters.  I could simply chain the POST parameters into the request like so:
POST /blah/verifyEmail.asp  --> GET /blah/verifyEmail.asp?param1=foo&param2=bar
which bugged me because once I started messing with this I realized I could cause the server to start doing some really weird stuff like stop responding!

One thing we quickly noticed was that while the site was hillariously SQL injectable (nearly every database call didn't properly sanitize), there were some frustrating things that made this code difficult to totally invade.

Even though the developer apparently cared nothing for sanitizing database query input parameters (one could insert the ' character into nearly every parameter value without fail.  This produced strangely familiar SQL errors such as this one ...
Microsoft OLE DB Provider for SQL Server error '80040e14'

Incorrect syntax near 'xxx'.
/IncludeDir/includeDir1/includeData.asp, line 44.
Naturally we focused on this for a minute ...but what was interesting was that the xxx was a 3-digit number that was nowhere in the http request.  This was concluded to be a "default" for the site, and we moved on to try and modify that in addition to the obvious SQL injection.

Submitting this POST to the SQL server, yielded more 'near' SQL errors, so nothing particularly interesting:
although ... adding this showed us that the developer had at least used the SQL trim() function to remove white-space:
username=Grover%40SesameStreet.org'select @@version--&type=&groupId=&mode=&action=submitRequest
thus producing this:
Incorrect syntax near 'select@@version'.
After playing with different character combinations, encoding types and tricks we had the following information on the site and its developer ...
  1. many characters were being trim() 'd including the % + and white-space
  2. the developer was surely inserting data dynamically into queries
  3. stored procedures were being used (we found an error identifying "sproc_InsertData")
  4. parameters were not typed
  5. there were at least 2 stored procedures being used here (why?!) which would break attack strings in strange ways across different queries(??)
So after all that, and about 10 hours of hacking away, calling people who were SQLi ninjas much smarter than us ...we had nothing.  Clearly the code was bad, and we were able to poke at the database.  Unfortunately, due to some of the developer's antics, we (nor anyone we reached out to) could figure out a meaningful way to get a complete [injected] query through to extract data.

The best I can figure is this ...the developer tried to create complex, robust code but instead ended up writing a steaming, twisted pile of crap which was so bad it was almost reasonably secure.

This is the worst kind of failure because it fosters that smug feeling of "I stumped the hackers"... remember, we are limited by time & resources...the bad guys ARE NOT.  They WILL get you.


Jed Mitten said...

If ' ' (0x20) and '%' (0x25) were being stripped, did you try to HEX() to see how that played out? HEX can be used to bypass some filters if the queries are accepting raw user input.

alex said...

Reminds me of when one of the us armed forces got so tired of nt 4 hacks back in the 90's they switched to MacOS 8 or 9 - the ip stack and associated networking was so messed up, it was actually much, much harder to hac, making the old Mac OS made an ideal web server.

Email Security Service said...

Really Good Story. Enjoyed lot!!!