邮件原子分裂:利用解析器绕过访问控制
引言
有些网站会解析电子邮件地址以提取域名,并推断所有者所属的组织。这种模式使得电子邮件地址解析器的差异变得至关重要。预测电子邮件将被路由到哪个域名本应很简单,但实际上却异常困难——即使是“有效的”、符合RFC规范的地址也是如此。
在本文中,我将向您展示如何将电子邮件解析差异转化为访问控制绕过甚至远程代码执行(RCE)。
本文附带一个免费的在线CTF,因此您将能够立即尝试您的新技能集。
您还可以将本文作为打印/下载友好的PDF获取。您还可以从Black Hat获取幻灯片。
我在Black Hat和DEF CON上做了这个演讲。您可以在这里观看:
大纲
- 引言
- 创建电子邮件域名混淆
- 解析器差异
- Unicode溢出
- 编码字
- 编码字案例研究
- GitHub
- Zendesk
- Gitlab
- PHPMailer
- Punycode
- 什么是Punycode?
- 畸形Punycode
- 尝试利用Joomla
- 利用Joomla
- 方法论/工具
- 生成电子邮件分裂攻击
- 自动化利用编码字
- 模糊测试畸形Punycode
- 奖励材料
- 防御
- 材料
- CTF
- 时间线
- 参考资料
引言
一些规定电子邮件地址格式的RFC已经存在了50多年,它们被混杂在一起形成了一个过于宽松的电子邮件地址标准。电子邮件可以包含引用值、注释、转义和各种编码。如果您面临编写电子邮件解析器的任务,技术上您应该遵循规范,但由于所有这些复杂性,这是一项困难的工作。Web应用程序将这种复杂性外包给电子邮件解析库,因此它们实际上不知道电子邮件是如何被解析的。当它们决定基于电子邮件域名做出安全决策时,这就会导致问题。
如果您查看RFC2822的3.2.5和3.2.2节,它允许您使用引用值和转义。它们使您能够在电子邮件地址的本地部分使用通常不允许的字符。一些例子是:
|
|
在第一个例子中,由于本地部分被引用,at符号将用作目标邮箱,并移除引号。在第二个例子中,它展示了如何在引用的本地部分内部使用转义来将双引号用作目标邮箱。如果我们更深入地看同一RFC节的3.2.3,我们可以看到它支持注释。注释是使用括号构造的,可以包含空格甚至嵌套。以下是一些使用注释的“有效”电子邮件示例:
|
|
您不仅限于字母数字值;您可以在注释中放置多种字符。这一切似乎都 ripe for abuse,通过在解析器、应用程序和邮件程序之间制造混淆。我的研究之旅始于试图通过滥用转义和注释来制造这种混淆。
创建电子邮件域名混淆
关于我如何发现这一点,我对此故事并不自豪,但这是事实。我并没有花几个小时用调试器查看Postfix和Sendmail的源代码,而且肯定有随机性和运气的成分。
事情始于我登录一个用于测试的盒子时,我安装了一个未命名的应用程序,并开始测试其电子邮件解析差异。我一无所获。我尝试的一切都失败了,我完全放弃了这项研究的想法。然后,出于绝望的行为,我复制了应用程序使用的特殊字符并将其粘贴到我的电子邮件地址中。我知道这会有效,因为这都是它们允许的字符,但我只是想看看邮件程序会发生什么。
我检查了盒子的系统日志,注意到我收到了一个带有无效主机的DSN(投递状态通知)。对此感到惊讶,我开始深入研究。我开始从电子邮件地址中移除字符,以缩小Sendmail认为它是无效主机的原因。最终,我将其缩小到感叹号,并记得在进行这项研究时读到的UUCP协议。
UUCP是一种在互联网和电子邮件之前存在的古老协议。它允许您在Unix系统之间发送消息,并代表Unix到Unix复制。它使用感叹号作为域和用户部分之间的分隔符,但顺序与传统电子邮件地址相反。
这太疯狂了,纯粹是运气,我粘贴的字符以反斜杠结尾,这转义了at符号,然后感叹号将地址视为UUCP地址!以下是我的发现:
原始发现:
|
|
自然,我必须使用不同的Collaborator域名进行跟进,以确认它实际上会转到不同的服务器:
|
|
前面的例子在使用Sendmail 8.15.2时,会转到Collaborator域名"oastify.com",而不是example.com。这对我来说非常令人兴奋,因为我证明了这项研究实际上是有进展的。下一步是找到导致这种行为的其他字符,所以我很快编写了一个SMTP模糊测试器。我发现Postfix没有这种行为,因为它更安全,对吧?嗯,这就是我最初的想法,直到我通过模糊测试器在Postfix 3.6.4中发现了一个变体:
|
|
这实际上会转到psres.net而不是example.com,并使用了另一个古老的协议,称为源路由。源路由允许您使用一系列服务器链来发送邮件。想法是您用逗号分隔每个主机,然后在末尾包括最终目的地。还有所谓的“百分比黑客”,即邮件程序将%或不同的选定字符转换为at符号,然后将电子邮件转发到服务器。这个例子说明了这一点:
|
|
在这个过程中,电子邮件最初发送到example.com,之后百分比符号转换为at符号,并发送电子邮件到foo@psres.net。这正是该向量发生的情况,括号注释掉了电子邮件地址的域名部分,然后Postfix使用本地部分作为源路由,将电子邮件发送到意外的目的地。Postfix实际上也支持UUCP。我后来发现,如果您使用单括号技巧。
这些发现使我相信外面有大量的错误,因此我开始寻找更多。
解析器差异
Unicode溢出
我在这项研究中必须解决的主要问题之一是生成被阻止的字符。由于许多Web应用程序会阻止多个at符号。这就是我开始研究unicode溢出的原因。
我正在测试一个未命名的目标,并注意到当使用较高的unicode字符时,它们会生成其他ASCII字符。这种模式起初看起来是随机的,但后来我理解了发生了什么。最好通过PHP中chr()算法的工作原理来说明。chr()函数返回由整数代码点指定的字符:
在示例中,PHP循环遍历字节并检查它是否小于零,如果是,则添加256直到它为正。然后它执行模运算以将值拟合到0-255范围内。这意味着如果您传递一个大于255的字节值,它将因模运算而溢出并被强制进入0-255范围。这正是unicode溢出的工作原理;我们只需要提供一个代码点大于255的字符来生成其他字符。这最好用一个简单的例子来说明:
|
|
在前面的例子中,我使用fromCodePoint函数生成一个字符,我传递一个十六进制值0x100,转换为十进制256,然后我添加0x40,这是at符号的十六进制数。然后当系统执行像PHP中的chr()函数这样的操作时,unicode代码点将溢出并拟合到0-255范围内,然后生成at符号。
在我发现这一点之后,我开始用Turbo Intruder对未命名目标进行模糊测试,并注意到其他字符也表现出这种行为。起初看起来是随机的,但后来我意识到发生了什么,0x100只是您可以用来执行溢出的数字之一。如果您使用更高的字符,您可以使用介于其间的任何字符。
|
|
上面的每个十六进制值都会创建溢出,因为模运算将导致零,并且这可以继续直到当前最大unicode代码点0x10ffff。这个目标允许各种unicode字符创建其他字符:
|
|
如果您对每个字符执行256模运算,它将产生生成的字符:
|
|
尽管我能够欺骗广泛的字符,但我无法在此未命名目标上使用此技术分裂电子邮件。但这只是开始,我证明了生成被阻止字符是可能的。这给了我寻找更多的信心。
编码字
我开始看得越多,电子邮件RFC想要给予的越多。在这项研究之前,我假设电子邮件通常是字母数字,本地部分中带有点。我从未想象过存在一个完整的复杂编码系统,允许您执行多层编码。然而,这就是我发现的。仔细阅读RFC,我注意到了rfc2047和编码字,这种编码系统允许您使用十六进制和base64表示字符。
如果我们使用编码电子邮件作为示例说明:
|
|
“=?”表示编码字的开始,然后您指定字符集,这里是UTF-8。然后问号分隔下一个命令,即“q”,表示“Q-Encoding”,之后有另一个问号表示编码格式的结束和编码数据的开始。Q-Encoding简单地说就是带有等号前缀的十六进制。在这个例子中,我使用=41=42=43,这是大写的“ABC”。最后,?=表示编码的结束。当电子邮件库解析时,电子邮件目的地将是ABCUSER@psres.net!
有了这些信息,我开始寻找使用这种编码解析电子邮件的真实系统。为了帮助这一点,我想出了两个探针,在大多数具有此行为的站点上都有效:
最初我使用字符集“x”来减小探针的大小,但是一些系统拒绝未知字符集并会失败。最好使用这两个探针,因为在测试了许多站点后,我发现它们是最常见的允许字符集。使用Collaborator生成有效载荷,并将上面的“collab”替换为生成的。然后,如果您在SMTP对话的RCPT TO命令中获得SMTP交互:
|
|
这然后证明电子邮件解析器正在用“编码字”解码电子邮件。
我发现了许多具有此行为的站点,它们都有一个共同点。Ruby。看起来它们都使用同一个名为“Mail”的Ruby Gem,它有超过5.08亿次下载。我开始查看源代码,我发现该库正在解码UTF-7!在我的测试台中,我试图重现这一点:
|
|
这太疯狂了!电子邮件现在可以有UTF-7了!然后一个想法突然出现在我的脑海中:如果有Q-Encoding和字符集,你能同时拥有两者吗?这个问题的惊人答案是响亮的“是”。您可以将UTF-7与Q-Encoding混合!
|
|
之后,我开始玩base64编码,因为当然“编码字”在电子邮件中支持那个!您只需在编码类型中使用“b”而不是“q”,就可以使用它。
|
|
前面的例子使用base64编码的字符串“foobar”,它被解析器解码。我知道您在想什么,或者也许只是我,但是是的,您可以使用UTF-7和base64编码的数据:
|
|
在这个例子中,有一个带有UTF-7字符集的base64编码地址。首先,电子邮件解析器将解码base64。然后,电子邮件解析器将解码UTF-7字符集。最后,电子邮件将被解码为foobar@psres.net。在这一点上,您可能对严格遵循RFC有些怀疑。尤其当我告诉您,在我测试Mail库时,这在域名部分也有效。注意我在这里使用字母数字值,但您当然也可以编码任何特殊字符。
编码字案例研究
GitHub:访问受Cloudflare“Zero Trust”保护的内部网络
到目前为止,我们已经看到了如何创建电子邮件域名混淆和令人惊讶的编码,但是是时候利用这些知识来利用真实系统了。我测试的第一个目标是GitHub。我特别针对GitHub,因为我知道它是用Ruby编写的。
我使用前面提到的两个探针来确认GitHub支持“编码字”。电子邮件在Collaborator SMTP对话中被解码!所以我开始进一步测试。我需要做的是使用“编码字”来产生另一个at符号。起初,我开始玩引用的本地部分值,我成功地在引用值中嵌入了原始at符号。也许我可以在引用的本地部分内部使用“编码字”来跳出引用值并产生两个不同的地址?我尝试了=22(双引号)和=40(at符号),但没有成功。
这项研究的麻烦在于,有时您得不到任何反馈,因为它通过了电子邮件验证,但在到达邮件程序之前失败了。您可以使用DNS交互作为线索,但它们通常几乎无用,因为您无法识别未能到达邮件程序的原因。
经过多次尝试,我开始考虑SMTP对话,并尝试放置大于号字符。这里的想法是,我可以使用它来结束SMTP对话中的RCPT TO命令:
|
|
前面的例子显示了一个带有原始at符号和大于号的引用本地部分。您可以看到攻击如何形成。您有两个地址,使用大于号的想法将使您能够忽略SMTP对话中的第二个地址。有了这个想法固定在我的脑海中,我开始使用编码向量来构建攻击。
我很快发现双引号对GitHub没有任何用处,原因是它总是留下一个开放的双引号,这将使验证失败。我当然尝试了编码和转义,但没有成功。我移除了引号,并使用“编码字”生成at符号和大于号,它通过了验证,但我没有收到电子邮件。没有SMTP对话。什么都没有。考虑到这一点,我认为也许电子邮件末尾的尾随垃圾导致邮件程序失败,无论是异常还是验证。如果我能引入一些字符来避免异常或验证呢?我尝试了编码的空白,但失败了,然后我尝试了编码的null,然后成功了!我有了以下电子邮件的交互:
|
|
对于GitHub,字符集无关紧要,所以我使用了“x”,编码的at符号(=40)被转换为at,大于号(=3e)结束RCPT TO命令,最后null(=00)使邮件程序忽略之后的所有内容,您需要在编码后放置一个有效的本地部分,所以我使用了“foo”,这成功通过验证并分裂了电子邮件。然后我可以验证任何我喜欢的电子邮件域名。我已经用microsoft.com、mozilla.com和github.com验证了我的测试帐户上的地址:
|
|
这已经是一个错误,因为您不应该能够验证您不拥有的地址。然后我的同事James Kettle建议我查看Cloudflare“Zero Trust”,看看是否可以配置为信任某些电子邮件域名。我创建了一个测试帐户并深入研究配置,发现您可以使用GitHub作为IdP,并使用电子邮件域名来确定您是否有权访问站点。这可能是内部网络或任何其他受Zero Trust保护的域名,只要它们使用GitHub作为IdP。
Zendesk:访问受电子邮件域名保护的支持中心
在GitHub取得成功后,我开始寻找使用Ruby并具有某种形式的电子邮件域名验证的应用程序。一个突出的是Zendesk,因为也许您可以访问受保护的支持台?在尝试分裂电子邮件地址之前,我搜索了他们的文档,发现您需要打开支持中心,允许注册,然后选择允许注册的域名。
支持中心配置好后,我开始测试。我尝试了所有在GitHub上使用的攻击,但没有成功。也许他们使用了不同的邮件程序或验证?我尝试了一些新想法,使用电子邮件的引用本地部分,并且我在Collaborator中得到的交互似乎比测试GitHub时更有希望。
我发现有用的是使用两个重复的Collaborator域名,这样我总是得到交互,并且通过检查SMTP对话,您可以看到什么被转换了。我发送了以下内容:
|
|
这个交互告诉了我几件事:首先是它们允许大写。其次是它们允许转换后的空格,第三是当解码时,它们似乎引用本地部分中通常不允许的值。也许我可以滥用这种行为?
经过更多尝试后,我终于取得了一些进展。我欺骗了解析/验证来转换被阻止的字符,双重编码的引号,并生成将被其代码移除的字符,直到最终我构建了一个有效的电子邮件分裂攻击:
|
|
使用这个“电子邮件”,我能够绕过支持中心设置的限制。此攻击的关键是解析器解码的嵌入编码引号。然后=3c22生成一个小于字符,该字符被移除,然后完成引号,从而通过它们的验证/异常。您会注意到“=3e=00”是我在GitHub上使用的相同序列,所以它们显然共享一些相同的代码,但它们的响应方式有很大不同,因此攻击更加复杂。
Gitlab:未经授权访问Gitlab Enterprise服务器
寻找更多Ruby新鲜目标,我转向了Gitlab。它们是一个IdP并提供企业产品,因此似乎是一个很好的测试目标。James有一个他之前测试过的Gitlab服务器,所以我首先开始研究那个。您可以配置它允许具有特定域名的注册。这立即引起了我的注意。我尝试了在GitHub和Zendesk上使用的向量,但它们没有奏效。然后我记得“编码字”允许您使用下划线作为空格,而这个向量是我迄今为止演示过的最优雅的:
|
|
我使用配置的Enterprise实例的邮件程序Postfix。您可以使用=20做同样的事情,但下划线是1个字符,我喜欢优雅的向量!
这意味着我可以访问使用基于域名的注册限制的Gitlab Enterprise服务器。正如我提到的,Gitlab也是一个IdP,所以我也开始测试Web应用程序。企业黑客在这里不起作用。我认为那是因为它们使用了不同的邮件程序。然而,我没花多长时间就找到了另一个向量。到目前为止,我已经收集了一堆向量,所以我有一个Turbo Intruder脚本,它遍历所有已知向量并尝试其他向量。它发现了一个使用编码空格的新向量,这很有意义,因为它在企业产品上有效,只是需要不同的方法来利用:
|
|
它与Github漏洞非常相似,但需要有效的字符集,并且需要空格而不是null。在图中我使用了“x”,但在真实攻击中,您会使用“iso-8859-1”。
PHPMailer
不幸的是,我并没有利用我测试的所有东西,并且有很多失败。每一个都是一个学习过程,但这个案例研究有趣的是,“编码字”在非Ruby系统上被解析和解码。
我已经按照James的建议构建了一个测试台,所以我开始测试PHPMailer如何解析电子邮件。我进行了黑盒和白盒测试的混合,我发现它不会在电子邮件地址的本地部分或域名部分解析“编码字”。然而,它确实在电子邮件地址外部的名称部分解析并解码它!
|
|
分析代码,尖括号是必需的,这意味着它经常在像Wordpress这样的应用程序中验证失败。我尝试在各种应用程序的名称参数中嵌入有效载荷,但无法利用这个特定的库。尽管如此,我打赌您可以用“编码字”嵌入XSS有效载荷,并且这将在某个地方有效。如果您设法做到,请与我联系,我很想听听。
Punycode
我们已经探索了如何操纵电子邮件解析以规避访问控制。但让我们更进一步。如果电子邮件地址可以被武器化以获得远程代码执行(RCE)呢?在本节中,我们将介绍Punycode攻击以及我如何利用Joomla。
什么是Punycode?
Punycode是一种在当前DNS系统中表示unicode字符的方式。Punycode总是以xn–开头,后跟连字符和字母数字字符。非ASCII字符使用一种特殊算法进行编码,该算法表示这些字符。该算法将Unicode字符序列转换为仅利用ASCII字符的表示形式。该算法规定,通常输入中不形成unicode字符的任何ASCII字符将按原样添加到输出中。例如,域名münchen.com使用以下Punycode序列编码。
|
|
Punycode的工作方式使其难以测试,因为更改一个字符会影响整个输出和字符位置,这是由于算法的工作方式。我们想要做的是在编码值被解码时生成恶意字符,而这样做是一个巨大的挑战。在以下示例中,您可以看到当一个字节被修改时,unicode字符的位置会发生变化。
|
|
畸形Punycode
在Wikipedia上阅读了所有相关内容后,我点击了一个在线Punycode转换器的链接。该转换器使用了IDN PHP库,并开始尝试各种Punycode地址。我发现,如果您在开头使用两个零,您可以生成意外的字符:
|
|
这是我第一次成功创建畸形Punycode的尝试。输入包含Punycode“xn–0049”,由于有缺陷的库,它解码为逗号。我能够使用这种技术生成更多字符:
|
|
有许多方法可以生成相同的字符。我考虑了电子邮件分裂攻击,但我得出结论,Punycode地址在发送电子邮件时不会被解码,因为那将是无效的。更有可能的是,它在显示电子邮件时被解码。自然,我问自己的问题是:你能创建一个XSS向量吗?
这是一个模糊测试器的任务。我开始构建一个,它立即开始产生有趣的结果:
|
|
我认为这是找到使用IDN PHP库的应用程序的好时机。在搜索Github后,我找到了一个有趣的目标使用该库:Joomla!这很棒,因为如果我得到XSS,那么我就有RCE。进行源代码分析,我注意到它们在Punycode解码之前对用户的电子邮件进行了转义。这意味着如果我能产生一些畸形Punycode,解码时产生HTML,我就能得到XSS,但这不会那么容易。
尝试利用Joomla
我带着兴奋回到我的模糊测试器,开始生成数百万个字符组合。我设法构建了部分XSS向量,但遇到了几个问题。我只能通过使用多个Punycode子域名生成两个ASCII字符。这种限制源于Punycode算法、PHP的具体工作方式以及有缺陷的PHP IDN库的怪癖。正如您在示例中看到的,我很接近,但这些问题使得利用Joomla非常困难。
|
|
我得出结论,XSS不可行,因为尽管我能够生成一个单引号HTML属性,但它需要一个下划线字符。然而,Joomla不允许在电子邮件地址的域名部分使用下划线。
利用Joomla实现RCE
那么故事就这样结束了吗?不完全是这样。我思考了一段时间,并想出,如果您使用单个Punycode子域名,您可以生成任何开始标签!最终,经过大量测试,我得出结论,唯一可利用的向量是一个开始样式标签:
|
|
预先存在的Joomla HTML代码的其余部分将添加一个空格和闭合尖括号。电子邮件在用户列表页面上输出。这意味着它是持久的,甚至不需要激活的帐户。您可以简单地注册一个用户,它将是持久的样式注入!但是我们如何将我们的邪恶CSS放入那里?为此,您需要一个地方来放置CSS而不被阻止。用户的名称字段是一个不错的选择,您可以使用@import导入邪恶样式。
我遇到的问题是,样式注入之后发生的所有HTML代码都将被视为CSS!要解决这个问题,您只需要欺骗CSS解析器,使其认为这都是无效的CSS选择器,这意味着只需使用{}。所以,如果您在名称字段的开头放置after,那么您可以在之后导入样式。攻击如下工作:
|
|
注意第一个帐户名称有一个“a”,第二个帐户名称有“x”,这是为了确保样式注入首先发生,第二个帐户使用@import。花括号用于将导入之前发生的所有HTML视为无效CSS选择器。Chrome的严格CSS mime类型检查在这里也不适用,因为使用了内联样式。
我们现在需要做的是通过CSS渗出CSRF令牌,幸运的是已经有很多关于这方面的好文章。最好的方法是使用导入链并使用d0nut和Pepe Vila开发的一个工具。我决定定制我已经用我的盲CSS渗出研究开发的工具,这涉及使其提取特定的Joomla令牌。我将在帖子后面的Github仓库中分享定制的代码。
随着我的CSS渗出器运行,我注册了两个帐户,并使用超级管理员帐户访问了用户页面。渗出器显示了管理员的CSRF令牌,所以下一步是向管理员提供使用渗出的令牌的CSRF漏洞利用。我的渗出器也构建CSRF漏洞利用。该漏洞利用然后修改管理员模板以获得RCE!
这是攻击的演示:
在视频中,颜色较浅的管理员浏览器在左侧,颜色较深的攻击者浏览器在右侧。攻击者注册两个帐户,第一个从畸形Punycode地址注入样式标签,第二个注入CSS渗出样式表。然后管理员访问后端和用户列表页面,恶意CSS立即加载并在几秒钟内渗出令牌。
一旦发生这种情况,攻击者就会收到管理员的CSRF令牌的通知,然后开始与管理员进行即时消息对话。管理员点击来自攻击者的链接,并被CSRF攻击以编辑后端模板,注入一些PHP,调用系统命令来cat /etc/passed。
方法论/工具
在进行这项研究时,我开发了一个在测试时发现有用的方法论。探测、观察、编码和利用。首先使用本文中提到的探针,然后在像Collaborator这样的工具中观察结果。重复这个过程,直到您拥有攻击所需的字符。然后当这个过程完成时,进行利用。您可以将此方法论应用于编码字和Punycode攻击。
首先探测“编码字”,观察解码后的电子邮件以确认它受支持。然后编码各种字符并观察它们如何被解码。然后跟进利用这些字符的攻击。
为了观察结果,我使用了Burp Collaborator,它允许我查看SMTP交互。
使用Hackvertor标签生成电子邮件分裂攻击
为了帮助找到电子邮件分裂攻击,我创建了几个Hackvertor标签。Hackvertor是我编写的另一个免费的Burp Suite扩展,它允许您在请求中使用标签并对数据执行嵌套转换。您只需将标签放在您希望unicode溢出发生的地方,然后将您想要转换的字符放在标签内部:
|
|
第一个标签创建单个unicode溢出,并使用标签参数0x100(十进制256)创建溢出。第二个使用标签参数作为最大unicode代码点,并生成尽可能多的字符,这些字符溢出到标签内部指定的字符。第三个标签将允许您执行编码字转换,在示例中我编码@符号。第四个标签将解码编码字序列。还有更多标签可以帮助创建和解码UTF-7电子邮件和编码字元字符。
要使用这些标签,您需要在Hackvertor菜单中启用“允许代码执行标签”。然后在同一菜单中点击“查看标签存储”。您可以通过点击它们的名称然后使用安装按钮来安装这两个标签。
使用Turbo Intruder自动化利用编码字
当我发现前几个错误时,我发现自动化对于找到其他错误非常有用,而Turbo Intruder通常非常有用来自动化这个过程。Turbo Intruder是另一个由James Kettle编写的免费Burp扩展。我创建了一个Turbo Intruder脚本来帮助利用邮件程序。当您已识别服务器支持编码字,但您想知道邮件程序是否允许您通过使用null或其他字符来分裂电子邮件时,使用此脚本。
它使用一系列已知的技术来分裂电子邮件,这些是我在测试GitHub、Zendesk、Gitlab、Bugcrowd和许多其他平台时发现的。您可以轻松自定义脚本以执行本演示中提到的其他攻击。要使用它,您只需要将validServer变量更改为您要欺骗的目标域名。然后您将%s放在请求中您想要添加电子邮件的位置,然后右键单击请求并发送到Turbo Intruder并使用修改后的脚本。然后运行攻击。如果攻击有效,您应该在Turbo Intruder内收到Collaborator交互。这意味着电子邮件域名是可欺骗的。如果您遇到具有速率限制的应用程序(就像我一样),您可以更改REQUEST_SLEEP变量以与这些服务器友好相处。
模糊测试畸形Punycode
我创建了一个Punycode模糊测试器来帮助找到畸形Punycode。我与我的PortSwigger同事分享了它,并创建了一个挑战,看看是否有人能在我有限制的情况下生成XSS向量。没有人成功,但我还是通过CSS渗出获得了RCE。模糊测试器的工作原理是给它一些带有Punycode地址的输入,占位符被随机数字、字符或空格替换。匹配和包含只是匹配模糊测试输出的正则表达式。它在找到可以生成的字符方面非常有效。
奖励材料
在DEF CON上,我展示了一些奖励向量,因为我有额外的5分钟时间。 RFC允许所谓的SMTP可选参数。其中一个参数“ORCPT”可用于走私电子邮件地址的域名部分并更改其目的地。由于许多应用程序通常接受引用的本地部分但错误处理转义字符,您可以滥用此来更改电子邮件目的地:
|
|
这种技术在Postfix中有效,但可能其他邮件程序也有效。 作为进一步的奖励,这里有一些更多令人惊讶的电子邮件解析行为 我发现的在Postfix中有效。我无法将这些用于访问控制绕过 但它们仍然有趣,并挑战您对如何 解析电子邮件地址的假设。第一个使用UUCP,并且无论 引号如何都会发送。
输入: “psres.net!collab”("@example.com 导致电子邮件发送至: collab@psres.net
第二个使用源路由 即使有方括号语法。 输入: collab%psres.net@[127.0.0.1] 导致电子邮件发送至: collab@psres.net
防御
我建议您在使用电子邮件解析库时禁用“编码字”。作为最后的手段,您可以通过使用以下正则表达式在电子邮件地址中查找“编码字”的开始和结束字符来防止其使用:
|
|
即使电子邮件来自SSO提供商(如GitHub),您也应始终验证电子邮件地址。永远不要使用电子邮件域名作为授权的唯一手段,因为正如我们所看到的,它很容易被欺骗。
参考资料
在进行这项研究时,一些博客文章/幻灯片确实鼓舞人心。我强烈建议您阅读每一篇,因为它们包含非常有用的信息。我用来渗出CSRF令牌的导入链技术来自Pepe Vila和d0nut。
电子邮件解析: https://www.jochentopf.com/email/address.html https://nathandavison.com/blog/exploiting-email-address-parsing-with-aws-ses https://medium.com/@fs0c131y/tchap-the-super-not-secure-app-of-the-french-government-84b31517d144
CSS渗出: https://vwzq.net/slides/2019-s3_css_injection_attacks.pdf https://d0nut.medium.com/better-exfiltration-via-html-injection-31c72a2dae8b
材料
这项研究的所有材料可在Github仓库获取
CTF
我们在Web Security Academy上创建了一个CTF,以便您可以尝试新技能。为方便起见,我还在Git仓库的Joomla目录中创建了一个带有Joomla易受攻击版本的docker文件。
时间线
- 2024年1月30日下午3:40报告给Joomla - 2024年2月20日修复 CVE-2024-21725
- 2024年2月8日上午11:49报告给IdnaConvert PHP库 - 2024年2月14日修复
- 2024年2月5日上午11:55报告给Gitlab - 2024年4月25日修复
- 2024年2月5日上午11:55报告给Github - 2024年5月9日修复
- 2024年2月5日下午2:54报告给Zendesk - 2024年5月9日修复
要点
有效的电子邮件地址可能触发主要的解析器差异 即使地址以“@example.com”结尾,也可能转到其他地方。 因此,使用电子邮件域名进行访问控制强制执行永远不安全