大佬:「這個 APP 破解下,能夠兼容客戶已出貨的產品」
我:「這個不合適吧」
大佬:「這個客戶對咱們很重要」
我:「好吧」
而後,就是經過反編譯某 APP ,分析藍牙交互協議,在新的 APP 中去兼容已出貨的設備,達到無縫對接。 –這種場景在開發中仍是比較常常碰到的。
隨着移動互聯網向社會生活的各個領域滲透,APP 的使用愈來愈普遍。但 Android 系統因爲其開源的屬性,市場上針對開源代碼定製的 ROM 良莠不齊(特別中國區域),在系統層面的安全防範和易損性都不同,Android 應用市場對 APP 的審覈相對 iOS 來講也比較寬泛,市場上一些主流的 APP 雖然多少都作了一些安全防範,但因爲大部分 APP 不涉及資金安全,因此對安全的重視程度不夠;並且因爲安全是門系統學科,絕大部分 APP 層的開發人員缺少對 APP 安全意識及措施,致使被有心者有隙可乘。android
Android 開發是當前最火的話題之一,但不多開發者會討論這個領域的安全問題,除了專業從業者,但移動應用安全隱患也給發展帶來了挑戰。c++
聲明,我不是專業的安全人員,從事的跟安全工做也沒有什麼關係,本文從自已平時涉及的項目出發,對客戶端的代碼質量、代碼篡改、不安全的數據儲存、不安全的通訊、不安全的認證、加密不足等安全問題做了說明,從普通開發者角度儘可能去提升自已的 APP 安全,以下降代碼安全漏洞,減小代碼被利用的可能性,避免信任危機、經濟損失和法律風險。web
Android 病毒就是手機木馬,主要是一些惡意的應用程序。手機木馬有的獨立存在,有的則假裝成圖片文件的方式附在正版 APP 上,隱蔽性極強,部分病毒還會出現變種,而且一代比一代更強大。算法
這些病毒有一些通用的特徵:sql
雖然 Java 代碼通常要作混淆,可是 Android 的幾大組件的建立方式是依賴注入的方式,所以不能被混淆,並且目前經常使用的一些反編譯工具好比 Apktool 等可以絕不費勁的還原 Java 裏的明文信息,Native 裏的庫信息也能夠經過 objdump 或 IDA 獲取。所以一旦 Java 或 Native 代碼裏存在明文敏感信息,基本上是毫無安全而言的。數據庫
即反編譯後從新加入惡意的代碼邏輯,重新打包一個 APK 文件。重打包的目的通常都是上面提到和病毒結合,對正版 APK 進行解包,插入惡意病毒後從新打包併發布,所以假裝性很強。截住 APP 重打包就必定程度上防止了病毒的傳播。跨域
通常經過進程注入或者調試進程的方式來 Hook 進程,改變程序運行的邏輯和順序,獲取程序運行的內存信息,也就是用戶全部的行爲都被監控起來,這也是盜取賬號密碼最經常使用的一種方式。數組
固然 Hook 行爲不必定徹底是惡意的,好比有些安全軟件會利用 Hook 的功能作主動防護。通常來講,Hook 須要獲取 root 權限或者跟被 Hook 進程相同的權限,所以若是你的手機沒有被 root,並且是正版 APK 的話,被注入仍是很困難的。 瀏覽器
傳輸過程最多見的劫持就是中間人攻擊。不少安全要求較高的應用程序要求全部的業務請求都是經過 Https,可是 Https 的中間人攻擊也逐漸多了起來,並且在實際使用中,證書交換和驗證在一些山寨手機或者非主流 ROM 上面存在一些問題,讓 Https 的使用碰到阻礙。安全
支付密碼通常是經過鍵盤輸入的,鍵盤輸入的安全直接影響了密碼的安全。鍵盤的安全隱患來自三個方面:
因爲如今 Hybrid APP 的盛行(混合開發),Webview 在 APP 的使用也是愈來愈多,Android 系統 Webview 存在一些漏洞,形成 js 提權。最爲著名的就是傳說中 js 注入漏洞和 webkit xss 漏洞。
PermissionGroup 能夠對 permission 進行一個邏輯上的分組。若是 PermissionGroup 的屬性爲空,會致使權限定義無效,且其餘 APP 沒法使用該權限。
開發建議:設置 PermissionGroup 屬性值或者不使用 PermissionGroup。
因爲對 APP 的自定義 permission 的 protectionLevel 屬性設置不當,會致使組件(如:content provider)數據泄露危險。最好的權限設置應爲 signature 或signatureOrSystem ,進而避免被第三方應用利用。
開發建議:注意使用 signature 或 signatureOrSystem 防止其餘 APP 註冊或接受該 APP 的消息,提升安全性。
經過 sharedUserId,可讓擁有同一個 User Id 的多個 APP 運行在同一個進程中,互相訪問任意資源。將 sharedUserId 設置爲 android.uid.system,能夠把 APP 放到系統進程中,APP 將得到極大的權限。若是 APP 同時有 master key 漏洞,容易致使被 root。
開發建議:合理設置軟件權限。
當這個標誌被設置成 true 或不設置該標誌位時,應用程序數據能夠備份和恢復,adb 調試備份容許惡意攻擊者複製應用程序數據。
開發建議:設置 AndroidManifest.xml 的 android:allowBackup 標誌爲 false。
在 AndroidManifest.xml 中定義 Debuggable 項,若是該項被打開,APP 存在被惡意程序調試的風險,可能致使泄露敏感信息等問題。
開發建議:顯示的設置 AndroidManifest.xml 的 debuggable 標誌爲 false。
Activity、activity-alias、service、receiver 組件對外暴露會致使數據泄露和惡意的攻擊。
開發建議:最小化組件暴露。對不會參與跨應用調用的組件添加 android:exported=false 屬性。
設置組件訪問權限。對跨應用間調用的組件或者公開的 receiver、service、activity 和 activity-alias 設置權限,同時將權限的 protectionLevel 設置爲 signature 或 signatureOrSystem。組件傳輸數據驗證。對組件之間,特別是跨應用的組件之間的數據傳入與返回作驗證和增長異常處理,防止惡意調試數據傳入,更要防止敏感數據返回。
建立隱式 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(),系統會拋出異常。
Intent Scheme URI 是一種特殊的 URL 格式,用來經過 Web 頁面啓動已安裝應用的 Activity 組件,大多數主流瀏覽器都支持此功能。
Android Browser 的攻擊手段—— Intent Scheme URLs 攻擊。這種攻擊方式利用了瀏覽器保護措施的不足,經過瀏覽器做爲橋樑間接實現 Intend-Based 攻擊。相比於普通 Intend-Based 攻擊,這種方式極具隱蔽性,
若是在 APP 中,沒有檢查獲取到的 load_url 的值,攻擊者能夠構造釣魚網站,誘導用戶點擊加載,就能夠盜取用戶信息。因此,對 Intent URI 的處理不當時,就會致使基於 Intent 的攻擊。
若是瀏覽器支持 Intent Scheme URI 語法,通常會分三個步驟進行處理:
關鍵點
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 時,要進行過濾和檢查。
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(); } }
NullPointerException 異常致使的拒絕服務
源於程序沒有對 getAction() 等獲取到的數據進行空指針判斷,從而致使了空指針異常致使應用崩潰
風險代碼:
Intent i = new Intent(); if (i.getAction().equals(TestForNullPointerException)) { Log.d(TAG, Test for Android Refuse Service Bug); }
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); } }
ClassNotFoundException 異常致使的拒絕服務漏洞
Intent i = getIntent(); getSerializableExtra(key);
開發建議:將比不要導出的組建設置爲不導出
在處理 Intent 數據時,進行捕獲異常,經過 getXXXExtra() 獲取的數據時進行如下判斷,以及用 try catch 方式捕獲全部異常,防止出現拒絕服務漏洞,包括:空指針異常、類型轉換異常、數組越界訪問異常、類未定義異常、其餘異常
Try{ .... xxx.getXXXExtra() .... }Catch Exception{ ** ** **// 爲空便可** }
一些 APP 在正式發佈前,爲了方便調試 APP,都會在 APP 裏集成一些調試或測試界面。這些測試界面可能包含敏感的信息。
從 Android APP 的結構來講,dex 文件是最重要、最須要保護的,由於 dex 中存放了代碼的信息,開發者經過使用 dex2jar 和 jd-gui 簡單幾步就能夠查看到源碼。
Andriod 應用程序使用 Java 開發,可經過反編譯的方式獲取對應的源碼
ProGuard 是一個免費的 Java 類文件的壓縮,優化,混餚器
新建個 Android 工程以後,proguard.cfg 文件會在工程的根目錄下自動建立文件定義了混淆器是怎樣優化和混淆你的代碼
目前開發經常使用方法:
SQLite 作爲 android 平臺的數據庫,對於數據庫查詢,若是開發者採用字符串連接方式構造 SQL 語句,就會產生 SQL 注入。
開發建議:
APP 在使用 openOrCreateDatabase 建立數據庫時,將數據庫設置了全局的可讀權限,攻擊者惡意讀取數據庫內容,獲取敏感信息。在設置數據庫屬性時若是設置全局可寫,攻擊者可能會篡改、僞造內容,能夠能會進行詐騙等行爲,形成用戶財產損失。
開發建議
因爲 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); } });
開發建議:避免使用剪貼板敏文存儲敏感信息或進行加密
在代碼中禁止硬編碼私鑰等敏感信息,攻擊者反編譯代碼,便可拿到。
APP 建立 Intent 傳遞數據到其餘 Activity,若是建立的 Activity 不是在同一個 Task 中打開,就極可能被其餘的 Activity 劫持讀取到 Intent 內容,跨 Task 的Activity 經過 Intent 傳遞敏感信息是不安全的。
開發建議:儘可能避免使用包含 FLAG_ACTIVITY_NEW_TASK 標誌的 Intent 來傳遞敏感信息。
使用 pendingIntent 時候,若是使用了一個空 Intent,會致使惡意用戶劫持 Intent 的內容。禁止使用空 intent 去構造 pendingIntent。
開發建議:禁止使用空 intent 去構造 pendingIntent。
程序在加載外部 dex、so 文件是否判斷文件來源、是否存放可信區域;程序刪除文件是否可篡改文件路勁
是否加載公共區域程序,如 sdcard、/data/local/tmp/、應用自建立但其餘應用有讀寫權限的目錄上
是否從網絡下載,檢測方法包括:閱讀代碼、監聽網路請求、見識存儲區域文件讀寫、查看安裝包
升級包是否存在公共區域存儲。
在使用 getDir、getSharedPreferences(SharedPreference) 或 openFileOutput 時,若是設置了全局的可讀權限,攻擊者惡意讀取文件內容,獲取敏感信息。在設置文件屬性時若是設置全局可寫,攻擊者可能會篡改、僞造內容,可能會進行詐騙等行爲,形成用戶財產損失。其中 getSharedPreferences 若是設置全局寫權限,則當攻擊 APP 跟被攻擊 APP 具備相同的 Android:sharedUserId 屬性時和簽名時,攻擊 APP 則能夠訪問到內部存儲文件進行寫入操做。
開發建議
使用 MODE_PRIVATE 模式建立內部存儲文件
加密存儲敏感數據
避免在文件中存儲明文敏感信息
避免濫用 Android:sharedUserId 屬性
若是兩個 APP Android:sharedUserId 屬性相同,切使用的簽名也相同,則這兩個 APP 能夠互相訪問內部存儲文件數據
在 APP 的開發過程當中,爲了方便調試,一般會使用 log 函數輸出一些關鍵流程的信息,這些信息中一般會包含敏感內容,如執行流程、明文的用戶名密碼等,這會讓攻擊者更加容易的瞭解 APP 內部結構方便破解和攻擊,甚至直接獲取到有價值的敏感信息。
開發建議: 禁止打印敏感信息
WebView 組件中的接口函數 addJavascriptInterface 存在遠程代碼執行漏洞,遠程攻擊者利用此漏洞能實現本地 Java 和 js 的交互,可對 Android 移動終端進行網頁掛馬從而控制受影響設備。
Webview 接口避免使用第三方程序惡意使用發送短信,撥打電話,刪除文件
修復方案: 白名單進行限制,功能僅限於該應用的功能範圍以內
釣魚這個事一直都安全界最經常使用的攻擊,也是最難經過技術手段解決的一類問題,並且釣魚的手段也是千奇百怪,要防釣魚除了讓用戶提升安全意識,不點擊來路不明的連接外,
技術層面能夠作到以下兩點:
主要是因爲 JS 的 XmlHttpRequest 能夠讀取本地文件,從而讀取到 APP data 數據庫目錄下的 webviewCookiesChromium.db , 這個 db 一般是系統存放 cookie 的地方,至關於變相的爲讀取 cookie 開了權限。
安全性要求高的應用程序必須避免使用不安全的或者強度弱的加密算法,現代計算機的計算能力使得攻擊者經過暴力破解能夠攻破強度弱的算法。例如,數據加密標準算法 DES(密鑰默認是 56 位長度、算法半公開、迭代次數少)是極度不安全的,使用相似 EFF(Electronic Frontier Foundaton)Deep Crack 的計算機在一天內能夠暴力破解由 DES 加密的消息。
開發建議:建議使用安全性更高的 AES 加密算法
在使用 RSA 加密時,密鑰長度小於 512bit,小於 512 bit 的密鑰很容易被破解,計算出密鑰。
風險代碼:
public static KeyPair getRSAKey() throws NoSuchAlgorithmException { KeyPairGenerator keyGen = KeyPairGenerator.getInstance(RSA); keyGen.initialize(512); KeyPair key = keyGen.generateKeyPair(); return key; }
開發建議:使用 RSA 加密時,建議密鑰長度大於 1024bit
AES 的 ECB 加密模式容易遭到字典攻擊,安全性不夠。
風險代碼:
SecretKeySpec key = new SecretKeySpec(keyBytes, AES); Cipher cipher = Cipher.getInstance(AES/ECB/PKCS7Padding, BC); cipher.init(Cipher.ENCRYPT\_MODE, key);
開發建議:避免使用 ECB 模式,建議使用 CBC。
使用 IVParameterSpec 函數,若是使用了固定的初始化向量,那麼密碼文本可預測性高得多,容易受到字典攻擊等。
風險代碼:
byte[] iv = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; IvParameterSpec ips = new IvParameterSpec(iv)
複製代碼開發建議
IVParameterSpec 初始化時,不使用常量 vector。
keytool 是一個 Java 數據證書的管理工具,Keytool 將密鑰(key,私鑰和公鑰配對)和證書(certificates)存在一個稱爲 keystore 的文件中,並經過密碼保護 keystore 中的密鑰。若是密碼設置過於簡單,例如:12345六、android 等,則會致使 keystore 文件的私鑰泄露,從而致使一系列的信息泄露風險。
開發建議:提升 keystore 保護密碼的強度
在程序須要執行系統命令等函數,須要謹慎使用,嚴格控制命令來源,防止黑客替換命令攻擊。
開發建議:嚴格按照要求使用
程序中重要的邏輯函數建議使用 NDK 技術經過 c/c++ 代碼實現。
由於 APK 自己未進行專業加固保護,存在被 baksmali/apktool/dex2jar 直接反編譯獲取程序 Java 代碼的風險,建議程序的重要函數使用 Android ndk 技術經過 c/c++ 實現,將重要函數編譯到 so 庫中,可以提升重要函數的邏輯安全強度。
發佈的軟件,應對 APP 進行加固,防止攻擊者獲取 APP 代碼、業務邏輯、API 接口等,對業務和公司聲譽形成必定影響,防止 APP 被破解二次打包,致使損失。
開發建議:APP 加固
整理了一些關於平時開發中會用到的知識點。須要更多相關的代碼源碼等等的能夠討論哦 本專欄爲那些想要進階成爲高級Android工程師所準備。 從初中級轉向高級工程師須要從技術的廣度,深度上都有必定的造詣。因此本專欄就主要爲你們分享一些技術,技術原理等。 包含源碼解析,自定義View,動畫實現,架構分享等。 內容難度適中,篇幅精煉,天天只需花上十幾分鍾閱讀便可。 你們能夠跟我一塊兒探討,有flutter—底層開發-性能優化—移動架構—資深UI工程師 —NDK-人工智能相關專業人員和視頻教學資料 。後續還有最新鴻蒙系統相關內容分享。
歡迎加羣討論交流:765080964