Wednesday, June 10, 2009

Small yet eternal lesson from a successful SQL injection attack

I just conduced a penetration attempt on behalf of a site's owner. The site is the kind you use for home-grown, not critical matters. I wanted to try SQL injections first, because since I read Security Warrior, by Cyrus Peikari and Anton Chuvakin, I felt a kind of inner vacuum for never having done that. Here is how I proceeded:

My goal was to change an existing data of the site to add the mention "hacked". The site was a typical interface to a database, with the notions of "new item", "update item" and "view item" clearly visible.
  • From that, I deduced it worked with a database.
Looking at a targetable data, one that I would want to target and mark as "hacked", I saw that the URL contained a GET parameter ?id=20
  • From that, I made the assumption that there would be a database table with the field id equal to 20 for the element I wanted to mark as "hacked".
Looking at the main connection page to the site, I saw another GET parameter in which I tried to input a single quote. The server answered me with an error message including the path to a library file, with the extension .php, with an identifiable name. I typed that name into a Google box and found it was a fairly well known free software underlying library.
  • From the fact that this library was free software, and that the files were named .php, I made the assumption that the database would be a MySQL one, as is most often the case.
I used the normal way to create an element inside the software of the same kind as that of the element I wanted to change. Then I went to the modification page for this element and gave a single quote in one of the text field values of the element. The server returned me an error message with the faulty SQL request.
  • From this I learnt the names of the table and some of its fields inside the database.
  • From this, I validated that id was actually a field inside the same table, which I only assumed earlier.
  • From there, I guessed it would be piece of cake :-)
I crafted a request, using id='20', value of the targeted element instead of that of my legally owned element. I looked on the Internet to find that the comment marker for MySQL was hyphen-hyphen-space and not hyphen-hyphen. And I changed the name field of the attacked element from "dummy title" to "dummy title hacked". And I pressed the button and everything went well. I then used the normal way to visualize data and found the victim element to be called "dummy title hacked".

So, from all that, I conclude that it's important to hide programmer's data from the eye of the user. Especially, GET parameters should not be used unthoughtfully and the error messages from server or middleware should not be displayed to the user. A good polite "We encountered an internal error." is fair enough.

So, next time the webservers' admin or the web dev tells you such small details are not important, just kick him in the balls. I take complaints at cpradier _at_