Update: This article is part of a series. Check out the full series: Part 1, Part 2, Part 3, Part 4!

In the pre-course material, hosted in the course’s webpage, we got introduced to the SQL language and data stores. The scope of this course is not to learn SQL or data stores but we are going to examine some more information about data store hacking that we will find useful in the rest of the course.

Currently, nearly all applications rely on a data store to manage data that is processed within the application. In many cases, this data drives the core application logic, holding user accounts, permissions, application configuration settings, and more. Data stores have evolved to become significantly more than passive containers for data. Most hold data in a structured format, accessed using a predefined query format or language, and contain internal logic to help manage that data.

Typically, applications use a common privilege level for all types of access to the data store and, when processing data, belonging to different application users. If an attacker can interfere with the application’s interaction with the data store, to make it retrieve or modify different data, he can usually bypass any controls over data access that are imposed at the application layer.

The principle just described can be applied to any kind of data store technology. Because this is a practical handbook, we will focus on the knowledge and techniques you need to exploit the vulnerabilities that exist in real-world applications. By far the most common data stores are SQL databases, XML based repositories, and LDAP directories. Practical examples seen elsewhere are also covered.

In covering these key features in this course, we will describe the practical steps that we can take to identify and exploit these defects.

To continue, SQL can be used to read, update, add, and delete information held within the database. SQL is an interpreted language, and web applications commonly construct SQL statements that incorporate user-supplied data. If this is done in an unsafe way, the application may be vulnerable to SQL injection. This flaw is one of the most notorious vulnerabilities to have afflicted web applications. In the most serious cases, SQL injection can enable an anonymous attacker to read and modify all data stored within the database, and even take full control of the server on which the database is running.

As awareness of web application security has evolved, SQL injection vulnerabilities have become gradually less widespread and more difficult to detect and exploit. Many modern applications avoid SQL injection by employing APIs that, if properly used, are inherently safe against SQL injection attacks. In these circumstances, SQL injection typically occurs in the occasional cases where these defense mechanisms cannot be applied. Finding SQL injection is sometimes a difficult task, requiring perseverance to locate the one or two instances in an application where the usual controls have not been applied.

As this trend has developed, methods for finding and exploiting SQL injection flaws have evolved, using more subtle indicators of vulnerabilities, and more refined and powerful exploitation techniques. We will begin by examining some basic cases, but not many of them, and then go on to describe the latest techniques for blind detection and advanced exploitation.

A wide range of databases are employed to support web applications. Although the fundamentals of SQL injection are common to the vast majority of these, there are many differences. These range from minor variations in syntax to significant divergences in behavior and functionality that can affect the types of attacks we can pursue. For reasons of space and sanity, we will restrict our examples to the three most common databases we are likely to encounter — Oracle, MS-SQL, and MySQL. Wherever applicable, we will draw attention to the differences between these three platforms. Equipped with the techniques we describe here, we should be able to identify and exploit SQL injection flaws against any other database by performing some quick additional research.

Injection flaws allow attackers to relay malicious code through an application to another system. These attacks include calls to the operating system via system calls, the use of external programs via shell commands, as well as calls to backend databases via SQL (i.e., SQL injection). Whole scripts written in Perl, Python, and other languages can be injected into poorly designed applications and executed. Any time an application uses an interpreter of any type, there is a danger of introducing an injection vulnerability.

Many web applications use operating system features and external programs to perform their functions. Sendmail is probably the most frequently invoked external program, but many other programs are used as well. When a web application passes information from an HTTP request through as part of an external request, it must be carefully scrubbed. Otherwise, the attacker can inject special (meta) characters, malicious commands, or command modifiers into the information and the web application will blindly pass these on to the external system for execution.

Also, every web application environment allows the execution of external commands such as system calls, shell commands, and SQL requests. The susceptibility of an external call to command injection depends on how the call is made and the specific component that is being called, but almost all external calls can be attacked if the web application is not properly coded. Let’s see the most important Injection attacks and how they work.

