查看原文
其他

回环域名解析遇上跨 App 攻击

0xcc 非尝咸鱼贩 2023-02-13

刚过完了一个小长假,也该开始干活了。之前预告过接下来会写一些 iOS 第三方 App 安全漏洞相关的文章,就以这篇开始。本文要介绍的案例利用场景有较高要求(从恶意 iOS App 发起攻击),导致危害相对有限;但漏洞原理结合了一些看上去风马牛不相及的跨界知识,倒也有些趣味。




跨 iOS App 的攻击有不少资料,例如这篇 NDSS 2015 的论文:


Unauthorized Cross-App Resource Access on MAC OS X and iOS


Xing L, Bai X, Li T, et al. Unauthorized cross-app resource access on mac os x and ios[J]. arXiv preprint arXiv:1505.06836, 2015.


https://arxiv.org/abs/1505.06836


作者将其命名为 XARA(Cross-App Resource Access)。攻击的场景是假设用户安装了带有恶意代码的 iOS 或 macOS 应用(还记得几年前的 Xcode 投毒事件吗?),恶意代码通过跨进程调用触发特定的漏洞,造成跨 App 的敏感信息被窃取,相当于部分绕过系统 App 之间原本的沙箱隔离机制。


而在移动平台上主要是 URL Scheme 这个输入点。


URL scheme 是主流移动操作系统上拉起 App 的主要方式,可以从浏览器跳转到应用,也可以在应用之间互相传递数据。在 OAuth 一键登录和移动支付等场景都有应用。


例如在 MobileSafari 的地址栏输入 sms://10086,确认之后会跳转到短信的发送界面。URL scheme 可以在 hostname、pathname 和 querstring 部分携带参数,具体解析逻辑由 App 自行实现。


假设最坏的情况,用户手机上安装了恶意应用,可能会针对 URL scheme 做两种文章:劫持攻击和作为输入向量触发安全漏洞。


劫持就是利用了 iOS 第三方应用同名的 scheme 优先级顺序难以保证的问题,抢注和知名应用相同的 URL,从而在本应该打开 B 应用的时候跳转到 A,并截获 URL 当中的参数。


而另一种则是利用 URL scheme 直接触发反序列化、XSS 等漏洞。




笔者在一些真实的移动 App 上遇到了一种有趣的场景。


  1. 应用导出了一种可以打开任意(或信任列表内)网址的 url scheme,如 xwebview://www.example.com,在 WebView 当中打开 www.example.com

  2. example.com 本身有一些子域名解析到 127.0.0.1(loopback,回环,也就是本机)


这两种情况结合会产生什么问题呢?


假设有一个域名 localhost.example.com 被解析到 127.0.0.1,那么用 xwebview://localhost.example.com 实际上打开的网页是 http://127.0.0.1。


在 iOS 上监听 80 端口不需要特殊权限,任意一个 App 都可以。Android 和一些主流操作系统都限制了小于 1024 端口的 TCP 监听权限需要 root 或管理员。这还给了一个额外的好处,就是最终的 URL 不需要使用非标准端口,不会有 localhost:81 和 localhost:80 被视作不同源的问题。


场景如下:


  • 恶意 App A 首先在后台启动一个 http 服务放在 http://127.0.0.1

  • 接下来用 xwebview:// 打开要攻击的 App B。在第一次切换 App 的时候 iOS 会询问用户是否打开,攻击者可以伪装成 OAuth 一键登录等场景诱导点击

  • iOS 对后台应用有冻结措施,需要调用相关 API(如音频播放、后台任务)保持活跃

  • App B 这时候以 localhost.example.com 访问由 App A 提供的网页

  • 在笔者遇到的案例中,example.com 的 cookie 都能被二级域名访问到;或者 App 本身的 WebView 提供了一些特殊 jsbridge 接口,但只有 *.example.com 能访问

  • 此时 App A 的恶意网页得到了 example.com 的敏感信息或者特殊权限


用这种思路能直接获得一些 App 的登陆状态 token,已经报告并得到修复。




回过头来看,为什么这些厂商需要把 localhost.example.com 解析到 127.0.0.1 呢?这是由于 PC 时代的遗留代码所致。


早期一些桌面客户端为了在网页中提供快捷访问的功能,会在本地特定端口直接运行一个『虫洞』 Web 服务,通过 AJAX 等方式直接和客户端交互。为了方便干脆就给了一个二级域名。


更有甚者,因为浏览器禁止在 https 加密页面中混合未加密的 URL 载入,客户端有时候会启用 https,要么强制在操作系统中安装自签名证书的根证书,要么把受信任的网站证书私钥直接打包到客户端程序,很容易通过逆向调试提取到。这种做法还会给用户造成中间人劫持的风险。


原本在桌面端,运行恶意程序本身具有的权限就比较高,没有必要通过在别的应用里打开一个网页的形式获取敏感信息。


到了移动 App 的场景,由于操作系统的安全设计,App 之间默认是不可以互相读取数据的。这种攻击变得有意义起来。


相对彻底的解决方案最好还是弃用类似的域名,毕竟 127.0.0.1 的内容不可控,变成了一个官方的 MITM 渠道。即使需要也应该使用独立的域名,例如 Amazon Music 就有这样一个 amazonmusiclocal.com 是解析到回环的,但即使有相关漏洞也显然不可能读到主站的信息。


客户端止血,可以在一开始处理 URL scheme 的时候拉黑一些已知的遗留域名。




关于 URL scheme 的安全漏洞检测并没有特别好的办法,主要还是要靠提取 App 可执行文件之后查看反汇编(编译)结果。


App 的 URL scheme 会保存在 Info.plist 当中。之前推送的 Grapefruit 工具有一个 URL scheme 的测试功能,可以直接列出所有的项目并填入参数测试:



但主要的工作量还是靠逆向,盲测甚至 fuzz 基本不会有收获。




这个安全风险的场景确实非常有限,要求安装恶意 App 并有一些交互,所以实际危害不大。


然而从这个案例我们可以发现,一些看上去不相关的小问题有时候会巧合般的被结合在一起。


像回环域名这种东西,相当于提供了一个官方的 MITM 渠道。只不过这个中间的坏人不需要真正截取流量,而只需下载打开一个看上去人畜无害的 App 就够了。




放假在家比较懒,封面图第一次没有用自己做的。来源 unsplash

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存