WebView 常见攻击面

Cookie窃取

能渲染任意url之后, 如何窃取cookie呢?

要能通过file://读到cookie, 那么必须要求setAllowFileAccess(true)来开启webview的文件系统访问.

在API29及以下默认设置为 true.

与之相关的两个相关的配置:

  1. setAllowFileAccessFromFileURLs(true): 允许通过file://访问的页面中js加载file://的资源
  2. setAllowUniversalAccessFromFileURLs(true) 允许通过file://访问的页面中js加载任意协议的资源

注意这里侧重的是限制资源的加载而不是访问, 比如通过http外带的时候, 请求是能发出去的, 只是不能通过http加载资源, 本质上是防XSS.

任意url加载

1. 应用克隆

条件 setAllowFileAccess(true) && (setAllowFileAccessFromFileURLs(true) || setAllowUniversalAccessFromFileURLs(true))

首先操作webview加载attack.html, 通过js中的file://直接读取出cookie, 再通过之类的label将cookie传出来.

2. 移花接木

条件 setAllowFileAccess(true) , 仅限Android7以下.

首先操纵webview去加载attack.html, attack.html中js的效果是延迟一段时间读取自身(正是因为这里是读取自身, 所以只需要setAllowFileAccess), 此时攻击app将attack.html替换为指向目标cookie文件的软链接, 再次读取时就会以受害app的权限读取出cookie文件. 最后传出.

(但这个延迟读取自身的方法似乎在新版chrome中不太行了, 测了一下即使是完全相同的file://路径也会被认为是不同源. 因为file://时origin直接设为了null).

3. 含沙射影

条件 setAllowFileAccess(true)
首先操纵webview访问setCookie.html, 里面的js将该站点的cookie设置为一段嵌入的恶意payload, 然后再次操纵webview访问attack.html, 它是一个指向cookie文件的软链接,这一步是为了伪造.html的后缀.在加载cookie文件时, 刚刚嵌入的恶意代码执行, 读取cookie并传出. 这里的读取Cookie可以直接获取document的内容而不走file://协议, 所以不会有跨域的问题.


总结

为什么不能直接通过file://读取cookie? 其实是可以的, 但关键在于读取+传出的连续动作.

如果要布置读取+传出的连续动作, 那么就需要将访问file://的js嵌在html里, 那么就会受到setAllowFileAccessFromFileURLs和setAllowUniversalAccessFromFileURLs的限制. 而方法2,3就是对限制的绕过.

loadDataWithBaseURL

https://developer.android.google.cn/develop/ui/views/layout/webapps/load-local-content#loadDataWithBaseUrl

如果能控制第二个参数就能进行xss, 如果能同时控制前两个参数可以进行任意域名下的xss绕过同源.

1
2
3
4
val html = "<html><body><p>Hello world</p></body></html>"
val baseUrl = "https://example.com/"

webView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl)

URL 校验

很多APP的开发者会把自己的域名作为白名单域名,然后对这个域名进行检查,如果检查通过才会打开高敏感权限的JsInterface接口,或者说让WebView去加载。这就导致有很多误用URL进行检查的案例。

以及loadUrl和Uri.parse的解析差异, android 8.1及之前有效.

如果直接从外部取uri而没有经过Uri.parse, 可以通过反射构造herachical Uri绕过.

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2025 翰青HanQi

请我喝杯咖啡吧~

支付宝
微信