The process by which an application accesses a data store usually is the same, regardless of whether that access was triggered by the actions of an unprivileged user or an application administrator. The web application functions as a discretionary access control to the data store, constructing queries to retrieve, add, or modify data in the data store based on the user’s account and type.

A successful injection attack that modifies a query (and not merely the data within the query) can bypass the application’s discretionary access controls and gain unauthorized access.

If security-sensitive application logic is controlled by the results of a query, an attacker can potentially modify the query to alter the application’s logic. In the following example, a back-end data store is queried for records in a user table that match the credentials that a user supplied. Many applications that implement a forms-based login function use a database to store user credentials and perform a simple SQL query to validate each login attempt.

SELECT * FROM users WHERE username = ‘marcus’ and password = ‘secret’

This query tells to the database to check all the rows that exist in the users table and return every record where the username column has the value marcus and the password column has the value secret. If a user’s details are returned to the application, the login attempt is successful, and the application creates an authenticated session for that user. In this situation, an attacker can inject into either the username or the password field to modify the query performed by the application and thereby subvert its logic. For example, if an attacker knows that the username of the application administrator is admin, he can log in as that user by supplying any password and the following username:

By supplying this in the username, it causes the query we described earlier to become:

SELECT * FROM users WHERE username = ‘admin’ — ‘ AND password = ‘random-pass’

The comment sequence ( — ) causes the remaining query after it to be ignored, and as a result the query that the database executes in the end, is:

SELECT * FROM users WHERE username = ‘admin’

And like this the password check is bypassed.

Now let’s suppose that the attacker does not know the administrator’s username. In most applications, the first account in the database is an administrative user, because this account normally is created manually and then is used to generate all other accounts via the application. Furthermore, if the query returns the details for more than one user, most applications will simply process the first user whose details are returned. An attacker can often exploit this behavior to log in as the first user in the database by supplying in the username field:

After this, the query we examined earlier will be:

SELECT * FROM users WHERE username = ‘’ OR 1=1 — ‘ AND password = ‘random-pass’

As earlier, because of the comment symbol, this query will be executed like this:

SELECT * FROM users WHERE username = ‘’ OR 1=1

which returns the details of all application users.

Extensible Markup Language (XML) is a specification for encoding data in a machine-readable form. Like any markup language, the XML format separates a document into content (which is data) and markup (which annotates the data).XML is used extensively in today’s web applications, both in requests and responses between the browser and front-end application server and in messages between back-end application components such as SOAP services. Both of these locations are susceptible to attacks whereby crafted input is used to interfere with the operation of the application and normally perform some unauthorized action.

Continuing, in today’s web applications, XML is often used to submit data from the client to the server. The server-side application then acts on this data and may return a response containing XML or data in any other format. This behavior is most commonly found in Ajax-based applications where asynchronous requests are used to communicate in the background. It can also appear in the context of browser extension components and other client-side technologies.

For example, consider a search function that, to provide a seamless user experience, is implemented using Ajax. When a user enters a search term, a client-side script issues the following request to the server:

POST /search/128/AjaxSearch.ashx HTTP/1.1 Content-Type: text/xml; charset=UTF-8

After this, the server responds with the following (although vulnerabilities may exist regardless of the format used in responses):

Content-Type: text/xml; charset=utf-8

<Search><SearchResult>No results found for expression: nothing will

The client-side script processes this response and updates part of the user interface with the results of the search.

When we encounter this type of functionality, we should always check for XML external entity (XXE) injection. This vulnerability arises because standard XML parsing libraries support the use of entity references. These are simply a method of referencing data either inside or outside the XML document. Entity references should be familiar from other contexts. For example, the entities corresponding to the < and > characters are as follows:

The XML format allows custom entities to be defined within the XML document itself. This is done within the optional DOCTYPE element at the start of the document. For example:

If a document contains this definition, the parser replaces any occurrences of the &testref; entity reference within the document with the defined value, testrefvalue.

