安卓開發開發規範手冊V1.0

tdaxia發表於2019-09-03

安卓開發開發規範手冊V1.0

之前釋出過一份Web安全開發規範手冊V1.0,看到收藏文章的讀者挺多,發現整理這些文件還挺有意義。

最近週末抽了些時間把之前收集關於安卓安全開發的資料也整理了一下,整理出一份安卓安全開發手冊,大部分內容都是在一些部落格看到各位師傅的分享。

一、manifest檔案安全

1.1 禁止PermissionGroup的屬性為空

PermissionGroup可以對permission進行一個邏輯上的分組。如果PermissionGroup的屬性為空,會導致許可權定義無效,且其他app無法使用該許可權。

開發建議

設定PermissionGroup屬性值或者不使用PermissionGroup

1.2 系統許可權確認

App如果使用一些系統限制許可權,諸如android.permission.WRITE_SECURE_SETTINGS和android.permission.INSTALL_PACKAGES,則該app應該是裝置自帶的系統或google自帶的app,並且應該放置在/system/app目錄下。否則就是一個惡意app。

App使用下述許可權,則該app有較高許可權,要謹慎使用。

android.permission.MOUNT\_FORMAT\_FILESYSTEMS,

android.permission.MOUNT\_UNMOUNT\_FILESYSTEMS,

android.permission.RESTART\_PACKAGES。

開發建議

根據業務需求,如非必要,移除該許可權。

1.3 protectionLevel屬性設定

由於對app的自定義permission的protectionLevel屬性設定不當,會導致元件(如:content provider)資料洩露危險。最好的許可權設定應為signature或signatureOrSystem,進而避免被第三方應用利用。

開發建議

注意使用signature或signatureOrSystem防止其他app註冊或接受該app的訊息,提高安全性。

1.4 合理設定sharedUserId許可權

通過sharedUserId,可以讓擁有同一個User Id的多個apk執行在同一個程式中,互相訪問任意資源。將sharedUserId設定為android.uid.system,可以把app放到系統程式中,app將獲得極大的許可權。如果app同時有master key漏洞,容易導致被root。

開發建議

合理設定軟體許可權。

1.5 設定allowBackup為false

當這個標誌被設定成true或不設定該標誌位時,應用程式資料可以備份和恢復,adb除錯備份允許惡意攻擊者複製應用程式資料。

開發建議

設定AndroidManifest.xml的android:allowBackup標誌為false。

影響範圍

API >= 8

1.6 禁止Debuggable為true

在AndroidManifest.xml中定義Debuggable項,如果該項被開啟,app存在被惡意程式除錯的風險,可能導致洩露敏感資訊等問題。

開發建議

顯示的設定AndroidManifest.xml的debuggable標誌為false。

二、元件安全

2.1 合理設定匯出Activity、activity-alias、service、receiver

Activity、activity-alias、service、receiver元件對外暴露會導致資料洩露和惡意的dos攻擊。

開發建議

  1. 最小化元件暴露。對不會參與跨應用呼叫的元件新增android:exported=false屬性。
  2. 設定元件訪問許可權。對跨應用間呼叫的元件或者公開的receiver、service、activity和activity-alias設定許可權,同時將許可權的protectionLevel設定為signature或signatureOrSystem。
  3. 元件傳輸資料驗證。對元件之間,特別是跨應用的元件之間的資料傳入與返回做驗證和增加異常處理,防止惡意除錯資料傳入,更要防止敏感資料返回。

2.2 Contentprovider資訊洩露風險

provider元件匯出可能會帶來資訊洩露隱患。api level在17以下的所有應用的android:exported屬性預設值為true,17及以上預設值為false。

開發建議

  1. 最小化元件暴露。對不會參與跨應用呼叫的元件新增android:exported=false屬性。
  2. 設定元件訪問許可權。對匯出的provider元件設定許可權,同時將許可權的protectionLevel設定為signature或signatureOrSystem。
  3. 由於Contentprovider無法在2(API-8)申明為私有。故建議將min sdk設為8以上。

影響範圍

api level在17以下的所有應用的android:exported屬性預設值為true,17及以上預設值為false。

2.3 嚴格過濾openFile對uri訪問

該漏洞由於Content provider元件暴露,沒有對Content provider元件訪問許可權進行限制且對Uri路徑沒有進行過濾,攻擊者通過Content provider實現的OpenFile介面進行攻擊,如通過../的方式訪問任意的目錄檔案,造成隱私洩露。

