1

I'm trying an SQLi attack.

The compiler executes the following query despite warnings:

select * from users where username='A' or 'B' and password='C';

Because the query executes, the attack is successful. Why does this query works and what is it doing? Can I assume that the value 'B' is taken as 'True' in the boolean sense? How do the logical operators work with each other? Is there any specific order like BODMAS for mathematics? Note that 'B' is standalone and not a boolean condition.

A query of the above format works fine in mysql database and returns the same result as the query:

select * from users where username='A';

No syantax errors are returned.

mysql> select * from authentication where user='A' or 'B' and password='C';
+------+----------+
| user | password |
+------+----------+
| A    | B        |
+------+----------+
1 row in set, 1 warning (0.00 sec)

The warning is as follows:

mysql> show warnings;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: 'B' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
niton
  • 8,771
  • 21
  • 32
  • 52
Mkl Rjv
  • 6,815
  • 5
  • 29
  • 47
  • I understand, but as you can probably guess, I'm trying an SQLi attack and due to the compiler executing this query despite warnings, the attack is successful-the reason why I wanted to know how it works. So, can I assume that the value 'B' is taken as 'True' in the boolean sense? – Mkl Rjv Oct 16 '13 at 14:59
  • Ok... your intial question was very unclear. You probably should have mentioned your intent, that you knew it was incorrect syntax, and that you wanted to know the result of the query in *MySQL*, specifically. See my updated answer. – JDB Oct 16 '13 at 15:35
  • I've updated your question to include the information from your comment. Please edit if I've misunderstood. – JDB Oct 16 '13 at 17:09

4 Answers4

3

If 'B' is not a boolean then you would need to specify what you are comparing against, which in this case is probably username.

Something like;

select * from users where username='A' or username='B' and password='C'

This would evaluate username='B' AND password='C' and then OR username='A'

You can also refer to this StackOverflow post.

You can find the SQL operator ordering here.

Community
  • 1
  • 1
Belzuk
  • 842
  • 9
  • 12
3

UPDATE

Based on your updated question and comments, it would appear that you are aware of the error in your syntax and want to know specifically how MySQL handles this query.

It would appear the MySQL first converts the character string to an integer value (producing a warning).

MySQL treats any non-zero number as TRUE, so 'B', aftering being converted to an integer, would evalute as TRUE.


To begin with, I don't think your query would be valid in any DBMS I am aware of. Since you say that 'B' is not a boolean condition, then I have to think that you mean:

select * from users where username IN ( 'A', 'B' ) and password='C';

which would, of course, invalidate your question about BODMAS. So, to answer what appears to be your core question, I am going to change your SQL to this:

select * from users where username='A' or username='B' and password='C';

It's going to depend on the DBMS and how it chooses to parse the SQL. Generally the AND should take precedence over OR, but obviously software developers are free to implement SQL however they'd like, so I'm sure you could find counter-examples if you looked hard enough (perhaps a DBMS that processes boolean operators in order, for example).

SQL Server will process the AND before OR

http://technet.microsoft.com/en-us/library/ms190276.aspx

username='A' or ( username='B' and password='C' )

MySQL will also process the AND before OR

http://dev.mysql.com/doc/refman/5.0/en/operator-precedence.html

username='A' or ( username='B' and password='C' )

Sybase will process the AND before the OR

http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.sqlug/html/sqlug/sqlug102.htm

username='A' or ( username='B' and password='C' )

DB2, like the others, will process AND before OR

http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2z9.doc.sqlref%2Fsrc%2Ftpc%2Fdb2z_precedenceofoperations.htm

username='A' or ( username='B' and password='C' )

Even MS Access, one of the least standards-compliant SQL implementations I am aware of, preserves AND-before-OR precedence:

http://office.microsoft.com/en-us/access-help/HV080756432.aspx

username='A' or ( username='B' and password='C' )
JDB
  • 25,172
  • 5
  • 72
  • 123
2

When you write a query like that the query analyzer will throw you a syntax error.

SQL does not allow the syntactical construction of a list of values separated by "OR", mu must "ORize" all the conditions:

select * from users where (username='A' or user_name='B') and password='C';

The parenthesys here are needed because the AND operator takes precedence over the OR operator, so the query without parenthesys is interprested as username='A' or (user_name='B' and password='C')

One extra advice: do NOT store passwords in database. Database should not deal with plain text passwords and user credential validation should be managed at application level, not at database level. Store crypted passwords hashes, retrieve them from application level and validate there. Morover, if working in a Web environment, it's strongly adviseable to encrypt passwords in the client (browser) layer or use SSL.

Yván Ecarri
  • 1,661
  • 18
  • 39
2

This article has a decent table showing the order of operations for T-SQL

Assuming you fix the minor syntax error in your query, you'd return anything that:

  • Has a username of 'B' and a password of 'C'
  • Has a username of 'A'

I believe your syntax should look like this

 select * from users where username='A' or username = 'B' and password='C';
Andy
  • 49,085
  • 60
  • 166
  • 233
  • Actually, there is no syntax error. A query of the above format works fine in mysql and returns the same result as: select * from users where username='A'; – Mkl Rjv Oct 16 '13 at 14:17
  • 3
    @MklRjv - I wouldn't call **`1 warning`** "fine". Warnings may not stop your query from executing, but they typically mean that the query is not doing what you mean for it to be doing. – JDB Oct 16 '13 at 14:28