3

I recently thought about something like this:

$sql = "SELECT password FROM users WHERE user = '" . $_POST["user"] . "'";
$result = mysql_query($sql);

if (myql_num_rows($result) != 1) {
//Error
}

$data = mysql_fetch_array($result);

if ($data["password"] == md5($_POST["password"])) {
//Welcome
} else {
//Error
}

Even though no parameterized querys or atleast escaping is used, I could not think of a proper sql injection with which you can get trough to the Welcome point. You would somehow need to modify the returned password whose md5 value you can then just use as a password.

Any ideas if this is possible?

Zulakis
  • 7,859
  • 10
  • 42
  • 67
  • 1
    I am not looking for a way on how to prevent sql injection. Seems like you didn't even read my post. – Zulakis Jan 10 '13 at 14:38
  • Read below: http://stackoverflow.com/questions/60174/how-to-prevent-sql-injection-in-php – Suresh Kamrushi Jan 10 '13 at 14:38
  • @halfer Yes, sorry. Thats a untested sketch I wrote in a minute. – Zulakis Jan 10 '13 at 14:39
  • 6
    My username is `; DELETE FROM users` - in this case probably won't cause problems, but you get the idea... – GarethL Jan 10 '13 at 14:40
  • 1
    I'm voting to close as an exact duplicate of the question above because there's nothing new here really - the first line is vulnerable to SQL injection and that should never be allowed to happen. No matter whether the user can use the vulnerability to log in or not - he can break the query and that mustn't happen. – Pekka Jan 10 '13 at 14:41
  • PHP's md5 implementation may vary server to server. Your codebase isn't very portable, as you risk locking users out, should the md5 function start returning a different hash after a major upgrade to the server. – Husman Jan 10 '13 at 14:42
  • 1
    I am reading your post, and indeed you do not ask if your SQL is vulnerable to injection and how to prevent it, so what are you asking? – Marlin Pierce Jan 10 '13 at 14:42
  • @GarethL I am explicitely looking for a way on how to circumvent the `md5()` test, but thanks. – Zulakis Jan 10 '13 at 14:42
  • Use list of most common 500 passwords, then use `1 or password=MD5('PASSWORD'`). – mellamokb Jan 10 '13 at 14:43
  • 1
    @mellamokb - that won't work here, because of the md5 test. – halfer Jan 10 '13 at 14:43
  • @halfer Well, you could use a list of the 500 most common passwords being md5-encrypted, but that's not the point. I am looking for a way on how to circumvent the md5-test in my example. – Zulakis Jan 10 '13 at 14:45
  • 1
    @Husman - really? md5 should return very standard results on any system on any language, afaik. Results between say PHP and ASP.net should be the same, as well as between major versions of PHP. – halfer Jan 10 '13 at 14:45
  • @halfer Yes, md5 is a standard which should always return the same hashes. Otherwise, this would mean that the hashes from the database would also not work after changing the system. – Zulakis Jan 10 '13 at 14:46

2 Answers2

8

Use the following value for User:

obviouslyinvalidusername' union select MD5('password123') as password --

Then a password of password123 should authenticate. I don't know what user account you would be logged in at this point, because that part of the logic isn't shown.

mellamokb
  • 56,094
  • 12
  • 110
  • 136
  • Yes, this will get through the requirement to return only one row, provided there is no user called '' in the db! +1 – halfer Jan 10 '13 at 14:52
  • 1
    @halfer: Good point, updated :) In my experience, the most dangerous injection comes in the form of allowing `union` statements at the end. – mellamokb Jan 10 '13 at 14:53
  • You'd probably want to `SELECT` a `user` here in practice, but many systems list usernames (profiles) publicly, so obtaining this could be trivial. – halfer Jan 10 '13 at 15:09
  • Nice one. Throwing in a control character into the "obviously invalid username" would help to make it more probable that the name is indeed invalid (something like `+ char(1)`, perhaps) – Andriy M Jan 10 '13 at 15:13
0
"'; UPDATE user SET password=MD5('fakepass') where username='username'"

That will insert an arbitrary password as a md5 hash into the database.

rs.
  • 26,707
  • 12
  • 68
  • 90
Husman
  • 6,819
  • 9
  • 29
  • 47
  • 2
    That won't work with `mysql_query`, since it only executes one statement. See here: http://uk1.php.net/manual/en/function.mysql-query.php – halfer Jan 10 '13 at 14:47