開發建議

  1. 將不必要匯出的Content provider設定為不匯出
  2. 由於Android元件Content provider無法在Android 2.2(即API Level 8)系統上設為不匯出,因此如果應用的Content provider不必要匯出,阿里聚安全建議宣告最低SDK版本為8以上版本;
  3. 由於API level 在17以下的所有應用的android:exported屬性預設值都為,因此如果應用的Content provider不必要匯出,阿里聚安全建議顯示設定註冊的Content provider元件的android:exported屬性為false;
  4. 去除沒有必要的penFile()介面
  5. 如果應用的Content provider元件沒有必要實現penFile()介面,阿里聚安全建議移除該Content provider的不必要的penFile()介面。
  6. 過濾限制跨域訪問,對訪問的目標檔案的路徑進行有效判斷
  7. 使用decode()先對Content Query Uri進行解碼後,再過濾如可通過../實現任意可讀檔案的訪問的Uri字串;
  8. 設定許可權來進行內部應用通過Content provider的資料共享
  9. 使用簽名驗證來控制Content provider共享資料的訪問許可權,如設定protectionLevel=signature或signatureOrSystem;
  10. 公開的content provider確保不儲存敏感資料
  11. 提供asset檔案時注意許可權保護

2.4 使用顯式Intent 呼叫bindService()

建立隱式Intent 時,Android 系統通過將Intent 的內容與在裝置上其他應用的清單檔案中宣告的Intent 過濾器進行比較,從而找到要啟動的相應元件。如果Intent 與Intent 過濾器匹配,則系統將啟動該元件,並將其傳遞給物件。如果多個Intent 過濾器相容,則系統會顯示一個對話方塊,支援使用者選取要使用的應用。

為了確保應用的安全性,啟動Service 時,請始終使用顯式Intent,且不要為服務宣告Intent 過濾器。使用隱式Intent 啟動服務存在安全隱患,因為您無法確定哪些服務將響應Intent,且使用者無法看到哪些服務已啟動。從Android 5.0(API 級別21)開始,如果使用隱式Intent 呼叫bindService(),系統會丟擲異常。

開發建議

為了確保應用的安全性,啟動 Service 時,請始終使用顯式 Intent,且不要為服務宣告 Intent 過濾器。使用隱式 Intent 啟動服務存在安全隱患,因為您無法確定哪些服務將響應Intent,且使用者無法看到哪些服務已啟動。從 Android 5.0(API 級別 21)開始,如果使用隱式 Intent 呼叫 bindService()),系統會丟擲異常。

影響範圍

全部。從Android 5.0(API 級別21)開始,如果使用隱式Intent 呼叫bindService(),系統會丟擲異常。

2.5 合理處理Intent Scheme URL

Intent Scheme URI是一種特殊的URL格式,用來通過Web頁面啟動已安裝應用的Activity元件,大多數主流瀏覽器都支援此功能。

Android Browser的攻擊手段——Intent Scheme URLs攻擊。這種攻擊方式利用了瀏覽器保護措施的不足,通過瀏覽器作為橋樑間接實現Intend-Based攻擊。相比於普通Intend-Based攻擊,這種方式極具隱蔽性,

如果在app中,沒有檢查獲取到的load_url的值,攻擊者可以構造釣魚網站,誘導使用者點選載入,就可以盜取使用者資訊。所以,對Intent URI的處理不當時,就會導致基於Intent的攻擊。

如果瀏覽器支援Intent Scheme URI語法,一般會分三個步驟進行處理:

  1. 利用parseUri解析uri,獲取原始的intent物件;
  2. 對intent物件設定過濾規則;
  3. 通過startActivityIfNeeded或者startActivity傳送intent;其中步驟2起關鍵作用,過濾規則缺失或者存在缺陷都會導致Intent Schem URL攻擊。

關鍵點

Intent.parseUri函式,通過掃描出所有呼叫了Intent.parseUri方法的路徑,並檢測是否使用如下的策略。

比較安全的使用Intent Scheme URI方法是:

如果使用了Intent.parseUri函式,獲取的intent必須嚴格過濾,intent至少包含addCategory(android.intent.category.BROWSABLE),setComponent(null),setSelector(null)3個策略。

所以,在檢的時候只要根據Intent.parseUri函式返回的Intent物件有沒有按照以下方式實現即可做出判斷:

// convert intent scheme URL to intent object

Intent intent = Intent.parseUri(uri);

 // forbid launching activities without BROWSABLE category

intent.addCategory(android.intent.category.BROWSABLE);

// forbid explicit call

intent.setComponent(null);

 // forbid intent with selector intent  intent.setSelector(null);

