How to hack
[Virus][Computer][Non Existing Law]

I'm going to teach you what an SQL Injection attack is and how you can perform it from the comfort of your own home. But first, a disclaimer: In some countries, e.g. the US, doing this may be illegal. There are so called "white hat hackers" who go around testing computers on the Internet for security flaws, and upon discovering them, notify the computers owner so that these flaws can be fixed. Eric McCarthy is one such white hat, and he notified a university of a security flaw in one of their servers, and McCarty is now facing arrest and legal charges by the FBI. Incidentally, the flaw that McCarty discovered is a vulnerability to SQL Injection Attack.

I'm not a neurosurgeon, but from my understanding, there's a part of your brain which is dedicated to storing your memories, and there's a part of your brain which is dedicated to making decisions based on what situation you're currently experiencing in combination with your memories. Internet servers behave the same way. The part that stores memories is called the "Database", and the part that makes decisions is called the "Application".

There needs to be a way for the application to communicate with the server, and this communicate takes place in a given language. By far, the most common language used for this purpose is SQL. An SQL statement looks like:

SELECT Name FROM Customers WHERE ID = 10

This will get all the names of all the customers whose IDs are 10. Probably there exist exactly one user with an ID of 10, so this statement should yield exactly one name. However, if for some reason there were five users with the ID 10 (perhaps an account that's shared across family members?), then the statement would yield five names. If there were no customers with the ID 10, then you would get zero names.

With that in mind, let's say someone tries to log in as "Nebu Pookins" with password "Im d4 man!". An easy way to check whether that particular username and password combination is valid might be a statement like:

SELECT Id FROM Users WHERE Name = 'Nebu Pookins' AND Password = 'Im d4 man!'

If the combination were correct, that is if there does exist in the database a user with the name "Nebu Pookins" and with the password "Im d4 man!", then this query should return exactly one result: the id of that user account. If, however, the password was invalid, and there didn't exist any users with that name and password combination, then you'd get zero results. So to actually perform the login verification process, you could just execute the above SQL query, and check how many results you got back.

Now the application itself is also written in some programming language, and this programming language is distinct from SQL. A common language to use for writing web applications is PHP. Now just like the way you have to construct a phrase in your head before you utter it to someone, PHP has to construct the query before it can send it to the database. A PHP script that does this might look something like the following:

$query = "SELECT Id FROM Users WHERE " + "(Name = 'Nebu Pookins') AND " + "(Password = 'Im d4 man!')"; $result = mysql_query($query);

The first three lines stores the query in a variable called $query. Note that I used the + operator to split the query into pieces. Basically, this + operator means take the first piece of text, and then add the second piece of text after it. It was used here because if I had written the whole query on one line, the query might have been too wide, and taken up too much screen space. In the last line, it gives $query to mysql, which is one particular brand of SQL servers, and stores the result in a variable called $result. Unfortunately, the above code will only ever check for one specific user name and password combination, which isn't very useful. What if people want to log in under a different name, or with a different password? Well, what you would do then, is build a login form, and then get the values that the user entered in, and place them into the query. The code would look something like:

$username = $_GET['username']; $password = $_GET['password']; $query = "SELECT Id FROM Users WHERE " + "(Name = '" + $username +') AND "+ "(Password = '" + $password + "')"; $result = mysql_query($query);

See, the first two lines are now getting the actual username and password that the user had entered in. Then, a query is built, substituting the actual name and password typed in by the user at the appropriate location. So if the user typed in user "Bob" and password "Foo", then the query that the SQL server would receive would be "SELECT Id FROM Users WHERE (Name = 'Bob') AND (Password = 'Foo')". It's like Madlibs.

Anyway, if you ever become a PHP programmer, you should NEVER write code like the above. Why? Because it's vulnerable to the SQL Injection Attack. Luckily, you've read my blog, so now you can be confident you'll never write a PHP script which has this vulnerability, but there are some people out there who don't read my blog (those poor bastards), and so there exists sites out on the Internet which are vulnerable to SQL injection attack. But what IS the SQL Injection attack? And what's wrong with the above code?

As I mentioned, the PHP script constructs the query just like it were playing madlibs, substituting exactly what you wrote into the appropriate positions. The next time you play with madlibs, and it asks for a verb, try putting a noun isntead. Or here, do this one. "Last night, he __(past tense verb)__ the dog." If you had put a noun there instead, e.g. "watermelon", you would have "broke" the madlib: "Last night, he watermelon the dog." It simply doesn't make sense.

That's all fine and dandy, but broken madlibs are no fun, right? Well, what if instead of just replacing the verb with a noun, you replaced it with an entire sentence? For example, when the madlib asks for a past tense verb, you provide it with "did nothing. However, I'd like to point out that Neb is the sexiest guy in the world. Now ignore this sentence fragment: ". If you take that long text and insert it into the madlib, you get "Last night, he did nothing. However, I'd like to point out that Neb is the sexiest guy in the world. Now ignore this sentence fragment: the dog." Amazing, isn't it? I can "hack" the madlib to say anything I want at all. In other words, even if someone else designed the madlib, as long as they gave me an empty blank to fill in, I can construct a filler that changes the meaning of the madlib to whatever I want. Well, you can do this same trick with the code above. Let's say you want to log in as "Nebu Pookins", but you don't know the password associated with that account. Well, start off by entering "Nebu Pookins" as the username. Then, instead of typing in any old password, try instead typing in something like "' OR '' = '". What will the resulting SQL query look like?

If we dutifully fill the query in like a broken madlib, we get the following:

SELECT Id FROM Users WHERE (Name = 'Nebu Pookins') AND (Password = '' OR '' = '')

So now let's take a point of view of the database receiving this query. The database will take this query, scratch it's head, and tell the application "Gee boss, this sure is a funny looking query. Are you sure that's what you want?" To which the application server replies "Shut up! You're not paid to think; I am! Just do as I say!" So the database shrugs, and performs the query. It sees the query starts with "SELECT Id FROM Users". Okay, so the database looks for where all the user accounts are stored, and remembers to pay special attention to the "Id" column. Then it starts reading the conditions. The first one is "Name = 'Nebu Pookins'". Well, the DB looks through its records and sees exactly one user who has the name 'Nebu Pookins'. "Well this is gonna be easy", says the DB to itself. "All I have to return is one record". But wait! Not so fast! There's another condition. The second condition says "Password = '' OR '' = ''". So the DB takes a look at the password column for the appropriate record. The password is "Im d4 man", so the "Password = ''" thing is false... However! The "'' = ''" part is true! That is, the empty text is equal to itself. And the condition says the password should be empty OR empty is equal to empty. Sounds weird, but then again, the DB is being paid enough to think. So it returns the record, just like the query says it should.

"Here's the ID boss. You got 1 result." says the DB to the application. "Excellent", says the application. "One record you say? That must mean the password is valid! Okay, give him full administrative access!"

That's basically all there is to it. It's called an SQL Injection attack because you're "injecting" commands directly into the SQL query. In other words, you're taking control of the madlib.

There are various ways to protect yourself against SQL Injection attacks. For one thing, you could for example check that the text that the user entered in didn't contain the single-quote mark. There are other techniques, but I won't bored you with the details of those. The point of this article was to inform the public at large of what an SQL injection attack is, and how it's done. The idea is that it'll become common knowledge, and then no programmer worth his salt will ever write web applications that are vulnerable to SQL injections again, thus saving the Eric McCarthies of the world from going to prison.

 
E-mail this story to a friend.
, , , , ...
1. Nebu Pookins said:

Don't bother trying "Im d4 man!"; I've since changed my password to something even subtler!

Posted on Wed May 10th, 2006, 4:25 PM EST acknowledged
2. Leafy Person said:
Hum...I'm going to try «Neb is the sexiest guy in the world»..
Posted on Fri May 12th, 2006, 12:36 AM EST acknowledged

You must be logged in to post comments.

Sites linking to this post: