12

I'm working on a site that has been hacked through SQL Injection (at first glance only db entries are corrupted with cross-site scripting) the potential vulnerability I found after looking at the code is that there's a lot of mysql_query call whose inputs are not escaped at all.

The good old :

$query = "SELECT * FROM mytable where name LIKE '%".$_GET['name']."%'"; /*HACK HERE*/
mysql_query($query, $connection);

Nevertheless I can't find how can we do something cool from that injection vulnerability (by cool I mean something like an INSERT or an UPDATE). I've tried to build a statement like this one :

SELECT * FROM mytable where name LIKE '%' AND WHERE id IN (INSERT INTO secondtable (id,description) VALUES (15, 'Fifteenth description');--%'

No success. I guess that the INSERT has nothing to do here.

I'm escaping all user's inputs in the code right now but I've not really get how hackers have penetrated this site, then I'm not 100% sure that my fix will do the job. Any brilliant suggestions ?

Thanks

AsTeR
  • 7,247
  • 14
  • 60
  • 99
  • 1
    I guess this site is not the right place to ask how to do this :) – Mike Jan 29 '12 at 14:03
  • Make sure that 'name' when concatenated with the base strings forms valid sql. – EBarr Jan 29 '12 at 14:05
  • An attacker could easily `JOIN`/`UNION` another table and get admin login credentials. Then, with elevated privileges he could do more evil things, e.g. uploading a PHP shell to execute arbitrary commands on the server – knittl Jan 29 '12 at 14:11
  • The answer you seek is discussed in this stackoverflow post: https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php – 29A Jul 17 '18 at 03:56
  • mysql_query() is no more. Let this question rest in peace. – Your Common Sense Apr 04 '19 at 14:56

7 Answers7

4

Depending upon the version of mysql you are using, and the setup of the connection, mysql_query may allow more than one statement.

You should look at how the connection is being created, and for any usage of mysql_set_server_option.

jmoreno
  • 12,752
  • 4
  • 60
  • 91
3

Interesting that your question hasn't received many (correct) answers yet!

As you discovered, usual PHP MySQL APIs like mysql_query, mysqli::query etc. only execute the first SQL statement in case one passes several of them (separated by semicolons), as would an attacker using the most common class of SQL injections.

Defender tip: banish mysqli::multi_query and friends from your code; the minute performance improvements are not worth the risk.

Does this clever move by PHP-folk completely close all attack channels on some code that goes like "SELECT yadda yadda" . $_GET["untrusted"]? Not quite. As knittl remarks, even a pure-DQL SELECT can be used to escalate one's privileges by UNION ALL SELECT'ing from any nearby interesting table, including but not limited to the passwords table. There are cheat sheets out there giving enough tips and tricks to basically extract the entire database this way.

Defender tip: apply defense-in-depth with known-good techniques:

  • input validation
  • whitelist indirection in an associative array
  • prepared statements (if you can make sure that they are effective and not just string escaping in disguise!)
  • an ORM
  • protective encoding (e.g. Base64) when the untrusted input cannot be satisfactorily sanitized (e.g. a blog post that may legitimately contain SQL-sensitive punctuation)
  • or as a last resort only, string escaping

Next, one may observe that not all DQL is side-effect free, in particular when it ends with INTO DUMPFILE somethingsomething.

Defender tip: always configure secure_file_priv in your MySQL / MariaDB server.

Last but not least, even an attacker who is in a position to inject arbitrary SQL is limited by the authority granted to the Web app as a whole.

Defender tip: secure your app by applying POLA.

  • Only GRANT the Web app's MySQL user as much authority as it needs. It is not a bad idea to design your app so that it requires no DDL at all. If you must provide a “back up / restore DB” feature or some such from the Web UI, use a separate MySQL user for that.
  • Automate backups, even though they are useless — restores are what matters.
DomQ
  • 4,184
  • 38
  • 37
3

Because mysql_query is not supporting multiple queries, So any injection that is doing like '; DROP TABLE mytable; -- won't be successful.

However, the attacker can combine with other select statement to select the other info like password info.

xdazz
  • 158,678
  • 38
  • 247
  • 274
1

Possible scenario 1
Weak passwords/hashing will let an attacker to select administrator's password.
It would be wise to change all administrators passwords.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
0

Now, it's been a while since did any php, but in general most data access libs have some sort of parameterized sql to reduce the risk. A quick google came up with this for php: http://php.net/manual/en/pdo.prepared-statements.php

The other poster have already described how to do a sql injection so I won't get into that.

Daniel
  • 622
  • 4
  • 6
  • " then I'm not 100% sure that my fix will do the job. Any brilliant suggestions ?" - I suggested an alternate fix – Daniel Jan 29 '12 at 14:12
  • this fix of the same nature with one used. but the op asked for the different nature. you just don't understand the question – Your Common Sense Jan 29 '12 at 15:10
  • IMO it's quite a big difference between a home rolled solution vs a tried and tested lib – Daniel Jan 29 '12 at 15:19
  • That's indeed not what I was asking. I plan to make somekind of dirty fix, I take what's in place and fix it. I know that the best solution from scratch would be to use PDO. – AsTeR Jan 29 '12 at 19:27
0

I'm pretty sure that a hacker would be able to modify the query easily. Even if mysql_query() doesn't support multiple queries, there are ways around that. you could just use a mysql IF statement added on to the end, and of course that will execute a completely new query.

Adam Fowler
  • 1,750
  • 1
  • 17
  • 18
-3
$query = "SELECT * FROM mytable where name LIKE '%".$_GET['name']."%'";

$_GET['name']="'; DROP TABLE mytable; -- ";

so

$query = "SELECT * FROM mytable where name LIKE '%'; DROP TABLE mytable; -- %'";
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92