Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I've got lines in my php/mysql code which look like this:

...
$sqlquery = "SELECT price FROM products WHERE 1=1 AND id=".$_POST['id'];
...
... query is executed
...
echo $price;

As a test/demonstration, how can I subvert this to show something like a user's password if I had a table users like:

id | username | password
------------------------
 1 |  abcde   | qwerty

Alternatively, what else can I get the system to show?

share|improve this question

3 Answers 3

up vote 17 down vote accepted

I'm assuming your using standard PHP mysql_query function in which case something like this would be effective in your example.

SELECT price FROM products WHERE 1=1 AND id=
999999999999999999999999 
UNION ALL 
(SELECT CONCAT(username, ' ', password) FROM user) limit 0, 1;

Explanation

  1. Use an ID of a product that is not going to exist.
  2. UNION with users table.
  3. SELECT a single column in the users table to return, as your only returning a single column from the product. In this case returning a concatenated field of the username and password columns.
  4. Limit by 1. As your code presumably expecting only a single result from query the query. You could alternatively use a WHERE condition to specify a specific user that you want to retrieve.

Another example would be to use group_concat this would allow for the retrieval of all the entries from the user table in a single query. Inspired from the answer on another question here.

SELECT price FROM products WHERE 1=1 AND id=-1 
UNION ALL 
(SELECT CONCAT(GROUP_CONCAT(username), '\n', GROUP_CONCAT(password)) FROM user);

Additional resources covering SQL Injection attacks:

share|improve this answer
2  
If you're lazy like me you could probably just use a negative number (encoded properly if necessary of course) instead of typing a whole crapload of 9s :) –  mrnap Mar 2 '11 at 2:55
    
@mrnap you make a good point you can just use a negative number I have updated my second example to just that. However it is worth noting that if the database has been designed correctly the id field would be unsigned and giving -1 as a value would result in an error. But in this case that is unlikely so doing it your way does make it a bit shorter. –  Mark Davidson Mar 2 '11 at 10:06

To your last question:

Alternatively, what else can I get the system to show?

Generally, it depends on how SQL server is configured and whether there are some mitigations present. But attacker may have will not only just to show user passwords, alternatively, he can try to:

  • read from and write to various files;
  • write to database and read from it;
  • make DoS and other harmful actions;

Each operation depends on several factors, like, how I said - the presence of mitigation factors, file permissions, system configuration, etc.

By the way, for attacker there is no need to show the result of SQL request. In the case when attacker cannot view the response, it makes the process of information extraction slower and harder, but not impossible.

If you are interested in, I would suggest you to read the blog of Bernardo Damele - the creator of sqlmap: http://bernardodamele.blogspot.com/. There are interesting presentations and reading on what can be done and how.

share|improve this answer

There is a classic example called "Exploits of a Mom" on xkcd that would probably work almost literally in your example. The idea is to post a string like the following as id, such that your code reads it as $_POST['id']:

-1; SELECT * FROM users;

Assuming that when you pass your query to the database it is separated into multiple statements at the semicolon, this is the result that your database sees:

SELECT price FROM products WHERE 1=1 AND id=-1;

SELECT * FROM users;

Your attacker has managed to list the entire user database. In this way, arbitrary database commands can be executed.

As your code probably processes the query result and displays some of the results on a webpage, an attacker could delete things, falsify data, or even spy out information from your database, and potentially use it to modify it as well. This can include hijacking of accounts or, if your database and server design allow it, placing orders without executing payments.

share|improve this answer
    
You are correct in saying that it depends on the database connector if it works. However, there are more than one that would allow it to work. You have already pointed out one way to have it work. Simply forwarding the query to the mysql client program would also make it work (although that is admittedly uncommon for PHP/MySQL). I haven't tested it, but suspect it might even work with PDO::query or the (deprecated) mysql_query. –  pyramids Jul 4 '13 at 18:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.