SQL exploits

You know its going to be a bad day when you get the following email:

Did someone hack our website? It looks like a Chinese news listing entry has been added with today’s date.

Ballsack!

Time to roll up the sleeves. How bad is the damage?

From the looks of it, other sites on the web server had not been damaged. Doing a search for modified files found nothing out of the ordinary had been changed. Log files sure but nothing out of the ordinary. A search through the web logs of the site showed that this appeared to be an attack on the Content Management System (CMS) for the site.

Whichever jackass wrote that code should be beaten! Get the torches and pitchforks, death to the programmer!! Oh wait, that was me. Death to the evil script kiddie that attacked my beautiful code!!!!!!!!!

Searching through the logs, I started seeing some interesting logs. A bunch of them that had variations such as this:

http://unigleeclub.com/news.phtml?id=-999.9%20UNION%20ALL%20SELECT%200x31303235343830303536,(SELECT%20concat(0x7e,0x27,Hex(cast(user.username%20as%20char)),0x27,0x7e)%20FROM%20`gleeclub`.user%20LIMIT%203,1)%20,0x31303235343830303536,0x31303235343830303536--

This one is actually after a lot of hits from the attacker of figuring out the tables and then getting down to the nitty gritty of pulling out a username and password.

The issue was that I had forgotten to sanitize my data. Like a jackass, I didn’t check that $id was an actual integer variable and when they ran thier script they were able to pull out a hex string that, with the use of such tools as this site, you can easily translate this into text.

The Quick Fix

I put in 2 fixes to ensure that we were dealing with an integer value here. First, I did some simple math to the variable that changes its type if it is not an integer.

$id = $id+;

If you have a string, you’ll get back a zero. If you have an integer value, you’re good to go.

Also in the code, I expanded the if statement that was around the code to grab the specific news item. Instead of just checking to see if the $id variable was set, I now check to see if it is set and greater than zero, another layer in ensuring that we have a number instead of a string of text.

//Before:
if(isset($id) && $id != "")

//After:
if(isset($id) && $id != "" && $id > )

We’re all human and humans make mistakes. This code that was exploited was written 8 years ago at a time when I should have known better, but missed it. It lived in the wild up until last year when it was finally exploited. I’m lucky that it took that long for it to expose itself, but kind of embarrassed that it was there in the first place. While I tend to come down hard on people for not doing these sort of things, its only because I’ve learned my lesson the hard way and have seen people continually mess this stuff up. While this happened to me a while ago, I’ve had friends get bit by this very recently so I figured it was time to finish off this post and get it out the door. An ounce of prevention sort of thing.

To lear more about SQL Inject attacks, here is a good article by Bhanu Mahesh on Quality Software Connection on how to prevent them.