首先要感谢《android安全攻防实战》这本书。简单实用。这篇文章是我把这本简单总结了下。希望能对大家有所帮助。也非常欢迎大家来反馈,交流。
验证app的签名(防篡改)
首先我们了解下app的证书和签名:
app的证书是以把开发者的id和他们app以密码学的方式关联起来的方式实现的。它被推送到app市场的app中,表示开发者身份。
app的签名确保了不会被其他app所冒充。所以在app被安装之前,都必须要经过签名。
怎么做:
第一种方法:
①:Java JDK中有一个名叫“jarsigner” 的工具,我们可以用它来搞定这个苦差事。你要做的就是执行:
jarsigner -verify -verbose [你的apk文件存放路径]
②:现在,你要做的就是查看屏幕上输出的.jar验证字符串。它表示这个app的签名已经被验证了。
第二种方法:
①获取签名
keytool -list -v -keystore your_app.store
(或者你自己方法获取,直接在打包的地方复制)
②复制SHA1 hash到你的类中设为静态字符串(冒号去掉)
private static String CERTIFICATE_SHA1="你的签名";
③编写运行时获取.apk文件当前签名的代码
我们之前存的签名是SHA1 hash,现在我们一样要转换成(十六进制)格式:
保护app组件
保护app组件的途径有两条:一是正确使用AndroidManifest.xml,二是在代码级别上强制进行权限检查。
首先你要了解你组件的用途、为什么要保护他,以及当一个恶意app向你的app发送intent、访问它的数据时,你的用户将会面临什么样的风险。所以在配置你的AndroidManifest.xml文件,或在你的app中加入权限检查代码之前,先得老老实实回答上面的问题。
怎么做:
一、使用exported属性决定是否允许组件被其他app调用,true为可以。
语法:<组件名 android:exported="false">这里的组件名字可以是activity,provider,service,receiver</组件名>
android 4.2中修改了默认行为(默认为false,即不允许其他app访问,可以把android:minSDKVersion或者android:targetSDKVersion设为17)
二、通过定制权限保护组件
①在添加定制之前,你先得声明表示permission标签的字符串,你可以通过编辑位于你的app项目文件夹中的res/values/strings.xml文件来完成。
<string name="custom_permission_label">Custom Permission</string>
②在你的app中添加保护级别normal的定制权限,你可以通过在AndroidManifest.xml文件夹中加入下列字符串来完成这一任务。
<permission android:name="android:permission.CUSTOM_PERMISSION"
android:protectionLevel="normal"
android:description="My custom permission"
android:label="@string/custom_permission_label">
ps:android:name 定义了权限的名称,也就是用来表示这一权限的字符串值。
android:protectionLevel:它定义了该权限的保护级别,以及控制用户是否被提示同意授予这一权限。
它有四个级别:
normal:不会提示,自动授予。
dangerous:被用来定义那些会使用户暴漏在财务、名誉或法律风险下权限的。
signature:这个权限会被自动赋予那些由定义该权限的app相同签名的app。(自己app共享)
signatureOrSystem:该权限会被自动赋予那些作为系统镜像的一部分。或者有定义该权限的app相同签名的app。
③把自己定制的权限添加到组件中去。
<组件名 ......
android:permission="android.permission.CUSTOM_PERMISSION">
④你也可以通过在app的AndroidManifest.xml文件中添加<uses-permission/>标签的方式,让其他app也能请求这一权限:
<uses-permission android:name="android.permission.CUSTOME_PERMISSION">
保护content provider的路径
由于content provider经常会记录与用户登录活动密切相关的数据,所以在app的各类组件中,content provider可能是最容易被黑客盯上的目标。
关于content provider你必须要知道URI是什么。
URI(Uniform resource identifiers)即统一资源定位符,是content provider用来标识给数据库的。
比如: content://com.myprovider.android/email/inbox
怎么做:
①为了加固你的content provider , 需要设置一个用于管理所有与你的认证相关路径的读和写权限的permission,你可以在你的android manifest 添加下面这个provider。
<provider android:enabled="true"
android:exported="true" //上面已经讲到了,exported为true的时候,外部应用才可以访问到,4.2之后默认为false
android:authorities="com.android.myAuthority"
android:name="com.myapp.provider"
android:permission="[permission name]"></provicer>
ps:[permission name]是其他app读或写必须拥有的权限。
②content provider会有一些他们存放相关数据的content路径,可以给她们加上读写权限。
<provider
android:writePermission="[write permission name]"
android:readPermission="[read permission name]">
</provider>
上面的android:writePermission和android:readPermission用来声明当别的app访问任何读相关(query)或写相关(update和insert)操作时,必须拥有特定权限。读和写必须分别独立进行声明。
例:
Chrome app:
<provider android:name="com.google.androdi.apps.chrome.ChromeBrowserProvider"
android:readPermission="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
android:writePermission="com.android.browser.permission.WIRTE_HISTORY_BOOKMARKS"
android:exported="true"></provider>
我们可以使用AndroidManifest.xml文件中<path-permission>元素,为每个单独的路径设置不同的权限:
<provider......>
<path-permission android:path="/[path name]"
android:permission="[read/write permission name]"
android:readPermissoin="[read permission name]"
android:writePermission="{write permission name">
</provider>
ps:path级的读写权限比provider权限优先级高。
③URI授权:
<provider ..>
<grant-uri-permission android:path="[path name]">
</provider>
(一般不会使用,除非确保其他app都能对某个路径增改查,才可以用。)
防御SQL注入攻击
避免用: SQLiteDatabase.rawQuery();
推荐用:SQLiteStatement(预先编译好,提供对参数的绑定和转换)
和
SQLiteDatabase类中query,insert,update,delete
本篇就写到这,会尽快完成第二篇的总结,如果您看到这了,就评论反馈一下吧。