3

I've been working on a legacy website. Recently a user has informed us about a potential security breach.

Long story short, when trying to login and using '=' 'or' as password or a username the following query will get executed.

SELECT * FROM `table-goes-here` WHERE `username` = ''=' 'or'' AND `password` = 'some-hash-goes-here'

This query will select everything in that table and will allow login without any actual valid credentials.

I just maintain the site and I have talked to the owner before about such security leaks, he won't listen.


What I want to know is how exactly is this a valid query and what exactly does it do(preferably step by step, explain it to me like I'm 5 version). My MySQL knowledge isn't the best there could be.


I'm very aware that this is an SQL injection. I know how to prepare statements, but they're not in the budget apparently. I just want to know what it does exactly. Namely this part. I have never seen this syntax before and googling doesn't really help as I don't know what I'm looking for exactly.

`username` = ''=' 'or''
Andrei
  • 3,434
  • 5
  • 21
  • 44
  • 2
    Possible duplicate of [PHP mysql injection protection](http://stackoverflow.com/questions/7043303/php-mysql-injection-protection) – Pedro Lobito Oct 12 '15 at 14:07
  • is this exactly the echo of your sql statement (except password)? – Julio Soares Oct 12 '15 at 14:09
  • @JulioSoares Yes, that is exactly the query. Without the table name and the password. – Andrei Oct 12 '15 at 14:10
  • 1
    Possible duplicate of [How can I prevent SQL-injection in PHP?](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) – Amelia Oct 12 '15 at 14:11
  • I would put your "what I want to know" in bold... – camelCase Oct 12 '15 at 14:12
  • Oof, not that I would have any non-prepared statements in a web app, but I'm now very glad that T-SQL's comparison operators don't support approximate equality / inline conversions to bool. In that dialect, comparison operators can occur once, at the expected position in a boolean clause, and that's it. It's interesting to learn about this difference, especially because I might be using MySQL later on... – underscore_d Oct 12 '15 at 14:48

3 Answers3

4

Thing is you are actually running

SELECT * FROM table WHERE (username= '' = '') or ('' AND password="");

and (user_username = '' = '') evaluates to true... try

SELECT  (username= '' = '') FROM table;

and ('' AND password="") also evaluates to true... try

Select ('' AND password="") FROM table;

also evaluates to true so... everything is shown

Julio Soares
  • 1,200
  • 8
  • 11
  • Ok, another question, how is this `user_username = '' = ''` valid? I've never seen this kind of syntax before. Obviously, it's valid, I just want to understand it. – Andrei Oct 12 '15 at 14:22
  • just a note, it doesn't change anything because of the `or`, but the second condition evaluates to false – Alex Andrei Oct 12 '15 at 14:28
  • @AlexAndrei It doesn't, but it also doesn't mean I don't want to understand it. – Andrei Oct 12 '15 at 14:32
  • @Andrew: Check the expression syntax of a where clause [here](https://dev.mysql.com/doc/refman/5.0/en/expressions.html), couple that with the fact that the [`=` operator has a relatively low precedence](https://dev.mysql.com/doc/refman/5.0/en/operator-precedence.html), even if it's a comparison operator, and you'll find that the comparisons with field values are turned into truthy boolean expressions – Elias Van Ootegem Oct 12 '15 at 14:46
  • @AlexeiAndrei. Yes, you are right. my rush... But it matters as it makes the expression "make sense" as it avoids the `OR AND password` that would be there without the injection – Julio Soares Oct 12 '15 at 16:45
1

I think it's working like this, first of all evals the username = '' this returns false or 0 then the other parts come 0 = ' '

as you can see from mysql : https://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_equal

if you compare string with 0 (zero), it returns 1 (true) AS a result:

SELECT 'blabla' = ''; // returns 0
SELECT 0 = ' '; // returns 1
Santa's helper
  • 976
  • 8
  • 21
0

The query would basically evaluate to true and would return all records.

So, the thing which would happen is that the hacker would be logged in as the user whose ID is stored first in your database.

Of course, it wouldn't show the database to the hacker, because you aren't echoing any of the database content anywhere, but with a little modification the hacker can manage to login as any user, not just the first one.

Read following to prevent such attacks How can I prevent SQL injection in PHP?

More info- http://www.w3schools.com/sql/sql_injection.asp

EDIT- The hacker would also have to use a similar trick in password field because else it would become false.

Community
  • 1
  • 1
prakhar19
  • 465
  • 4
  • 18