在进行APP设计时,要清楚哪些Provider的数据是用户隐私数据或者其他重要数据,考虑是否要提供给外部应用使用,如果不需要提供,则在AndroidManifes文件中将其exported属性显式的设为“false”,这样就会减少了很大一部分的攻击面。
人工排查肯定比较麻烦,建议开发者使用阿里聚安全提供的安全扫描服务,在APP上线前进行自动化的安全扫描,尽早发现并规避这样的风险。
注意:
由于Android组件Content Provider无法在Android 2.2(即API Level 8)系统上设为不导出,因此建议声明最低SDK版本为8以上版本(这已经是好几年前的SDK了,现在一般都会大于此版本);
由于API level 在17以下的所有应用的“android:exported”属性默认值都为true,因此如果应用的Content Provider不必要导出,建议显式设置注册的Content Provider组件的“android:exported”属性为false;
如果必须要有数据提供给外部应用使用,则做好设计,做好权限控制,明确什么样的外部应用可以使用,如对于本公司的应用在权限定义时用相同签名即可,合作方的应用检查其签名;不过还是尽量不提供用户隐私敏感信息。
对于必须暴露的Provider,如第二部分遇到的风险解决办法如下:
3.1 正确的定义私有权限
在AndroidManifest中定义私有权限的语法为:
其中android:protectionLevel的可选值分别表示:
-
normal:默认值,低风险权限,在安装的时候,系统会自动授予权限给 application。
-
dangerous:高风险权限,如发短信,打电话,读写通讯录。使用此protectionLevel来标识用户可能关注的一些权限。Android将会在安装程序时,警示用户关于这些权限的需求,具体的行为可能依据Android版本或者所安装的移动设备而有所变化。
-
signature: 签名权限,在其他 app 引用声明的权限的时候,需要保证两个 app 的签名一致。这样系统就会自动授予权限给第三方 app,而不提示给用户。
-
signatureOrSystem:除了具有相同签名的APP可以访问外,Android系统中的程序有权限访问。
大部分开放的Provider,是提供给本公司的其他应用使用的,一般的话一个公司打包签名APP的签名证书都应该是一致的,这种情况下,Provider的android:protectionLevel应为设为“signature”。
3.2 防止本地SQL注入
注意:一定不要使用拼接来组装SQL语句。
如果Content Provider的数据源是SQLite数据库,如果使用拼接字符串的形式组成原始SQL语句执行,则会导致SQL注入。
如下的选择子句:
如果执行此操作,则会允许用户将恶意 SQL 串连到 SQL 语句上。
例如,用户可以为 mUserInput 输入“nothing; DROP TABLE ** ; ”,这会生成选择子句
var = nothing; DROP TABLE **;
由于选择子句是作为SQL语句处理,因此这可能会导致提供程序擦除基础 SQLite 数据库中的所有表(除非提供程序设置为可捕获 SQL 注入尝试)。
使用参数化查询:
要避免此问题,可使用一个“ ? ” 作为可替换参数的选择子句以及一个单独的选择参数数组。
执行此操作时,用户输入直接受查询约束,而不解释为 SQL 语句的一部分。
由于用户输入未作为 SQL 处理,因此无法注入恶意 SQL。
请使用此选择子句,而不要使用串连来包括用户输入:
String mSelectionClause = “var = ?”;
按如下所示设置选择参数数组:
String[] selectionArgs = {“”};
按如下所示将值置于选择参数数组中:
selectionArgs[0] = mUserInput;
还可调用SQLiteDatabase类中的参数化查询query()方法:
3.3 防止目录遍历
1、去除Content Provider中没有必要的openFile()接口。
2、过滤限制跨域访问,对访问的目标文件的路径进行有效判断:
使用Uri.decode()先对Content Query Uri进行解码后,再过滤如可通过“../”实现任意可读文件的访问的Uri字符串,如:
3.4 通过检测签名来授权合作方应用访问
如果必须给合作方的APP提供Provider的访问权限,而合作方的APP签名证书又于自己公司的不同,可将合作方的APP的签名哈希值预埋在提供Provider的APP中,提供Provider的APP要检查请求访问此Provider的APP的签名,签名匹配通过才让访问。
参考
[1]《内容提供程序基础知识
》
https://developer.android.com/guide/topics/providers/content-provider-basics.html
[2]《Android app端的sql注入》
http://zone.wooyun.org/content/15097
[3]《Android – Content Providers》
http://www.tutorialspoint.com/android/android_content_providers.htm
[4]
http://www.compiletimeerror.com/2013/12/content-provider-in-android.html
[5]
https://developer.android.com/guide/topics/manifest/permission-element.html?hl=zh-cn
[6]
https://developer.android.com/guide/topics/manifest/permission-element.html
[7]
http://www.wooyun.org/bugs/wooyun-2013-039697
[8]
http://www.wooyun.org/bugs/wooyun-2014-057590
[9] 《Android Content Provider Security》
http://drops.wooyun.org/tips/4314
[10]
http://www.wooyun.org/bugs/wooyun-2016-0175294
[11]《Android Content Provider Security
》
http://drops.wooyun.org/tips/4314
[12]
http://www.wooyun.org/bugs/wooyun-2013-044407
[13]
http://www.wooyun.org/bugs/wooyun-2013-044411
[14] 《Content Provider文件目录遍历漏洞浅析》,
https://jaq.alibaba.com/blog.htm?id=61
[15]
https://github.com/programa-stic/security-advisories/tree/master/FacebookLite