Android應用與系統安全防御
來源:荊州網站建設
時間:2017-06-07
Android應用的安全隱患包括代碼安全、數據安全、組件安全、WebView等幾個方面。
1. 代碼安全
代碼安全主要是指Android apk容易被反編譯,從而面臨軟件破解,內購破解,軟件邏輯修改,插入惡意代碼,替換廣告商ID等風險。我們可以采用以下方法對apk進行保護:
1.1 代碼混淆
代碼混淆可以在一定程度上增加apk逆向分析的難度。Android SDK從2.3開始就加入了ProGuard代碼混淆功能,開發者只需進行簡單的配置就可以實現對代碼的混淆。
1.2 Apk簽名校驗
每一個軟件在發布時都需要開發人員對其進行簽名,而簽名使用的密鑰文件時開發人員所獨有的,破解者通常不可能擁有相同的密鑰文件,因此可以使用簽名校驗的方法保護apk。Android SDK中PackageManager類的getPackageInfo()方法就可以進行軟件簽名檢測。
1.3 Dex文件校驗
重編譯apk其實就是重編譯了classes.dex文件,重編譯后,生成的classes.dex文件的hash值就改變了,因此我們可以通過檢測安裝后classes.dex文件的hash值來判斷apk是否被重打包過。
(1)讀取應用安裝目錄下/data/app/xxx.apk中的classes.dex文件并計算其哈希值,將該值與軟件發布時的classes.dex哈希值做比較來判斷客戶端是否被篡改。
(2)讀取應用安裝目錄下/data/app/xxx.apk中的META-INF目錄下的MANIFEST.MF文件,該文件詳細記錄了apk包中所有文件的哈希值,因此可以讀取該文件獲取到classes.dex文件對應的哈希值,將該值與軟件發布時的classes.dex哈希值做比較就可以判斷客戶端是否被篡改。
為了防止被破解,軟件發布時的classes.dex哈希值應該存放在服務器端。
另外由于逆向c/c++代碼要比逆向Java代碼困難很多,所以關鍵代碼部位應該使用Native C/C++來編寫。
1.4 逆向工具對抗
對apk進行重打包常用的工具是apktool,apktool對于后綴為PNG的文件,會按照PNG格式進行處理,如果我們將一個非PNG格式文件的文件后綴改為PNG,再使用apktool重打包則會報錯。
1.5 調試器檢測
為了防止apk被動態調試,可以檢測是否有調試器連接。在Application類中提供了isDebuggerConnected()方法用于檢測是否有調試器連接,如果發現有調試器連接,可以直接退出程序。
以上是使用比較多的幾種保護方法,單獨使用其中一種效果不大,應該綜合運用。
1.6 加殼保護
使用加殼程序防止apk逆向是一種非常有效的方式,也是一個趨勢。Jack_Jia在《Android APK加殼技術方案》一文中詳細闡述了Android apk加殼原理以及幾種加殼方案的具體實現。我們可以利用這幾種方案對apk進行加殼。
不過這種加殼方式是在Java層實現的,被反編譯的風險仍然很大。為了克服這個缺點,今后可以研究采用如下思路來進行保護:
將核心業務邏輯代碼放入加密的.jar或者.apk文件中,在需要調用時使用Native C/C++代碼進行解密,同時完成對解密后文件的完整性校驗。如果需要更加安全的保護方法,可以考慮對so文件(Native C/C++代碼編譯得到的文件)進行加殼。Android so加殼主要需要解決兩個問題:
(1)對ELF文件加殼;
(2)對Android SO的加載、調用機制做特殊處理。
其實不管是Linux還是Windows,加殼的思路基本是一致的,簡單點無非加密+拆解+混淆,復雜點如Stolen Code + VM等。所以確定好一個加殼方案之后,剩下的就是了解elf的文件結構和加載機制,然后自己寫一套殼+loader。
Android上的loader是/system/bin/linker,跟linux上的ld有一些區別。但主要過程還是一致的:map + relocate + init。
Android so主要充當的角色是通過JNI與java交互,所以主要是作為一個庫存在(也有一些so是可執行的),然后被Android runtime加載,并能被java層調用。所以對elf加完殼之后,還要對Android so做一些特殊處理:
1. Android so被System.LoadLibrary()加載之后,會將so的信息存儲在一個全局鏈表里,所以要保證脫殼后的so能被這個鏈表訪問到。
2. Android so庫函數被java調用有兩種方式:一種是通過registerNative注冊,另一種是通過javah命名規則命名(參考http://blog.csdn.net/sno_guo/article/details/7688227)。所以一個通用的加殼方案要保證所有的庫函數都能被調用,前者好解決,后者需要花點功夫。
解決掉這兩個問題之后,基本上一套Android SO加殼框架就成形了,后續就可以增加各種Anti tricks來完善殼的強度。
2. 數據安全
2.1 存儲安全問題
關于數據存儲可能出現的問題包括如下幾點:外部存儲(SD卡)上的文件沒有權限管理,所有應用都可讀可寫。開發者把敏感信息明文存在 SD 卡上,或者動態加載的payload放在SD卡上。
(1)明文存儲敏感數據,導致直接被攻擊者復制或篡改。
將隱私數據、系統數據明文保存在外部存儲
將軟件運行時依賴的數據保存在外部存儲
將軟件安裝包或者二進制代碼保存在外部存儲
使用全局可讀寫(MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE)的內部存儲方式,或明文存儲敏感信息(用戶賬號密碼等)。
(2)不恰當存儲登陸憑證,導致攻擊者利用此數據竊取網絡賬戶隱私數據。
解決方案:
對這些數據進行加密,密碼保存在內部存儲,由系統托管或者由用戶使用時輸入。
對應用配置文件,較安全的方法是保存到內部存儲;如果必須存儲到SD卡,則應該在每次使用前檢驗它是否被篡改,與預先保存在內部的文件哈希值進行比較。
應用如果需要安裝或加載位于SD卡的任何文件,應該先對其完整性做驗證,判斷其與實現保存在內部存儲中的(或從服務器下載來的)哈希值是否一致。
如果要跨應用進行數據共享,有種較好的方法是實現一個Content Provider 組件,提供數據的讀寫接口并為讀寫操作分別設置一個自定義的權限。
對于登錄憑證的存儲,使用基于憑據而不是密碼的協議滿足這種資源持久訪問的需求,例如OAuth。
Android數據存儲機制
存儲方式 | 描述 | 數據保密性 |
Shared preferences | 用來存儲一些簡單配置信息的一種機制,使用Map數據結構來存儲數據,以鍵值對的方式存儲,采用了XML格式將數據存儲到設備中。例如保存登錄用戶的用戶名和密碼。只能在創建它的應用中使用,其他應用無法使用。不能指定存儲文件的位置,創建的存儲文件保存在/data/data/<package name>/shares_prefs文件夾下。支持的存儲類型有:Boolean、Float、Integer、Long、String等 | 可以設置四種模式: MODE_PRIVATE(默認模式,文件只能讓創建的應用程序訪問)、 MODE_WORLD_WRITEABLE、 MOED_WORLD_READABLE、 MODE_APPEND |
內部存儲 | 在設備內存中存儲數據。通常這些數據不允許被其它應用甚至終端用戶訪問。即使重啟設備,這些數據仍然存在,不過當終端用戶卸載程序后,這些數據就會被刪除。 | 可以設置三種模式: MODE_PRIVATE(默認模式)、MODE_WORLD_READABLE、 MODE_WORLD_WRITABLE |
外部存儲 | 外部存儲(SD卡)的數據是全局可讀的。設備用戶和其它應用都能讀取、修改、刪除這些數據 | 數據默認是全局可讀的 |
SQLite數據庫 | 如果需要使用數據庫的搜索和數據管理功能,則可以使用SQLite數據庫存儲機制 | 程序內部可以任意訪問,外部程序不能訪問 |
網絡存儲 | 通過web服務器存儲和獲取數據 | 基于web 服務器的設置 |
2.2 傳輸安全問題
? 不使用加密傳輸
最危險的是直接使用HTTP協議登錄賬戶或交換數據。例如,攻擊者在自己設置的釣魚網絡中配置DNS服務器,將軟件要連接的服務器域名解析至攻擊者的另一臺服務器在,這臺服務器就可以獲得用戶登錄信息,或者充當客戶端與原服務器的中間人,轉發雙方數據。
? 使用加密傳輸但忽略證書驗證環節
如開發者在代碼中不檢查服務器證書的有效性,或選擇接受所有的證書。例如,開發者可以自己實現一個X509TrustManager接口,將其中的CheckServerTrusted()方法實現為空,即不檢查服務器是否可信或者在SSLSoketFactory的實例中,通過setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIET),接受所有證書。這可能是因為開發者使用了自己生成的證書,客戶端發現證書沒有和可信CA 形成信任鏈,出現了CertificateException等異常,從而不得不做出這種選擇。這種做法可能導致的問題是中間人攻擊。
我們在對敏感數據進行傳輸時應該采用基于SSL/TLS的HTTPS進行傳輸。由于移動軟件大多只和固定的服務器通信,我們可以采用“證書鎖定”(certificate pinning)方式在代碼更精確地直接驗證服務器是否擁有某張特定的證書。實現“證書鎖定”的方法有二種:一種是實現X509TrustManager接口,另一種則是使用keystore。具體可以參考Android開發文檔中的HttpsURLConnection類的概述。
3. 組件安全
android應用內部的Activity、Service、Broadcast Receiver等組件是通過Intent通信的,組件間需要通信就需要在Androidmanifest.xml文件中配置,不恰當的組件配置、組件在被調用時未做驗證、在調用其他組件時未做驗證都會帶來風險。
可能產生的風險包括:
(1)惡意調用
(2)惡意接受數據
(3)仿冒應用,例如(惡意釣魚,啟動登錄界面)
(4)惡意發送廣播、啟動應用服務。
(5)調用組件,接受組件返回的數據
(6)攔截有序廣播
比如:調用暴露的組件發短信、微博等。
解決辦法:
(1)最小化組件暴露
不參與跨應用調用的組件添加android:exported="false"屬性,這個屬性說明它是私有的,只有同一個應用程序的組件或帶有相同用戶ID的應用程序才能啟動或綁定該服務。
(2)設置組件訪問權限
對參與跨應用調用的組件或者公開的廣播、服務設置權限。只有具有該權限的組件才能調用這個組件。
(3)暴露組件的代碼檢查
Android 提供各種API來在運行時檢查、執行、授予和撤銷權限。這些API 是 android.content.Context 類的一部分,這個類提供有關應用程序環境的全局信息。
4. WebView
存在的漏洞:
惡意App可以注入JavaScript代碼進入WebView中的網頁,網頁未作驗證。
惡意網頁可以執行JavaScript反過來調用App中注冊過的方法,或者使用資源。
漏洞利用:
惡意程序嵌入Web App,然后竊取用戶信息。
惡意網頁遠程調用App代碼。更有甚者,通過Java Reflection調用Runtime執行任意代碼。
解決方式:
1、如果無需與JS交互,請刪除對addJavascriptInterface函數的調用;
2、在載入頁面時對URL進行白名單判定,只有存在白名單中的域才允許導出或調用相關的Java類或方法。
參考資料:http://www.zhihu.com/question/22933619
5. SQL注入
使用字符串連接方式構造SQL語句就會產生SQL注入。
解決方法:使用參數化查詢。
5. 其他漏洞
ROOT后的手機可以修改App的內購,或者安裝外掛App等。
Logcat泄露用戶敏感信息。
惡意的廣告包插件(可能存在后門、WebView漏洞等)
UXSS漏洞:
UXSS漏洞可以繞過同源策略訪問存儲在Android應用目錄/data/data/[應用包名]/下的所有內容。
如果產生該漏洞的是web瀏覽器,則攻擊者可以利用該漏洞竊取瀏覽器存儲的所有cookie信息以及其它信息。
測試代碼:
代碼地址:https://github.com/click1/uxss
在線測試地址:http://uxss.sinaapp.com/index.php
解決方法:
1、服務端禁止iframe嵌套X-FRAME-OPTIONS:DENY。
2、客戶端使用setAllowFileAccess(false)方法禁止webview訪問本地域。
3、客戶端使用onPageStarted (WebView view, String url, Bitmap favicon)方法在跳轉前進行跨域判斷。
4、客戶端對iframe object標簽屬性進行過濾。
Android系統安全防御
1. 操作系統安全問題
Android root問題
系統漏洞,補丁更新不及時
認證機制問題
2. 系統安全解決方案
2.1 權限管理與隔離
對運行在Android系統上的應用程序進行權限的細粒度管理和隔離,防止越權行為的發生和濫用權限獲取敏感數據。
可以采用MAC(Mandatory Access Control)強制訪問控制模型實現。它是一個針對Linux的安全加強系統SELinux中使用的安全模型,即任何進程想在SELinux系統中干任何事情,都必須先在安全策略配置文件中賦予權限。凡是沒有出現在安全策略配置文件中的權限,進程就沒有該權限。Google在Android 4.4上正式推出了一套以SELinux為基礎的系統安全機制SEAndroid。所以如果我們要定制一個Android系統,可以采用具有SEAndroid安全機制的Android 4.4版本。
2.2 內核與應用層漏洞防護
增加補丁更新功能,如果發現漏洞,及時提醒用戶進行系統補丁更新。
2.3 惡意程序檢測與防護
建立一套惡意代碼防護模型,對運行在Android系統上的惡意程序進行檢測,抵御惡意代碼的入侵。
2.4 數據安全存儲與傳輸:
對Android系統上的數據存儲和數據傳輸進行加密保護,保證終端上數據能夠安全地使用。
以上內容由湖北國菱計算機科技有限公司荊州網站建設荊州軟件開發組轉載自:http://www.cnblogs.com/goodhacker/p/3864680.html