// start the activity by the intent

context.startActivityIfNeeded(intent, -1)

開發建議

如果使用了Intent.parseUri函式,獲取的intent必須嚴格過濾,intent至少包含addCategory(android.intent.category.BROWSABLE),setComponent(null),setSelector(null)3個策略。除了以上做法,最佳處理不要信任任何來自網頁端的任何intent,為了安全起見,使用網頁傳過來的intent時,要進行過濾和檢查

2.6 本地拒絕服務

Android系統提供了Activity、Service和Broadcast Receiver等元件,並提供了Intent機制來協助應用間的互動與通訊,Intent負責對應用中一次操作的動作、動作涉及資料、附加資料進行描述,Android系統則根據此Intent的描述,負責找到對應的元件,將Intent傳遞給呼叫的元件,並完成元件的呼叫。Android應用本地拒絕服務漏洞源於程式沒有對Intent.GetXXXExtra()獲取的異常或者畸形資料處理時沒有進行異常捕獲,從而導致攻擊者可通過向受害者應用傳送此類空資料、異常或者畸形資料來達到使該應用Crash的目的,簡單的說就是攻擊者通過Intent傳送空資料、異常或畸形資料給受害者應用,導致其崩潰。

對匯出的元件傳遞一個不存在的序列化物件,若沒有try...catch捕獲異常就會崩潰

ComponentName cn = new ComponentName(com.test, com.test.TargetActivity)

Intent i = new Intent()

i.setComponentName(cn)

i.putExtra(key, new CustomSeriable())

startActivity(i)

**public class DataSchema implements Serializable {**

        public DataSchema() {

                super();

        }

}

2.6.1 NullPointerException 異常導致的拒絕服務

源於程式沒有對getAction()等獲取到的資料進行空指標判斷,從而導致了空指標異常導致應用崩潰

風險程式碼:

Intent i = new Intent();

if (i.getAction().equals(TestForNullPointerException)) {

    Log.d(TAG, Test for Android Refuse Service Bug);

}

2.6.2 ClassCastException 異常導致的拒絕服務

源於程式沒有對getSerializableExtra()等獲取到的資料進行型別判斷而進行強制型別轉換,從而導致型別轉換異常導致拒絕服務漏洞

風險程式碼:

Intent i = getIntent();

String test = (String) i.getSerializableExtra(serializable\_key);

**IndexOutOfBoundsException 異常導致拒絕服務漏洞**

源於程式沒有對getIntegerArrayListExtra()等獲取到的資料陣列元素大小判斷,導致陣列訪問越界而造成拒絕服務漏洞

風險程式碼:

Intent intent = getIntent();

ArrayList<Integer> intArray = intent.getIntegerArrayListExtra(user\_id);

if (intArray != null) {

    for (int i = 0; i < 10; i++) {

        intArray.get(i);

    }

}

2.6.3 ClassNotFoundException 異常導致的拒絕服務漏洞

Intent i = getIntent();

getSerializableExtra(key);

開發建議

  1. 將比不要匯出的組建設定為不匯出
  2. 在處理Intent資料時,進行捕獲異常,通過getXXXExtra()獲取的資料時進行以下判斷,以及用try catch方式捕獲所有異常,防止出現拒絕服務漏洞,包括:空指標異常、型別轉換異常、陣列越界訪問異常、類未定義異常、其他異常
Try{

    ....

xxx.getXXXExtra()

....

}Catch Exception{

**   **  **// 為空即可**

}

2.7 合理定義android.intent.category.BROWSABLE

在AndroidManifest檔案中定義了android.intent.category.BROWSABLE屬性的元件,可以通過瀏覽器喚起,這會導致遠端命令執行漏洞攻擊

開發建議

  1. APP中任何接收外部輸入資料的地方都是潛在的攻擊點,過濾檢查來自網頁的引數
  2. 不要通過網頁傳輸敏感資訊,有的網站為了引導已經登入的使用者到APP上使用,會使用指令碼動態的生成URL Scheme的引數,其中包括了使用者名稱、密碼或者登入態token等敏感資訊,讓使用者開啟APP直接就登入了。惡意應用也可以註冊相同的URL Sechme來擷取這些敏感資訊。Android系統會讓使用者選擇使用哪個應用開啟連結,但是如果使用者不注意,就會使用惡意應用開啟,導致敏感資訊洩露或者其他風險。

2.8 刪除Debug和Test資訊

一些app在正式釋出前,為了方便除錯app,都會在app裡整合一些除錯或測試介面。這些測試介面可能包含敏感的資訊。

開發建議

