概述 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>