概述 android |
移动应用开发中,每每有跨进程通讯的需求,方便地实现程序间的数据共享。Android提供了多种IPC通讯的方式,给开发人员带来了便利,但若是选择或使用不当,就有可能发生各类各样的风险。 sql |
|
安全准则 chrome |
A. 应用程序间的数据共享尽可能优先采用content provider,尽可能不要用带全局读写属性的IPC文件进行进程间通讯(好比全局读写的SharedPreferences)。 数据库 B. 若是应用中的content provider、Broadcast Receivers、Activities和Services不须要被其它应用程序访问,应在android manifest文件中显式声明android:exported=”false”。 浏览器 C. 若是组件须要被其它应用程序访问,应使用permission标签设置权限;若是只是在同一开发者开发的程序之间进行IPC,优先考虑使用signature级别的permission; 安全 D. content provider支持对指定的Uri分别设置读写权限,建议只开放能完成任务的最小权限。 网络 E. 使用content provider提供外部应用程序进行数据库存取时应使用带占位符的参数化查询防SQL注入。 app F. 不要使用基于socket的IPC通讯方式。 socket |
|
详细描述 ide |
A. 在android manifest文件中将permission的属性android:protectionLevel设置为”signature”,此时,具备相同签名的而且申请了相应权限的应用才可访问该组件,参考附录4。 B. content provider的独立读写权限设置方法可参考附录5。 C. SQLiteDatabase对象的部份内置方法是能够有效防SQL注入的,好比query(),insert(),update和delete(),另外,正确地使用rawQuery()也能够防止SQL注入,而execSQL()方法建议避免使用,如何正确的使用这些方法和相关错误案例请参考附录3。 |
|
备注 |
A. 当使用基于socket的IPC方式时,设备上的应用均可以访问该监听端口,最差的状况是端口彻底对外开放监听,至关于任何应用均可以经过网络跟该端口进行通讯。 B. 当一个组件定义了intent-filter,其android:exported的默认值为true,不然为false。 |
注:若是IE浏览器显示格式不正确,请使用chrome浏览器。
附录:
11.1.一、使用SQLiteDatabase对象自带的防SQL注入的方法,好比query(),insert(),update和delete():
DatabaseHelper dbhelper = new DatabaseHelper(SqliteActivity.this,"sqliteDB");
SQLiteDatabase db = dbhelper.getReadableDatabase();
/*查询操做,userInputID和userInputName是用户可控制的输入数据 */
Cursor cur = db.query("user", new String[]{"id","name"}, "id=? and name=?", new String[]{userInputID,userInputName}, null, null, null);
/* 插入记录操做*/
ContentValues val = new ContentValues();
val.put("id", userInputID);
val.put("name", userInputName);
db.insert("user", null, val);
/*更新记录操做*/
ContentValues val = new ContentValues();
val.put("id", userInputName);
db.update("user", val, "id=?", new String[]{userInputID });
/*删除记录操做*/
db.delete("user", "id=? and name=?", new String[]{userInputID , userInputName });
11.1.二、正确地使用SQLiteDatabase对象的rawQuery()方法(仅以查询为例):
DatabaseHelper dbhelper = new DatabaseHelper(SqliteActivity.this,"sqliteDB");
SQLiteDatabase db = dbhelper.getReadableDatabase();
/* userInputID和userInputName是用户可控制的输入数据*/
String[] selectionArgs = new String[]{userInputID , userInputName };
String sql = "select * from user where id=? and name=?";//正确!此处绑定变量
Cursor curALL = db.rawQuery(sql, selectionArgs);
11.1.三、如下为错误案例!仅供参考:
DatabaseHelper dbhelper = new DatabaseHelper(SqliteActivity.this,"sqliteDB");
SQLiteDatabase db = dbhelper.getReadableDatabase();
/*案例1:错误地使用rawQuery(),未绑定参数*/
String sql = "select * from user where id='" + userInputID +"'";//错误!动态拼接,未绑定变量
Cursor curALL = db.rawQuery(sql, null);
/*案例2:使用execSQL()方法*/
String sql = "INSERT INTO user values('"+userInputID +"','"+userInputName +"')";//错误同上
db.execSQL(sql);
在应用的AndroidManifest.xml定义以下:
<!- 声明权限 ->
<permission
android:protectionLevel="signature"
android:name="com.hik.helloworld.activity"/>
<activity
android:name="com.hik.helloworld.TestActivity"
android:label="@string/app_name"
android:exported="false"
<!- 为对应组件使用权限 ->
android:permission="com.hik.helloworld.activity">
</activity>
则只有相同数字签名的应用申请该权限后才能够访问该组件。
/* 只容许外部程序对特定Uri进行读操做时的样例设置 */
<provider android:name=". MyContentProvider "
android:authorities=" com.hik.contentprovider.MyContentProvider"
android:exported="true"
android:multiprocess="true"
android:readPermission="
com.hik.contentprovider.MyContentProvider .permission.read">
<path-permission android:pathPattern="/queryData/.*"
android:permission="
com.hik.contentprovider.MyContentProvider .permission.read "/>
</provider>
/* 只容许外部程序对特定Uri进行写操做时的样例设置 */
<provider android:name=". MyContentProvider "
android:authorities=" com.hik.contentprovider.MyContentProvider"
android:exported="true"
android:multiprocess="true"
android:writePermission="
com.hik.contentprovider.MyContentProvider .permission.write">
<path-permission android:pathPattern="/updateData/.*"
android:permission="
com.hik.contentprovider.MyContentProvider .permission.write "/>
</provider>