在正式釋出前移除所有的測試元件

2.9 Intent不安全反射風險

通過Intent接收的Extra引數來構造反射物件會導致從不受信任的源載入類。攻擊者可以通過巧妙地構造達到載入其它類的目的

兩個關鍵函式,分別是:getIntent()和Class.forName(....)

public class SecondActivity extends Activity {

        @Override

            protected void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                setContentView(R.layout.activity\_second);

                Intent intent = getIntent();

                String className = intent.getStringExtra(className);

                String methodName = intent.getStringExtra(methodName);

                try {

                        Class<?> clz = null;

                        clz = Class.forName(className);

                        Date object = (Date) clz.newInstance();

                        Method method = clz.getMethod(methodName);

                        Toast.makeText(getApplicationContext(), method.invoke(object, null) + ======, Toast.LENGTH\_LONG).show();

                } catch (Exception e) {

                        e.printStackTrace();

                }

        }

}

逆向後對應的smali程式碼如下:


invoke-virtual {p0}, Lcom/bug/intent/reflection/SecondActivity;->getIntent()Landroid/content/Intent;

invoke-static {v0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;

開發建議

  1. 不要通過Intent接收的Extra傳播的反射函式
  2. 將接受反射的元件設定為非匯出元件

三、webview元件安全

3.1 WebView遠端執行漏洞

和WebView遠端程式碼執行相關的漏洞主要有CVE-2012-6336,CVE-2014-1939,CVE-2014-7224, 這些漏洞中最核心的漏洞是CVE-2012-6336,另外兩個CVE只是發現了幾個預設存在的介面。

Android API < 17之前版本存在遠端程式碼執行安全漏洞,該漏洞源於程式沒有正確限制使用addJavaScriptInterface(CVE-2012-6636)方法,攻擊者可以通過Java反射利用該漏洞執行任意Java物件的方法,導致遠端程式碼執行安全漏洞除。

開發建議

  1. API等於高於17的Android系統。出於安全考慮,為了防止Java層的函式被隨意呼叫,Google在2版本之後,規定允許被呼叫的函式必須以@JavascriptInterface進行註解。
  2. API等於高於17的Android系統。建議不要使用addJavascriptInterface介面,以免帶來不必要的安全隱患,如果一定要使用該介面:
  3. 如果使用https協議載入url,應用進行證照校驗防止訪問的頁面被篡改掛馬
  4. 如果使用http協議載入url,應進行白名單過濾、完整性校驗等防止訪問的頁面被篡改
  5. 如果載入本地html,應將html檔案內建在apk中,以及進行對html頁面完整性的校驗
  6. 使用removeJavascriptInterface移除Android系統內部的預設內建介面:searchBoxJavaBridge_、accessibility、accessibilityTraversal

範圍:

CVE-2012-6636

Android API 16.0及之前的版本中存在安全漏洞,該漏洞源於程式沒有正確限制使用WebView.addJavascriptInterface方法。遠端攻擊者可通過使用Java Reflection API利用該漏洞執行任意Java物件的方法

Google Android <= 4.1.2 (API level 16) 受到此漏洞的影響。

CVE-2014-1939

java/android/webkit/BrowserFrame.java

使用addJavascriptInterface API並建立了SearchBoxImpl類的物件。攻擊者可通過訪問searchBoxJavaBridge_介面利用該漏洞執行任意Java程式碼。

Google Android <= 4.3.1 受到此漏洞的影響

CVE-2014-7224

香港理工大學的研究人員發現當系統輔助功能中的任意一項服務被開啟後,所有由系統提供的WebView都會被加入兩個JS objects,分別為是accessibility和accessibilityTraversal。惡意攻擊者就可以使用accessibility和accessibilityTraversal這兩個Java Bridge來執行遠端攻擊程式碼.

Google Android < 4.4 受到此漏洞的影響。

3.2 WebView潛在XSS攻擊

允許WebView執行JavaScript(setJavaScriptEnabled),有可能導致XSS攻擊。

開發建議

應儘量避免使用。如果一定要使用:

  1. API等於高高於17的Android系統。出於安全考慮,為了防止Java層的函式被隨意呼叫,Google在2版本之後,規定允許被呼叫的函式必須以@JavascriptInterface進行註解。
  2. API等於高高於17的Android系統。建議不要使用addJavascriptInterface介面,一面帶來不必要的安全隱患,如果一定要使用該介面:
  3. 如果使用https協議載入url,應用進行證照校驗防止訪問的頁面被篡改掛馬
  4. 如果使用http協議載入url,應進行白名單過濾、完整性校驗等防止訪問的頁面被篡改
  5. 如果載入本地html,應將html檔案內建在apk中,以及進行對html頁面完整性的校驗
  6. 使用removeJavascriptInterface移除Android系統內部的預設內建介面:searchBoxJavaBridge_、accessibility、accessibilityTraversal

影響範圍

Android api <17

3.3 WebView File域同源策略繞過

應用程式一旦使用WebView並支援File域,就會受到該漏洞的攻擊。該漏洞源於:JavaScript的延時執行能夠繞過file協議的同源檢查,並能夠訪問受害應用的所有私有檔案,即通過WebView對Javascript的延時執行和將當前Html檔案刪除掉並軟連線指向其他檔案就可以讀取到被符號連結所指的檔案,然後通過JavaScript再次讀取HTML檔案,即可獲取到被符號連結所指的檔案。

大多數使用WebView的應用都會受到該漏洞的影響,惡意應用通過該漏洞,可在無特殊許可權下盜取應用的任意私有檔案,尤其是瀏覽器,可通過利用該漏洞,獲取到瀏覽器所儲存的密碼、Cookie、收藏夾以及歷史記錄等敏感資訊,從而造成敏感資訊洩露。

開發建議

  1. 將不必要匯出的元件設定為不匯出

    如果應用的元件不必要匯出,建議顯式設定所註冊元件的android:exported屬性為false;

  2. 如果需要匯出元件,禁止使用File域

    如果應用的需要匯出包含WebView的元件,建議禁止使用File域協議:

myWebView.getSettings. setAllowFileAccess(false);

  1. 如果需要使用File協議,禁止File協議呼叫JavaScript

    如果應用的WebView需要使用File域協議,建議禁止File域協議呼叫JavaScript:

myWebView.getSettings. setJavaScriptEnabled(false);

3.4 禁止webview密碼明文儲存

webview的儲存密碼功能預設設定為true。Webview會明文儲存網站上的密碼到本地私有檔案databases/webview.db中。對於可以被root的系統環境或者配合其他漏洞(如webview的同源繞過漏洞),攻擊者可以獲取到使用者密碼。

image

開發建議

顯示設定webView.getSetting().setSavePassword(false)

3.5 主機名弱校驗漏洞

自定義HostnameVerifier類,卻不實現verify方法驗證域名,導致中間人攻擊漏洞。

開發建議

自定義HostnameVerifier類並實現verify方法驗證域名。

3.6 證照弱校驗漏洞

App在實現X509TrustManager時,預設覆蓋google預設的證照檢查機制方法:checkClientTrusted、checkServerTrusted和getAcceptedIssuers,會導致中間人攻擊漏洞。

開發建議

如果自己建立X509Certificate,則在覆蓋checkClientTrusted、checkServerTrusted和getAcceptedIssuers後要進行校驗。

3.7 中間人攻擊漏洞

App呼叫setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER),信任所有主機名,會導致中間人攻擊。

開發建議

查詢所有設定了ALLOW_ALL_HOSTNAME_VERIFIER欄位屬性的方法路徑;對信任的主機嚴格認證

3.8 WebView不校驗證照漏洞

Android WebView元件載入網頁發生證照認證錯誤時,會呼叫WebViewClient類的onReceivedSslError方法,如果該方法實現呼叫了handler.proceed()來忽略該證照錯誤,則會受到中間人攻擊的威脅,可能導致隱私洩露。

自定義實現的WebViewClient類在onReceivedSslError是否呼叫proceed()方法。

開發建議

當發生證照認證錯誤時,採用預設的處理方法handler.cancel(),停止載入問題頁面當發生證照認證錯誤時,採用預設的處理方法handler.cancel(),停止載入問題頁面

3.9 WebView元件系統隱藏介面未移除

android webview元件包含3個隱藏的系統介面:searchBoxJavaBridge_,accessibilityTraversal以及accessibility,惡意程式可以利用它們實現遠端程式碼執行。

風險程式碼:

const-string v3, searchBoxJavaBridge\_

invoke-virtual {v1, v3}, Landroid/webkit/WebView;->removeJavascriptInterface(Ljava/lang/String;)V

const-string v3, accessibility

invoke-virtual {v1, v3}, Landroid/webkit/WebView;->removeJavascriptInterface(Ljava/lang/String;)V

const-string v3, accessibilityTraversal

invoke-virtual {v1, v3}, Landroid/webkit/WebView;->removeJavascriptInterface(Ljava/lang/String;)V

開發建議

