This page has been robot translated, sorry for typos if any. Original content here.

Some vulnerabilities in web resources using SQL

The note discusses the SQL vulnerability associated with penetration into the body of the query.

The essence of vulnerability

Consider the work of the simplest system with a WEB-interface, which allows users to save information about themselves as well. Such systems are one of the most common on the network. It can also exist a guest book, also a chat, also a photo gallery, and an email service.

The generated query to the database is forced to have a login also the password entered by the user. Based on these fields, the database should find the corresponding record in the table. After finishing the request, the database returns the information found about the user, which the PHP script makes out as HTML also gives to the user.

Consider a fairly typical fragment of a PHP script that uses an SQL query to access the database:

<? php
$ result = mysql_db_query ("database", "select * from userTable where login = '$ userLogin' and password = '$ userPassword'");
while ($ row = mysql_fetch_array ($ result)) {
echo $ row ["fullname"];
echo $ row ["email"];
echo $ row ["password"];
mysql_free_result ($ result);

As we observe, the login is also the password entered by the user contained in the variables $ userLogin and $ userPassword . The content of these variables is inserted into the request to filter information about this user. The filter is specified using the where option of the select SQL command. In this case, the query looks like this: select * from userTable where login = '$ userLogin' and password = '$ userPassword' where userTable is the name of the table containing the required information. If the login and password variables also contain vanya and vasya values, respectively, then the request sent to the database will look like this: select * from userTable where login = 'vanya' and password = 'vasya' . It is clear that if there is an entry in the database in which the login is vanya, however the password is vasya , right up to the request it will not send a single line from the database, and the script will not return anything. Thus, the above system provides access to information only to a user who has an error-free password and login.

It would seem that such a system does not contain flaws. In the lesson itself, this is not the case. The logic of the programmers who created the above example implies that the username and password entered by the user will be contained within single quotes that are hard-coded in the request body. However, let's see what happens if the password entered by the user himself contains a quotation mark. Let it own the value vas'ya , while the request will take the form: select * from userTable where login = 'vanya' and password = 'vas'ya' . When executing such a request, an error will certainly occur, because the quotation mark from the password closed the opening quotation mark from the request, also the end of the password ya ' remained "hanging" outside the conditional expression.

And if you insert the following line as the password: 'or 1 = 1' , the request will become like this:: select * from userTable where login = 'vanya' and password = '' or 1 = 1 '' will also not have syntax errors . But the logical expression will become identically true, also in opposition to this query, SQL will return the entire user database 8-).

Thus, using the apostrophe symbol, we can penetrate into the body of the SQL query also to make the condition being checked true. If we are interested in a particular user vanya , then to get information about him, it is allowed to use the following password line: 'or login =' vanya . The request will become: select * from userTable where login = 'vanya' and password = '' or login = 'vanya' . As you know, as a result, we get information about vanya .

The described vulnerability of services based on SQL is not limited to unauthorized receipt of information. Since MySQL is used, as a rule, in such systems, it is possible not only to modify the conditional expression in the select command, but also to go beyond this command and also execute another database command. Since MySQL allows multiple commands in a single query, separated ; , then we can execute any of these commands by entering the following code in the password field: '; <SQL command> in which place as <sql> command it is allowed to specify any valid command. So for example such a code: '; drop table 'userTable will simply destroy the userTable table from the database.

Practical use of the vulnerability

Despite its simplicity, the practical use of SQL query errors is very difficult.

In this head, we consider the following problems that arise when using the described vulnerability:
  • Determining the fact of using SQL in the system.
  • Identification of the existence of a vulnerability. Finding out the reaction of the script to errors.
  • Defining field names in a table.
  • Defining the names of existing tables.

    The considered vulnerability is inherent in all SQL queries, regardless of the script or program from where they are called. Nevertheless, we will consider systems based on PHP. This is because the PHP error stream as a position (default) is directed to the end user. At the same time, Perl or Exe applications usually do not inform the user of the nature of errors.

    Determining the fact of using SQL in the system.

    When researching a specific system, you first need to find out if it uses SQL.
    This fact can be detected either indirectly (by looking at the names of the files used, links to the tools used, etc.), or directly - forcing SQL to prove itself. If we work with PHP, then there is only one way to determine unambiguously the use of SQL - this will cause an error in its execution. If an error occurs while executing the request, also, however, the PHP script clearly doesn’t handle any errors, the PHP error message will be sent directly to the user’s page.
    How to cause an error in executing an SQL query depends on the particular device of the system in question. In most cases, an error can be caused by entering incorrect data into the system.

    Identification of the existence of a vulnerability. Finding out the reaction of the script to errors.

    The most unsophisticated means of detecting the presence of a vulnerability, but at the same time also the fact of using SQL, is the following: In any field that is supposedly involved in the formation of the SQL query (for example, the Login or Password field), enter a single quote. The remaining fields are filled with any valid data (or left blank if the system allows it). After sending these forms, we look at the reaction of the system. If, as a result, the PHP script gives us an SQL error, then we can congratulate ourselves: the system uses SQL and the script does not filter a single quote in any way. That eating system contains vulnerability.
    The SQL query error will then look like this on the page:

    Data Entry Form:

    As a result, an SQL query error:

    If there is no SQL error code on the page, then this may mean the following:
    1) The system contains a vulnerability, but the PHP script handles errors. In this case, the system is allowed to be hacked, but you will have to act “by touch”, because we won’t know at what time the SQL syntax will be correct, but at what time.
    2) The script filters the quotation mark also, therefore, errors do not arise. In this case, the system does not contain any vulnerabilities.
    3) The general system does not use SQL in any way.
    In the last couple of cases, it is clear that further SQL research does not make sense.

    Defining field names in a table.

    In order to get information from a database with specific data, we must determine the values ​​of some fields in the request (for example, set the user login). However, for this you need to know the name of the corresponding fields. There is no direct possibility to find out these names. Therefore, you will have to look for these names by brute force. The data names may coincide with the names of the fields in the form sent to the server, or they may also not coincide in any way. It’s a good thing that the names of the fields as a position are standard and there are not so many options for writing them. So, for example, the field name for the username will most likely become login either user or nick . Similar for password: password is either pwd or pass .
    To determine the existence of a specific field, an ingenious method is proposed: Let us want to check if the pwd field exists in the table. Introduce the string 'pwd =' in any form field. If the pwd field exists in the table, then SQL will correctly process the query; if there is no such field, then again the SQL execution error will occur. Thus, substituting different values ​​of the field names while also examining the result of the query finishes, we can find out which fields exist in the table, but which do not.

    Defining the names of existing tables.

    Similar to the method of finding field names in tables, it is also possible to search for the names of existing tables in the database. Suppose we want to find out if the adminList table exists in the database. To do this, enter the following line in the form field “; select * from adminList . If, as a result of the error, SQL does not start at all, then the adminList table exists. For the correctness of this test, you must enter this line in the field that appears final in the SQL query. This is necessary in order to avoid any syntax error due to the remaining tail of the original request, which will be present later select * from adminList . Note that if a pair of Login and Password fields also owns the view for the request, then most likely the password field will be the last to appear in the request.


    Using this vulnerability, the site was hacked (more precisely, its photo gallery is also a chat). We reported the vulnerability to the owners of the site. The hole was fixed. But now, we once again checked the chat registration form. Plus I found all that blah blah vulnerability 8-).