💉SQL Injection
Login Bypass
Try seclists wordlist for sql
Favourite:
SQL Basics
Create database
CREATE DATABASE users;
Creating a table
Input longer than 100 characters will give error
To output table structure
DESCRIBE table_name;
Table properties
To auto increment a column, here id for example
id INT NOT NULL AUTO_INCREMENT,
To have unique and not null value
username VARCHAR(100) UNIQUE NOT NULL,
To set default value
date_of_joining DATETIME DEFAULT NOW(),
To set primary key
PRIMARY KEY (id)
Statements
To insert into tables:
INSERT INTO table_name VALUES (column1_value, column2_value, column3_value, ...);
To insert selectively
INSERT INTO table_name(column2, column3, ...) VALUES (column2_value, column3_value, ...);
DROP to remove tables and databases.
ALTER to change the name of any table and any of its fields or to delete or add a new column to an existing table :
ALTER TABLE logins ADD newColumn INT;
Rename:ALTER TABLE logins RENAME COLUMN newColumn TO oldColumn;
Change datatype :ALTER TABLE logins MODIFY oldColumn DATE;
Drop column:ALTER TABLE logins DROP oldColumn;
UPDATE statement can be used to update specific records within a table, based on certain conditions general syntax is
UPDATE table_name SET column1=newvalue1, column2=newvalue2, ... WHERE <condition>;
Example:
UPDATE logins SET password = 'change_password' WHERE id > 1;
Query Results
Sorting results:
Order by column:
SELECT * FROM logins ORDER BY password DESC;
can also omit desc or asc. Can also sort with multiple columns
Limit to limit no of results:
SELECT * FROM logins LIMIT 2;
Can also set an offset to limit fromSELECT * FROM logins LIMIT 1, 2;
. This limits from the id 2 excluding 1.WHERE Clause Used to specify a condition like so
SELECT * FROM table_name WHERE <condition>;
Like Clause To match a certain pattern
SELECT * FROM logins WHERE username LIKE 'admin%';
% is a wildcard.To match with 3 no of characters do this:
SELECT * FROM logins WHERE username like '___';
SQL Injection
Miscellaneous
In oracle databases there is always a table called dual
.
To concatenate two columns use CONCAT
or col1 || '~' || col2
To check for the requests use ffuf: Example:
Usually when database is searched it is in the format of:
Use of sql in php:
F or example if a login form is as follows: SELECT * FROM logins WHERE username='admin' AND password = 'p@ssw0rd';
Discovery
To test for SQLi add any of these and check for errors:
OR injection
AND operator would be evaluated before the OR operator. This means that if there is at least one TRUE condition in the entire query along with an OR operator, the entire query will evaluate to TRUE since the OR operator returns TRUE if one of its operands is TRUE.
So can inject the following: `
` ![[SQL & SQL Injection.png]] The AND operator will be evaluated first, and it will return false. Then, the OR operator would be evalutated, and if either of the statements is true, it would return true. Since 1=1 always returns true, this query will return true, and it will grant us access.
Comments
We can use two types of line comments with MySQL --
and #
, in addition to an in-line comment /**/
Example using --
: SELECT username FROM logins; -- Selects usernames from the logins table
Note: In SQL, using two dashes only is not enough to start a comment. There has to be an empty space after them, so the comment starts with (-- ), with a space at the end. This is sometimes URL encoded as (--+), as spaces in URLs are encoded as (+). To make it clear, we will add another (-) at at the end (-- -), to show the use of a space character.
Example using #
: mysql> SELECT * FROM logins WHERE username = 'admin'; # You can place anything here AND password = 'something'
Note: if you are inputting your payload in the URL within a browser, a (#) symbol is usually considered as a tag, and will not be passed as part of the URL. In order to use (#) as a comment within a browser, we can use '%23', which is an URL encoded (#) symbol.
So auth bypass with previous example would look like SELECT * FROM logins WHERE username='admin'-- ' AND password = 'something';
SQL also has parenthesis for precedence: ![[SQL & SQL Injection-1.png]] The above query ensures that the user's id is always greater than 1, which will prevent anyone from logging in as admin.
Union
Union can be used as follows:
The above query would return username and password entries from the passwords table, assuming the products table has two columns.
Use junk data if columns are uneven:
here 2 is junk data
Union Injection
There are two methods of detecting the number of columns:
Using ORDER BY Keep increasing till an error is caused. If 4 caused an error then 3 columns are present
Using UNION Keep adding junk columns till error.
Not every column is shown to the user so to test which columns are shown can use @@version:
![[SQL & SQL Injection-2.png]]
To check for MySQL:
To check for the column that holds string value:
In oracle there is a builtin table called DUAL
Checking versions:
Reading Files
To get useful information:
To combine columns into one using concatenation:
To check tables in non-oracle databases:
Column in each table in non-oracle databases:
To find current user use any of the following :
For example the union injection in the previous example would be:
or
To check for super admin privileges:
in Union injection:
If Y then true
To show other privileges:
But to show specific user privileges:
To load files:
In union injection:
Can also get source code:
INFORMATION_SCHEMA Database
Check tables in current database:
The INFORMATION_SCHEMA database contains metadata about the databases and tables present on the server.
To reference table in other database use :
The table SCHEMATA in the INFORMATION_SCHEMA database contains information about all databases on the server: The schema_name column contains all database names
To find current database:
To get the table schema of the database called dev
The TABLE_NAME column stores table names, while the TABLE_SCHEMA column points to the database each table belongs to These are the tables in dev database: ![[SQL & SQL Injection-3.png]]
To find column names of credential table:
Write File Privileges
To check:
Or
In union inj:
If empty then can write to any location.
SELECT INTO OUTFILE
To write output of table to a file:
To write anyyyything:
Tip: Advanced file exports utilize the 'FROM_BASE64("base64_data")' function in order to be able to write long/advanced files, including binary data.
Note: To write a web shell, we must know the base web directory for the web server (i.e. web root). One way to find it is to use load_file to read the server configuration, like Apache's configuration found at /etc/apache2/apache2.conf, Nginx's configuration at /etc/nginx/nginx.conf, or IIS configuration at %WinDir%\System32\Inetsrv\Config\ApplicationHost.config, or we can search online for other possible configuration locations. Furthermore, we may run a fuzzing scan and try to write files to different possible web roots, using this wordlist for Linux or this wordlist for Windows. Finally, if none of the above works, we can use server errors displayed to us and try to find the web directory that way.
Writing a Web Shell
We can write this : <?php system($_REQUEST[0]); ?>
In Union injection:
Now to execute commands: http://SERVER_IP:PORT/shell.php?0=id
To access files with shell:
Blind SQL injection
The sql injection can be in a cookie too.
To check use examples like the following:
We can check the difference in the website.
To check if table user is present:
Check if administrator user exists:
Check length of password
Keep increasing to find length of password
Assume a table called Users with Password and Username as columns. To determine the first letter of the password for
Administrator
user:
If this returns true then the first letter is greater than m.
Then we can check for character
t
but it is false:
This returns true so first character is s for sure:
Note: The SUBSTRING
function is called SUBSTR
sometimes.
Error-based SQL Injection
You may be able to induce the application to return a specific error response based on the result of a boolean expression
You may be able to trigger error messages that output the data returned by the query. This turns blind SQL into visible ones
Blind SQL injection by triggering conditional errors
We are using errors just like conditions Some applications carry out SQL queries but their behavior doesn't change, regardless of whether the query returns any data. In this case the BOOLEAN method does not work as we won't see a difference in the Web Application.
NOTE: ORACLE SPECIFIC
With the first input, the
CASE
expression evaluates to'a'
, which does not cause any error.With the second input, it evaluates to
1/0
, which causes a divide-by-zero error. To induce an error:
(TO_CHAR IS ORACLE SPECIFIC)
To check password length:
We can use it like so:
Check for errors:
Extracting Information from Verbose Errors
Occasionally, you may be able to induce the application to generate an error message that contains some of the data that is returned by the query. This effectively turns an otherwise blind SQL injection vulnerability into a visible one.
Most of the times the data is string so trying to convert it to int will cause an error.
Checking with cast:
ERROR: argument of AND must be type boolean, not type integer
We need to make it into a Boolean:
There is a character limit so delete the original trackingID and the following query:
To get password:
Time Delays
Set maximum concurrent requests to 1 in Burp Suite.
Testing (PostgreSQL):
Url encode if doesn't work.
To check if administrator in the users table:
Password length:
Using this technique to get passwords 1 at a time:
out-of-band (OAST) techniques
An application might carry out the same SQL query as the previous example but do it asynchronously. The application continues processing the user's request in the original thread, and uses another thread to execute a SQL query using the tracking cookie.
In this situation, it is often possible to exploit the blind SQL injection vulnerability by triggering out-of-band network interactions to a system that you control. These can be triggered based on an injected condition to infer information one piece at a time.
A variety of network protocols can be used for this purpose, but typically the most effective is DNS. Many production networks allow free egress of DNS queries
Example (MSSQl):
You can use Burp Collaborator to generate a unique subdomain and poll the Collaborator server to confirm when any DNS lookups occur.
To exfiltrate data:
MSSQL
RCE
For MSSQL on windows we can run any code in SQL injection: To get RCE:
Using Public folder as we know it is writeable by all users.
Impersonation
Check users we can impersonate:
To impersonate:
Verifying current user and role:
Linked Database
Enable xp_cmdshell
Sqlmap
To use burp request as parameter pass in -r
Pass in parameter with -p
1 is a dummy value
To dump the database:
To gain shell access:
time-based blind SQLi are not ideal for a shell so we will try an UNION-based SQLi example:
First intercept the POST request and save it as a local file using burp.
Now invoke sqlmap with
-r
parameter to use the request as a parameter:
Automating SQLi
To use burp request as parameter pass in -r
We can use sqlmap to automate this process.
Pass in parameter with -p
1 is a dummy value
To dump the database:
To gain shell access:
time-based blind SQLi are not ideal for a shell so we will try an UNION-based SQLi example:
First intercept the POST request and save it as a local file using burp.
Now invoke sqlmap with
-r
parameter to use the request as a parameter:
For postgresql
SQL Injection in different contexts
XML:
Use hackverter
2nd Order SQL Injection
First-order SQL injection occurs when the application processes user input from an HTTP request and incorporates the input into a SQL query in an unsafe way.
Second-order SQL injection occurs when the application takes user input from an HTTP request and stores it for future use. Also know as stored SQL injection.
Last updated