使用了WebView,那麼使用WebView.removeJavascriptInterface(String name) API,顯示的移除searchBoxJavaBridge_、accessibility、accessibilityTraversal這三個介面

影響範圍

4.0~4.4(不包含)

四、sqlite安全

4.1 SQLite sql注入漏洞

SQLite做為android平臺的資料庫,對於資料庫查詢,如果開發者採用字串連結方式構造sql語句,就會產生sql注入。

開發建議

  1. provider不需要匯出,請將export屬性設定為false
  2. 若匯出僅為內部通訊使用,則設定protectionLevel=signature
  3. 不直接使用傳入的查詢語句用於projection和selection,使用由query繫結的引數selectionArgs
  4. 完備的SQL隱碼攻擊語句檢測邏輯

4.2 Databases任意讀寫漏洞

APP在使用openOrCreateDatabase建立資料庫時,將資料庫設定了全域性的可讀許可權,攻擊者惡意讀取資料庫內容,獲取敏感資訊。在設定資料庫屬性時如果設定全域性可寫,攻擊者可能會篡改、偽造內容,可以能會進行詐騙等行為,造成使用者財產損失。

開發建議

  1. 用MODE_PRIVATE模式建立資料庫
  2. 使用sqlcipher等工具加密資料庫
  3. 避免在資料庫中儲存明文和敏感資訊

網路通訊安全

5.1 SSL不安全元件

SSLCertificateSocketFactory#getInsecure方法無法執行SSL驗證檢查,使得網路通訊遭受中間人攻擊。

開發建議

移除SSLCertificateSocketFactory#getInsecure方法。

5.2 HttpHost安全

HttpHost target = new HttpHost(uri.getHost(), uri.getPort(), HttpHost.DEFAULT_SCHEME_NAME);

HttpHost.DEFAULT_SCHEME_NAME預設是http,不安全。

開發建議

改成使用https

5.3 HttpURLConnection漏洞

在Android 2.2版本之前,HttpURLConnection一直存在著一些令人厭煩的bug。比如說對一個可讀的InputStream呼叫close()方法時,就有可能會導致連線池失效了。

開發建議

判斷Android版本,並設定http.keepAlive為false。

private void disableConnectionReuseIfNecessary() {

        // Work around pre-Froyo bugs in HTTP connection reuse.

        if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION\_CODES.FROYO) {

                System.setProperty(http.keepAlive, false);

        }

}

影響範圍

2.2版本之前

六、弱加密風險檢測

6.1 禁止使用弱加密演算法

安全性要求高的應用程式必須避免使用不安全的或者強度弱的加密演算法,現代計算機的計算能力使得攻擊者通過暴力破解可以攻破強度弱的演算法。例如,資料加密標準演算法DES(金鑰預設是56位長度、演算法半公開、迭代次數少)是極度不安全的,使用類似EFF(Electronic Frontier Foundaton)Deep Crack的計算機在一天內可以暴力破解由DES加密的訊息。

使用DES弱加密演算法,樣例

風險程式碼:


SecretKeySpec key = new SecretKeySpec(rawKeyData, DES);

Cipher cipher = Cipher.getInstance(DES/ECB/PKCS5Padding);

cipher.init(Cipher.DECRYPT\_MODE, key);

開發建議

建議使用安全性更高的AES加密演算法

規範 6.2 不安全的金鑰長度風險

在使用RSA加密時,金鑰長度小於512bit,小於512bit的金鑰很容易被破解,計算出金鑰。

風險程式碼:

public static KeyPair getRSAKey() throws NoSuchAlgorithmException {

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(RSA);

        keyGen.initialize(512);

        KeyPair key = keyGen.generateKeyPair();

        return key;

      }

開發建議

使用RSA加密時,建議金鑰長度大於1024bit

6.3 AES/DES弱加密風險(ECB)

AES的ECB加密模式容易遭到字典攻擊,安全性不夠。

風險程式碼:

SecretKeySpec key = new SecretKeySpec(keyBytes, AES);

**Cipher cipher = Cipher.getInstance(AES/ECB/PKCS7Padding, BC);**

cipher.init(Cipher.ENCRYPT\_MODE, key);

開發建議

避免使用ECB模式,建議使用CBC。

6.4 IVParameterSpec不安全初始化向量

使用IVParameterSpec函式,如果使用了固定的初始化向量,那麼密碼文字可預測性高得多,容易受到字典攻擊等。

風險程式碼:

byte[] iv = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

IvParameterSpec ips = new IvParameterSpec(iv)

開發建議

IVParameterSpec初始化時,不使用常量vector。