Furthermore, the XML specification allows entities to be defined using external references, the value of which is fetched dynamically by the XML parser. These external entity definitions use the URL format and can refer to external web URLs or resources on the local filesystem. The XML parser fetches the contents of the specified URL or file and uses this as the value of the defined entity. If the application returns in its response any parts of the XML data that use an externally defined entity, the contents of the specified file or URL are returned in the response.

External entities can be specified within the attacker’s XML-based request by adding a suitable DOCTYPE element to the XML (or by modifying the element if it already exists). An external entity reference is specified using the SYSTEM keyword, and its definition is a URL that may use the file: protocol. In the preceding example, the attacker can submit the following request, which defines an XML external entity that references a file on the server’s filesystem:

This causes the XML parser to fetch the contents of the specified file and to use this in place of the defined entity reference, which the attacker has used within the SearchTerm element. Because the value of this element is echoed in the application’s response, this causes the server to respond with the contents of the file, as follows:

In addition to using the file: protocol to specify resources on the local filesystem, the attacker can use protocols such as http: to cause the server to fetch resources across the network. These URLs can specify arbitrary hosts, IP addresses, and ports. They may allow the attacker to interact with network services on back-end systems that cannot be directly reached from the Internet. For example, the following attack attempts to connect to a mail server running on port 25 on the private IP address 192.168.1.1:

This technique may allow various attacks to be performed:

● The attacker can use the application as a proxy, retrieving sensitive content from any web servers that the application can reach, including those running internally within the organization on private, nonroutable address space.

● The attacker can exploit vulnerabilities on back-end web applications, provided that these can be exploited via the URL.

● The attacker can test for open ports on back-end systems by cycling through large numbers of IP addresses and port numbers. In some cases, timing differences can be used to infer the state of a requested port. In other cases, the service banners from some services may actually be returned within the application’s responses.

Finally, if the application retrieves the external entity but does not return this in responses, it may still be possible to cause a denial of service by reading a file stream indefinitely. For example:

One of the most difficult aspects of writing secure JavaScript code is how easy it is to “accidentally” introduce a vulnerability into an application through simple misconfiguration. Let’s analyze the following code:

While this might seem safe, the eval function is vulnerable here, and attackers can exploit this code. In the code we saw, the eval function evaluates the data that is being passed in dynamically by the user. Therefore, if the user submits a JSON object as expected, the eval function will evaluate that as JSON. However, if the user has malicious intentions and submits an actual JavaScript command such as response.end(“Ended Response”);, the server will evaluate and execute this command, which in this case terminates the response prematurely.

Now that we have introduced a vector to get code execution access on a server, we can shift our attention to determining the types of exploits that can be executed. Traditionally speaking, client-side JavaScript injection vulnerabilities attack users and can be most effective when coupled with some form of social engineering, such as phishing. In the case of SSJI, no social engineering is necessary, and attackers can directly access the filesystem with a combination of a few clever tricks.

By leveraging the Node.js CommonJS API, attackers can require the filesystem (fs) module. The following payloads can then be used to read the contents of the current directory and the previous one:

response.end(require(‘fs’).readdirSync(‘.’).toString()) response.end(require(‘fs’).readdirSync(‘..’).toString())

If these payloads are successfully executed, then the attacker can effectively read any file on the server. Moreover, the attacker could leverage the writeFileSync functionality to write or overwrite any files on the server.

In order to take things one step further, the attacker can require the child_process module in order to execute binary files. The following payload can be used to execute files on the system:

require(‘child_process’).spawn(filename);

Any further exploits are limited only by the attacker’s imagination. To conclude, avoiding the eval function altogether significantly decreases the risk of this vulnerability. Particularly when parsing JSON objects, JSON.parse() is a much safer method. The eval function is used particularly for its speed benefits; however, it can compile and execute any JavaScript code. As demonstrated earlier, this introduces significant risk into the security posture of the application. The following code snippet is a remediated version of the previous vulnerable code. By making a simple substitution of the eval function with the JSON.parse() function, the code is no longer injectable:

var http = require(‘http’); http.createServer(function (request, response) { if (request.method === ‘POST’) { request.addListener(‘data’, function(chunk) { data += chunk; }); request.addListener(‘end’, function() { var bankData = JSON.parse(data); bankQuery(bankData.balance);

We have already said many things about SQL and we have examined a small example in data store injection. Let’s start exploiting a basic SQL Injection vulnerability now, that will help us get inside it and continue in the next module with the advanced topics.

Let’s consider a web application deployed by a book retailer that enables users to search for products by author, title, publisher, and so on. The entire book catalog is held within a database, and the application uses SQL queries to retrieve details of different books based on the search terms supplied by users. When a user searches for all books published by Wiley, the application will execute the following query:

SELECT author,title,year FROM books WHERE publisher = ‘Wiley’ and published=1

This query causes the database to check every row within the books table, extract each of the records where the publisher column has the value Wiley and published has the value 1, and return the set of all these records. The application then processes this record set and presents it to the user within an HTML page.

In this query, the words to the left of the equals sign are SQL keywords and the names of tables and columns within the database. This portion of the query was constructed by the programmer when the application was created. The expression Wiley is supplied by the user, and its significance is as an item of data. String data in SQL queries must be encapsulated within single quotation marks to separate it from the rest of the query.

Now, consider what happens when a user searches for all books published by O’Reilly. This causes the application to perform the following query:

SELECT author,title,year FROM books WHERE publisher = ‘O’Reilly’ and published=1

In this case, the query interpreter reaches the string data in the same way as before. It parses this data, which is encapsulated within single quotation marks, and obtains the value O. It then encounters the expression Reilly’, which is not valid SQL syntax, and therefore generates the following error:

Incorrect syntax near ‘Reilly’. Server: Msg 105, Level 15, State 1, Line 1 Unclosed quotation mark before the character string ‘

When an application behaves in this way, it is wide open to SQL injection. An attacker can supply input containing a quotation mark to terminate the string he controls. Then he can write arbitrary SQL to modify the query that the developer intended the application to execute. In this situation, for example, the attacker can modify the query to return every book in the retailer’s catalog by entering this search term:

As we saw earlier, this will cause the application to perform the following query:

SELECT author,title,year FROM books WHERE publisher = ‘Wiley’ OR 1=1 — ‘ and published=1

This modifies the WHERE clause of the developer’s query to add a second condition. The database checks every row in the books table and extracts each record where the publisher column has the value Wiley or where 1 is equal to 1. Because 1 always equals 1, the database returns every record in the books table.

The double hyphen in the attacker’s input is a meaningful expression in SQL that tells the query interpreter that the remainder of the line is a comment and should be ignored. This trick is extremely useful in some SQL injection attacks, because it enables you to ignore the remainder of the query created by the application developer. In the example, the application encapsulates the user-supplied string in single quotation marks. Because the attacker has terminated the string he controls and injected some additional SQL, he needs to handle the trailing quotation mark to avoid a syntax error, as in the O’Reilly example. He achieves this by adding a double hyphen, causing the remainder of the query to be treated as a comment. In MySQL, you need to include a space after the double hyphen, or use a hash character to specify a comment.

The original query also controlled access to only published books, because it specified and published=1. By injecting the comment sequence, the attacker has gained unauthorized access by returning details of all books, published or otherwise.

There is also an alternative way to handle the trailing quotation mark without using the comment symbol is to “balance the quotes”, in some situations. We finish the injected input with an item of string data that requires a trailing quote to encapsulate it. For example, entering the search term:

Will result in the execution of the following query:

SELECT author,title,year FROM books WHERE publisher = ‘Wiley’ OR ‘a’=’a’ and published=1

This is perfectly valid and achieves the same result as the 1 = 1 attack to return all books published by Wiley, regardless of whether they have been published.

This example shows how application logic can be bypassed, allowing an access control flaw in which the attacker can view all books, not just books matching the allowed filter (showing published books). However, we will describe shortly how SQL injection flaws like this can be used to extract arbitrary data from different database tables and to escalate privileges within the database and the database server. For this reason, any SQL injection vulnerability should be regarded as extremely serious, regardless of its precise context within the application’s functionality.

Different Statement Injection.

The SQL language contains a number of verbs that may appear at the beginning of statements. Because it is the most commonly used verb, the majority of SQL injection vulnerabilities arise within SELECT statements. Indeed, discussions about SQL injection often give the impression that the vulnerability occurs only in connection with SELECT statements, because the examples used are all of this type. However, SQL injection flaws can exist within any type of statement. We need to be aware of some important considerations in relation to each. Of course, when we are interacting with a remote application, it usually is not possible to know in advance what type of statement a given item of user input will be processed by. However, we can usually make an educated guess based on the type of application function you are dealing with. The most common types of SQL statements and their uses are described here.

SELECT Statements: SELECT statements are used to retrieve information from the database. They are frequently employed in functions where the application returns information in response to user actions, such as browsing a product catalog, viewing a user’s profile, or performing a search. They are also often used in login functions where user-supplied information is checked against data retrieved from a database. As in the previous examples, the entry point for SQL injection attacks normally is the query’s WHERE clause. User-supplied items are passed to the database to control the scope of the query’s results. Because the WHERE clause is usually the final component of a SELECT statement, this enables the attacker to use the comment symbol to truncate the query to the end of his input without invalidating the syntax of the overall query. Occasionally, SQL injection vulnerabilities occur that affect other parts of the SELECT query, such as the ORDER BY clause or the names of tables and columns.

INSERT Statements: INSERT statements are used to create a new row of data within a table. They are commonly used when an application adds a new entry to an audit log, creates a new user account, or generates a new order. For example, an application may allow users to self-register, specifying their own username and password, and may then insert the details into the users table with the following statement: INSERT INTO users (username, password, ID, privs) VALUES (‘sample’, ‘magazine’, 2248, 1)

If the username or password field is vulnerable to SQL injection, an attacker can insert arbitrary data into the table, including his own values for ID and privs. However, to do so he must ensure that the remainder of the VALUES clause is completed gracefully. In particular, it must contain the correct number of data items of the correct types. For example, injecting into the username field, the attacker can supply the following: hak’, ‘in9’, 9999, 0) —

This creates an account with an ID of 9999 and privs of 0. Assuming that the privs field is used to determine account privileges, this may enable the attacker to create an administrative user. In some situations, when working completely blind, injecting into an INSERT statement may enable an attacker to extract string data from the application. For example, the attacker could grab the version string of the database and insert this into a field within his own user profile, which can be displayed back to his browser in the normal way.

UPDATE Statements: UPDATE statements are used to modify one or more existing rows of data within a table. They are often used in functions where a user changes the value of data that already exists — for example, updating her contact information, changing her password, or changing the quantity on a line of an order. A typical UPDATE statement works much like an INSERT statement, except that it usually contains a WHERE clause to tell the database which rows of the table to update. For example, when a user changes her password, the application might perform the following query:

UPDATE users SET password=’newsecret’ WHERE user = ‘marcus’ and password = ‘secret’ This query in effect verifies whether the user’s existing password is correct and, if so, updates it with the new value. If the function is vulnerable to SQL injection, an attacker can bypass the existing password check and update the password of the admin user by entering the following username: admin’-

DELETE Statements: DELETE statements are used to delete one or more rows of data within a table, such as when users remove an item from their shopping basket or delete a delivery address from their personal details. As with UPDATE statements, a WHERE clause normally is used to tell the database which rows of the table to update. User-supplied data is most likely to be incorporated into this clause. Subverting the intended WHERE clause can have far-reaching effects, so the same caution described for UPDATE statements applies to this attack.

Continuing, the UNION operator is used in SQL to combine the results of two or more SELECT statements into a single result set. When a web application contains a SQL injection vulnerability that occurs in a SELECT statement, you can often employ the UNION operator to perform a second, entirely separate query, and combine its results with those of the first. If the results of the query are returned to your browser, this technique can be used to easily extract arbitrary data from within the database. UNION is supported by all major DBMS products. It is the quickest way to retrieve arbitrary information from the database in situations where query results are returned directly.

Let’s examine again the application that enabled users to search for books based on author, title, publisher, and other criteria. Searching for books published by Wiley causes the application to perform the following query:

SELECT author,title,year FROM books WHERE publisher = ‘Wiley’

This query will return the author, the title and the year from books with publisher Wiley. A more interesting attack, from the attacks we saw until now, would be to use the UNION operator to inject a second SELECT query and append its results to those of the first. This second query can extract data from a different database table. For example, entering the search term:

Wiley’ UNION SELECT username,password,uid FROM users —

causes the application to perform the following query:

SELECT author,title,year FROM books WHERE publisher = ‘Wiley’ UNION SELECT username,password,uid FROM users — ‘

This returns the results of the original search followed by the contents of the users table. This simple example demonstrates the potentially huge power of the UNION operator when employed in a SQL injection attack. However, before it can be exploited in this way, two important provisos need to be considered:

● When the results of two queries are combined using the UNION operator, the two result sets must have the same structure. In other words, they must contain the same number of columns, which have the same or compatible data types, appearing in the same order.

● To inject a second query that will return interesting results, the attacker needs to know the name of the database table that he wants to target, and the names of its relevant columns.

Let’s look a little deeper at the first of these provisos. Suppose that the attacker attempts to inject a second query that returns an incorrect number of columns. He supplies this input:

Wiley’ UNION SELECT username,password FROM users —

The original query returns three columns, and the injected query returns only two columns. Hence, the database returns the following error:

ORA-01789: query block has incorrect number of result columns

Suppose instead that the attacker attempts to inject a second query whose columns have incompatible data types. He supplies this input:

Wiley’ UNION SELECT uid,username,password FROM users-

This causes the database to attempt to combine the password column from the second query (which contains string data) with the year column from the first query (which contains numeric data). Because string data cannot be converted into numeric data, this causes an error:

ORA-01790: expression must have same datatype as corresponding expression

In many real-world cases, the database error messages shown are trapped by the application and are not be returned to the user’s browser. It may appear, therefore, that in attempting to discover the structure of the first query, you are restricted to pure guesswork. However, this is not the case. Three important points mean that your task usually is easy:

● For the injected query to be capable of being combined with the first, it is not strictly necessary that it contain the same data types. Rather, they must be compatible. In other words, each data type in the second query must either be identical to the corresponding type in the first or be implicitly convertible to it. You have already seen that databases implicitly convert a numeric value to a string value. In fact, the value NULL can be converted to any data type. Hence, if you do not know the data type of a particular field, you can simply SELECT NULL for that field.

● In cases where the application traps database error messages, you can easily determine whether your injected query was executed. If it was, additional results are added to those returned by the application from its original query. This enables you to work systematically until you discover the structure of the query you need to inject.

● In most cases, you can achieve your objectives simply by identifying a single field within the original query that has a string data type. This is sufficient for you to inject arbitrary queries that return string-based data and retrieve the results, enabling you to systematically extract any desired data from the database.

There are small differences between database management systems and those can have a huge impact on the feasibility and the result of an SQL injection attack. It is especially important for us to identify the underlying DBMS since it will allow us to fine tune the injected segment and fully exploit the vulnerability. We are going to see now, the different techniques that can be used to fingerprint a database from an SQL injection.

Firstly, a common practice to extract information about the tested system is to intentionally generate errors. This technique can be useful in order to fingerprint the database, especially when database errors are returned to the end user. The message returned by the DBMS may contain the name and version, but in most cases this is the unique error message structure that will help identify the database. In fact, each DBMS has its own error message template and retracing which DBMS generated the error is quite easy. Here is a classic error:

ORA-01789: query block has incorrect number of result columns.

This example, similar to one we checked earlier, indicates that Oracle is the underlying database. The error prefix “ORA” and the 5 digit error number is characteristic to this specific DBMS.

To continue, the easiest and most accurate way to identify which database is used is to ask the database to identify itself. Before going any further, here is how the database software and version can be obtained with the most popular DBMS, by injecting complete UNION SELECT statements:

● Retrieve Oracle version: SELECT banner FROM v$version WHERE rownum=1

● Retrieve SQL Server or MySQL version: SELECT @@version

Let’s now see how such SELECT statement could be injected in the main query with the use of the UNION operator:

1 AND 1=2 UNION SELECT 1, 2, @@version

This will result in the execution of the following query:

SELECT id, qty, name FROM products WHERE id=1 UNION SELECT 1, 2, @@version

Which will give us the following information:

Microsoft SQL Server 2008 (SP1) — 10.0.2531.0 (X64) Copyright © 1988–2008 Microsoft Corporation Express Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)1

As we can see, not only can we retrieve information about the database software, but the details about the version are also returned. If the underlying database is not up to date, new vectors of attack such as buffer overflows could be explored by the tester.

Inference Database Fingerprinting

Now, given no information is returned to the end user, the attacker could still identify the database by using inference testing. The basic idea is to submit SQL segments that are only valid for one DBMS. If the injected segment is correctly executed, we can conclude that we have discovered which database is used. The process is slightly different depending on the vulnerable parameter type (numeric or string), but the principle is the same.

There are two ways to do so:

Numeric input: Any function that returns a number and exists in only one database system can be used to achieve the fingerprint. If the function injected in the vulnerable parameter is not recognized by the DBMS, an error will be thrown. Otherwise, the function will be executed and the returned value will be integrated in the query. Here is a list of numeric functions that could be used to achieve our tests (all functions listed return 1).

o MySQL numeric function example: POW(1,1)

o Oracle numeric function example: BITAND(1,1)

o SQL Server numeric function example: SQUARE(1)

If we would like to know if the underlying database is MySQL, we would do the following test in this vulnerable site, http://www.website.com/author.php?id=5 :

http://www.victim.com/author.php?id=6-POW(1,1)

If both requests show the same page, we can conclude that MySQL is probably the backend database. Otherwise, the same test should be done with Oracle and MSSQL functions.

Text input: Any function returning predictable text could be used but since concatenation operators are different from one DBMS to another, it is an excellent alternative to functions. Here we can see concatenation operators for the most popular DBMS.

o Oracle concatenation example: ‘abc’ || ‘def’

o MySQL concatenation example: ‘abc’ ‘def’

o SQL Server concatenation example: ‘abc’ + ‘def’

The inference test is pretty similar to what was presented for numeric input. Here is a classic example for text input.

http://www.victim.com/author.php?nickname=SteeveJobs

Which, after the inference test will be (the space character is not URL encoded for simplicity):

http://www.victim.com/author.php?nickname='Steeve' ‘Jobs’

If the same page is returned, MySQL is most likely the DBMS used by the application.

The inference approach could be generalized. In fact, the same result would be obtained by using blind SQL injection in conjunction with any function that exists in only one DBMS. In most cases, a well-crafted SQL segment containing a time-based test will do the job.

Finally, when none of the techniques presented earlier works, assumptions can be made about the database used. The positive is that there is a strong correlation between some technologies and DBMS. For example, a Web application built using ASP.NET is likely to be interacting with an SQL Server database, a PHP website will probably extract its data from MySQL, etc. Common sense will give us a rough idea of how we should orient our SQL injection testing.

Originally published at https://learncybersec.blogspot.com.

Cyber Security Analyst & researcher