forked from Trietptm-on-Security/WooYun-2
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Android应用安全开发之浅谈网页打开APP.html
186 lines (104 loc) · 121 KB
/
Android应用安全开发之浅谈网页打开APP.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<html>
<head>
<title>Android应用安全开发之浅谈网页打开APP - 阿里移动安全</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>原文地址:<a href="http://drops.wooyun.org/mobile/15202">http://drops.wooyun.org/mobile/15202</a></h1>
<p>
<p><strong>Author:伊樵,呆狐,<a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="20c8a8bfc6959760c9b89fc9a7acc7879bc5aa88c58ea9c5a588">[email protected]</a><script data-cfhash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script></strong></p>
<h1>0x00 网页打开APP简介</h1>
<hr />
<p>Android有一个特性,可以通过点击网页内的某个链接打开APP,或者在其他APP中通过点击某个链接打开另外一个APP(AppLink),一些用户量比较大的APP,已经通过发布其AppLink SDK,开发者需要申请相应的资格,配置相关内容才能使用。这些都是通过用户自定义的URI scheme实现的,不过背后还是Android的Intent机制。Google的官方文档<a href="https://developer.chrome.com/multidevice/android/intents">《Android Intents with Chrome》</a>一文,介绍了在Android Chrome浏览器中网页打开APP的两种方法,一种是用户自定义的URI scheme(Custom URI scheme),另一种是“intent:”语法(Intent-based URI)。</p>
<!--more-->
<p>第一种用户自定义的URI scheme形式如下:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209202214629140.jpg" alt="p1" /></p>
<p>第二种的Intent-based URI的语法形式如下:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209202650760228.jpg" alt="p2" /></p>
<p>因为第二种形式大体是第一种形式的特例,所以很多文章又将第二种形式叫Intent Scheme URL,但是在Google的官方文档并没有这样的说法。</p>
<p><strong>注意:</strong>使用Custom URI scheme给APP传递数据,只能使用相关参数来传递数据,不能想当然的使用scheme://host#intent;参数;end的形式来构造传给APP的intent数据。详见3.1节的说明。</p>
<p>此外,还必须在APP的Androidmanifest文件中配置相关的选项才能产生网页打开APP的效果,具体在下面讲。</p>
<h1>0x01 Custom Scheme URI打开APP</h1>
<hr />
<h3>1.1 基本用法</h3>
<p>需求:使用网页打开一个APP,并通过URL的参数给APP传递一些数据。 </p>
<p>如自定义的Scheme为:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209202847271319.jpg" alt="p3" /></p>
<p><strong>注意:</strong>uri要用UTF-8编码和URI编码。</p>
<p>网页端的写法如下:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209202951459413.jpg" alt="p4" /></p>
<p>APP端接收来自网页信息的Activity,要在Androidmanifest.xml文件中Activity的intent-filter中声明相应action、category和data的scheme等。 </p>
<p>如在MainActivity中接收从网页来的信息,其在AndroidManifest.xml中的内容如下:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209203180208513.jpg" alt="p5" /></p>
<p>在MainActivity中接收intent并且获取相应参数的代码:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209203319298614.jpg" alt="p6" /></p>
<p>另外还有以下几个API来获取相关信息: </p>
<pre><code>#!bash
getIntent().getScheme(); //获得Scheme名称
getIntent().getDataString(); //获得Uri全部路径
getIntent().getHost(); //获得host
</code></pre>
<h3>1.2 风险示例</h3>
<p>常见的用法是在APP获取到来自网页的数据后,重新生成一个intent,然后发送给别的组件使用这些数据。比如使用Webview相关的Activity来加载一个来自网页的url,如果此url来自url scheme中的参数,如:<code>jaq://jaq.alibaba.com?load_url=http://www.taobao.com</code>。</p>
<p>如果在APP中,没有检查获取到的load_url的值,攻击者可以构造钓鱼网站,诱导用户点击加载,就可以盗取用户信息。</p>
<p>接2.1的示例,新建一个WebviewActivity组件,从intent里面获取load_url,然后使用Webview加载url:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209203478610714.jpg" alt="p7" /></p>
<p>修改MainActivity组件,从网页端的URL中获取load_url参数的值,生成新的intent,并传给WebviewActivity:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209203674488812.jpg" alt="p8" /></p>
<p>网页端:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209203928263910.jpg" alt="p9" /></p>
<p>钓鱼页面:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209204215545109.jpg" alt="p10" /></p>
<p>点击“打开钓鱼网站”,进入APP,并且APP加载了钓鱼网站:</p>
<p><img src="http://static.wooyun.org//drops/20160422/20160422092044681191114.jpg" alt="p11" /></p>
<p><strong>本例建议:</strong><br />
在Webview加载load_url时,结合APP的自身业务采用白名单机制过滤网页端传过来的数据,黑名单容易被绕过。</p>
<h3>1.3 阿里聚安全对开发者建议</h3>
<ol>
<li>APP中任何接收外部输入数据的地方都是潜在的攻击点,过滤检查来自网页的参数。</li>
<li>不要通过网页传输敏感信息,有的网站为了引导已经登录的用户到APP上使用,会使用脚本动态的生成URL Scheme的参数,其中包括了用户名、密码或者登录态token等敏感信息,让用户打开APP直接就登录了。恶意应用也可以注册相同的URL Sechme来截取这些敏感信息。Android系统会让用户选择使用哪个应用打开链接,但是如果用户不注意,就会使用恶意应用打开,导致敏感信息泄露或者其他风险。</li>
</ol>
<h1>0x02 Intent-based URI打开APP</h1>
<hr />
<h3>2.1基本用法</h3>
<p>Intent-based URI语法:</p>
<p><img src="http://static.wooyun.org//drops/20160422/20160422092045385601211.jpg" alt="p12" /></p>
<p><strong>注意:</strong>第二个Intent的第一个字母一定要大写,不然不会成功调用APP。</p>
<p><strong>如何正确快速的构造网页端的intent?</strong></p>
<p>可以先建个Android demo app,按正常的方法构造自己想打开某个组件的Intent对象,然后使用Intent的toUri()方法,会得到Intent对象的Uri字符串表示,并且已经用UTF-8和Uri编码好,直接复制放到网页端即可,切记前面要加上“intent:”。 </p>
<p>如:</p>
<p><img src="http://static.wooyun.org//drops/20160422/20160422092047772571310.jpg" alt="p13" /></p>
<p>结果:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209205169242148.jpg" alt="p14" /></p>
<p>S.load_url是跟的是intent对象的putExtra()方法中的数据。其他类型的数据可以一个个试。</p>
<p>如果在demo中的Intent对象不能传递给目标APP的Activity或其他组件,则其Uri形式放在网页端也不可能打开APP的,这样写个demo容易排查错误。</p>
<p>APP端中的Androidmanifest.xml的声明写法同2.1节中的APP端写法完全一样。对于接收到的uri形式的intent,一般使用Intent的parseUri()方法来解析产生新的intent对象,如果处理不当会产生Intent Scheme URL攻击。</p>
<p><strong>为何不能用scheme://host#intent;参数;end的形式来构造传给APP的intent数据?</strong></p>
<p>这种形式的intent不会直接被Android正确解析为intent,整个scheme字符串数据可以使用Intent的getDataSting()方法获取到。 </p>
<p>如对于:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209205383294158.jpg" alt="p15" /></p>
<p>在APP中获取数据:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209205421707167.jpg" alt="p16" /></p>
<p>结果是:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209205810120179.jpg" alt="p17" /></p>
<p>由上图可知Android系统自动为Custom URI scheme添加了默认的intent。 </p>
<p>要想正确的解析,还需使用Intent的parseUri()方法对getDataString()获取到的数据进行解析,如:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209210067503188.jpg" alt="p18" /></p>
<h3>2.2 风险示例</h3>
<p>关于Intent-based URI的风险我觉得<a href="http://blog.csdn.net/l173864930/article/details/36951805">《Android Intent Scheme URLs攻击》</a>和<a href="http://drops.wooyun.org/papers/2893">《Intent Scheme URL attack》</a>这两篇文章写的非常好,基本把该说的都都说了,我就不多说了,大家看这两篇文章吧。</p>
<h3>2.3 阿里聚安全对开发者建议</h3>
<p>上面两篇文章中都给出了安全使用Intent Scheme URL的方法:</p>
<p><img src="http://static.wooyun.org//drops/20160422/2016042209210170821196.jpg" alt="p19" /></p>
<p>除了以上的做法,还是不要信任来自网页端的任何intent,为了安全起见,使用网页传过来的intent时,还是要进行过滤和检查。</p>
<h1>0x03 参考</h1>
<hr />
<ol>
<li><a href="https://developer.chrome.com/multidevice/android/intents">Android Intents with Chrome</a></li>
<li><a href="http://drops.wooyun.org/papers/2893">Intent scheme URL attack</a> </li>
<li><a href="http://www.jssec.org/dl/android_securecoding_en.pdf">Android Appliaction Secure Design/Secure Coding Guidebook</a></li>
<li><a href="http://developer.android.com/intl/zh-cn/training/app-links/index.html">Handling App Links</a></li>
<li><a href="http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0718/3200.html">Android M App Links: 实现, 缺陷以及解决办法</a></li>
<li><a href="http://blog.csdn.net/l173864930/article/details/36951805">Android Intent Scheme URLs攻击</a></li>
</ol> </p>
</body>
</html>