6.5 RSA中不使用Padding風險

使用RSA公鑰時通常會繫結一個padding,原因是為了防止一些依賴於no padding時對RSA演算法的攻擊。

風險程式碼:

Cipher rsa = null;

try {

  rsa = javax.crypto.Cipher.getInstance(RSA/NONE/NoPadding);

}catch (java.security.NoSuchAlgorithmException e) {}

catch (javax.crypto.NoSuchPaddingException e) {}

SecretKeySpec key = new SecretKeySpec(rawKeyData, RSA);

Cipher cipher = Cipher.getInstance(RSA/NONE/NoPadding);

cipher.init(Cipher.DECRYPT\_MODE, key);

開發建議

建議使用Padding模式。

6.6 KeyStore弱密碼風險

keytool是一個Java資料證照的管理工具,Keytool將金鑰(key,私鑰和公鑰配對)和證照(certificates)存在一個稱為keystore的檔案中,並通過密碼保護keystore中的金鑰。如果密碼設定過於簡單,例如:123456、android等,則會導致keystore檔案的私鑰洩露,從而導致一系列的資訊洩露風險。

開發建議

提高keystore保護密碼的強度

七、資料安全

7.1 剪貼簿敏感資訊洩露風險

由於Android剪貼簿的內容向任何許可權的app開放,很容易就被嗅探洩密。同一部手機中安裝的其他app,甚至是一些許可權不高的app,都可以通過剪貼簿功能獲取剪貼簿中的敏感資訊。

風險程式碼:

clipBtn = (Button) findViewById(R.id.btn\_clip);

        clipBtn.setOnClickListener(new OnClickListener() {

            @Override

            public void onClick(View v) {

                ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD\_SERVICE);

                ClipData clip1 = ClipData.newPlainText(label,password=123456);

                clipboard.setPrimaryClip(clip1);

            }

        });

開發建議

避免使用剪貼簿敏文儲存敏感資訊或進行加密

7.2 金鑰硬編碼風險

在程式碼中禁止硬編碼私鑰等敏感資訊,攻擊者反編譯程式碼,即可拿到。

7.3 Intent敏感資料洩露

APP建立Intent傳遞資料到其他Activity,如果建立的Activity不是在同一個Task中開啟,就很可能被其他的Activity劫持讀取到Intent內容,跨Task的Activity通過Intent傳遞敏感資訊是不安全的。

開發建議

儘量避免使用包含FLAG_ACTIVITY_NEW_TASK標誌的Intent來傳遞敏感資訊。

7.4 PendingIntent誤用風險

使用pendingIntent時候,如果使用了一個空Intent,會導致惡意使用者劫持Intent的內容。禁止使用空intent去構造pendingIntent。

開發建議

禁止使用空intent去構造pendingIntent。

7.5 資料或程式(DEX、SO)載入、刪除檢查

程式在載入外部dex、so檔案是否判斷檔案來源、是否存放可信區域;程式刪除檔案是否可篡改檔案路勁

  1. 是否載入公共區域程式,如sdcard、/data/local/tmp/、應用自建立但其他應用有讀寫許可權的目錄上
  2. 是否從網路下載,檢測方法包括:閱讀程式碼、監聽網路請求、見識儲存區域檔案讀寫、檢視安裝包
  3. 升級包是否存在公共區域儲存。

7.6 檔案全域性讀寫漏洞

在使用getDir、getSharedPreferences(SharedPreference)或openFileOutput時,如果設定了全域性的可讀許可權,攻擊者惡意讀取檔案內容,獲取敏感資訊。在設定檔案屬性時如果設定全域性可寫,攻擊者可能會篡改、偽造內容,可能會進行詐騙等行為,造成使用者財產損失。其中getSharedPreferences如果設定全域性寫許可權,則當攻擊app跟被攻擊app具有相同的Android:sharedUserId屬性時和簽名時,攻擊app則可以訪問到內部儲存檔案進行寫入操作。

開發建議

  1. 使用MODE_PRIVATE模式建立內部儲存檔案
  2. 加密儲存敏感資料
  3. 避免在檔案中儲存明文敏感資訊
  4. 避免濫用Android:sharedUserId屬性

如果兩個appAndroid:sharedUserId屬性相同,切使用的簽名也相同,則這兩個app可以互相訪問內部儲存檔案資料

7.7 日誌洩露風險

在APP的開發過程中,為了方便除錯,通常會使用log函式輸出一些關鍵流程的資訊,這些資訊中通常會包含敏感內容,如執行流程、明文的使用者名稱密碼等,這會讓攻擊者更加容易的瞭解APP內部結構方便破解和攻擊,甚至直接獲取到有價值的敏感資訊。

開發建議

禁止列印敏感資訊

八、其他風險

8.1 謹慎使用高風險函式

在程式需要執行系統命令等函式,需要謹慎使用,嚴格控制命令來源,防止黑客替換命令攻擊。

風險程式碼:

Example Java code:

  Runtime rr = Runtime.getRuntime();

  Process p = rr.exec(ls -al);

Example Bytecode code:

  const-string v2, ls -al

  invoke-virtual {v1, v2}, Ljava/lang/Runtime;->exec(Ljava/lang/String;)Ljava/lang/Process;

開發建議

嚴格按照要求使用

8.2 Fragment注入漏洞(CVE-2013-6271)

在api level 小於19的app,所有繼承了PreferenceActivity類的activity並將該類置為exported的應用都受到Fragment注入漏洞的威脅。

Google在Android 4.4 KitKat 裡面修正了該問題,引入了PreferenceActivity.isValidFragment函式,要求使用者重寫該函式驗證Fragment來源正確性。

開發建議

  1. 當Android api >=19時,要覆蓋每一個PreferenceActivity類下的isValidFragment方法以避免異常丟擲;
  2. 當Android api < 19時,如果在PreferenceActivity內沒有引用任何fragment,建議覆蓋isValidFragment並返回false

影響範圍

小於Android 4.4(API level 19)

8.3 SQLite資料庫日誌洩露漏洞(CVE-2011-3901)

Android SQLite資料庫journal檔案可被所有應用程式讀取,所有目錄對應程式資料庫目錄擁有執行許可權,意味著應用程式資料目錄全域性訪問,/data/data/<app package>/databases目錄以[rwxrwx--x]許可權建立,可導致全域性讀寫。資料庫目錄下建立的journal檔案以[-rw-r--r--]許可權建立,可被所有app讀取。

開發建議

升級到Android4.0.1以上版本或者使用SQLCipher或其他庫加密資料庫和日誌資訊。

影響範圍

Android2.3.7版本存在該漏洞,其他版本可能也受到影響,4.0.1不受影響

8.4 隨機數生成漏洞

SecureRandom的使用不當會導致生成的隨機數可被預測,該漏洞存在於Android系統隨機生成數字串安全金鑰的環節中。該漏洞的生成原因是對SecureRandom類的不正確使用方式導致生成的隨機數不隨機。

風險程式碼:

SecureRandom secureRandom = new SecureRandom();

        byte[] b = new byte[] { (byte) 1 };

        secureRandom.setSeed(b);

        // Prior to Android 4.2, the next line would always return the same number!

        Log.v(wgc,-------------------------------);

        Log.v(wgc,Test1: + secureRandom.nextInt());

        SecureRandom secureRandom2 = new SecureRandom(new byte[] { (byte) 1 });

        Log.v(wgc,Test2: + secureRandom2.nextInt());

        SecureRandom secureRandom3 = new SecureRandom();

        secureRandom3.setSeed(10L);

        Log.v(wgc,Test3: + secureRandom3.nextInt())

        SecureRandom secureRandom4 = new SecureRandom();

        secureRandom4.nextBytes(b);

        secureRandom4.setSeed(10L);

        Log.v(wgc,Test4: + secureRandom4.nextInt());

        SecureRandom secureRandom5 = new SecureRandom();

        Log.v(wgc,Test5: + secureRandom4.nextInt());

開發建議

  1. 不要使用自定義隨機源代替系統預設隨機源(推薦)除非有特殊需求,在使用SecureRandom類時,不要呼叫以下函式:SecureRandom類下SecureRandom(byte[]seed)、setSeed(long seed)和setSeed(byte[]seed)方法。
  2. 在呼叫setSeed方法前先呼叫任意nextXXX方法。具體做法是呼叫setSeed方法前先呼叫一次SecureRandom#nextBytes(byte[]bytes)方法,可以避免預設隨機源被替代,詳細見參考資料。

影響範圍

Android 4.2之前,Android API 17以後SecureRandom的預設實現方式從Cipher.RSA換到了OpenSSL。SecureRandom新的實現方式不能將自己的seed替換掉系統的seed。

8.5 釋出版本需加固

釋出的軟體,應對app進行加固,防止攻擊者獲取app程式碼、業務邏輯、API介面等,對業務和公司聲譽造成一定影響,防止app被破解二次打包,導致損失。

開發建議 APP加固


內容編輯:湯青松

更新時間:2019-09-03

相關文章