Android安全知識筆記合集

反編譯

反編譯代碼

  • dex2jar 這個工具用於將dex文件轉換成jar文件
  • jd-gui 這個工具用於將jar文件轉換成java代碼 ,使用jd-gui工具打開classes-dex2jar.jar這個文件就能查看Java代碼

反編譯資源

  • apktool 這個工具用於最大幅度地還原APK文件中的9-patch圖片、佈局、字符串等等一系列的資源。

沒有反編譯資源以前,AndroidManifest.xml和activity_main.xml這樣的資源文件都是非明文的,沒法閱讀。php

從新打包

微信圖片_20191207175045.png

smali文件夾的目錄結構和咱們源碼中src的目錄結構是幾乎同樣的,主要的區別就是全部的java文件都變成了smali文件。smali文件其實也是真正的源代碼,只不過它的語法和java徹底不一樣,它有點相似於彙編的語法,是Android虛擬機所使用的寄存器語言html

使用smali語法,修改代碼,就能從新編譯本身的apk。可是apk還不能安全,由於還沒簽名。java

由於沒法得到原來正版的簽名,可使用Android Studio生成本身的簽名,進行打包,生成本身的apk。android

參考:

blog.csdn.net/guolin_blog…web

混淆

混淆的好處:

  • 令 APK 難以被逆向工程,增長反編譯的成本。
  • 打包時移除無用資源,減小 APK 體積。

啓動混淆

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

複製代碼
  • minifyEnabled 設置爲 true 來開啓混淆
  • 設置 shrinkResourcestrue 來開啓資源的壓縮。
  • 通常在打 release 包時才啓用混淆,由於混淆會增長額外的編譯時間,因此不建議在 debug 模式下啓用。
  • 須要注意的是:只有在啓用混淆的前提下開啓資源壓縮纔會有效!
  • 以上代碼中的 proguard-android.txt 表示 Android 系統爲咱們提供的默認混淆規則文件,而 proguard-rules.pro 則是咱們想要自定義的混淆規則,

不能被混淆的元素

枚舉

枚舉類內部存在 values 方法,混淆後該方法會被從新命名,並拋出 NoSuchMethodException。Android 系統默認的混淆規則中已經添加了對於枚舉類的處理,咱們無需再去作額外工做。算法

被反射的元素

緣由在於:代碼混淆過程當中,被反射使用的元素會被重命名,然而反射依舊是按照先前的名稱去尋找元素,因此會常常發生 NoSuchMethodExceptionNoSuchFiledException 問題。數據庫

實體類

實體類即咱們常說的"數據類",固然常常伴隨着序列化反序列化操做。不少人也應該都想到了,混淆是將本來有特定含義的"元素"轉變爲無心義的名稱,因此,通過混淆的"洗禮"以後,序列化以後的 value 對應的 key 已然變爲沒有意義的字段,這確定是咱們不但願的。api

反序列化的過程建立對象從根本上來講仍是藉助於反射,混淆以後 key 會被改變,因此也會違背咱們預期的效果。安全

四大組件

Android 中的四大組件一樣不該該被混淆。緣由在於:bash

  1. 四大組件使用前都須要在 AndroidManifest.xml 文件中進行註冊聲明,然而混淆處理以後,四大組件的類名就會被篡改,實際使用的類與 manifest 中註冊的類並不匹配,故而出錯。
  2. 其餘應用程序訪問組件時可能會用到類的包名加類名,若是通過混淆,可能會沒法找到對應組件或者產生異常。

JNI 調用的Java 方法

當 JNI 調用的 Java 方法被混淆後,方法名會變成無心義的名稱,這就與 C++ 中本來的 Java 方法名不匹配,於是會沒法找到所調用的方法。

其餘不該該被混淆的

  • 自定義控件不須要被混淆
  • JavaScript 調用 Java 的方法不該混淆
  • Java 的 native 方法不該該被混淆
  • 項目中引用的第三方庫也不建議混淆

參考

郭霖:blog.csdn.net/guolin_blog…

juejin.im/post/5d1717…

WebView

問題:WebView明文存儲密碼帶來的安全漏洞
  • WebView組件默認開啓了密碼保存功能,會提示用戶是否保存密碼,當用戶選擇保存在WebView中輸入的用戶名和密碼,則會被明文保存到應用數據目錄的databases/webview.db中。攻擊者可能經過root的方式訪問該應用的WebView數據庫,從而竊取本地明文存儲的用戶名和密碼。
解決方案:
  • 開發者調用 WebView.getSettings().setSavePassword(false),顯示調用API設置爲false,讓WebView不存儲密碼

四大組件

問題:動態註冊Receiver風險
  • 使用BroadcastReceiver組件須要動態註冊或者靜態註冊,若是動態註冊廣播,即在代碼中使用registerReceiver()方法註冊BroadcastReceiver,只有當registerReceiver()的代碼執行到了才進行註冊,取消時則調用unregisterReceiver()方法。但registerReceiver()方法註冊的BroadcastReceiver是全局的而且默承認導出的,若是沒有限制訪問權限,能夠被任意外部APP訪問,向其傳遞Intent來執行特定的功能。所以,動態註冊的BroadcastReceive可能會致使拒絕服務攻擊、APP數據泄漏或是越權調用等安全風險
解決方案:
  • 1:在 AndroidManifest.xml 文件中使用靜態註冊 BroadcastReceiver,同時設置 exported="false",不被外部應用調用。 2:必須動態註冊 BroadcastReceiver時,使用registerReceiver(BroadcastReceiver,IntentFilter,broadcastPermission,android.os.Handle)函數註冊。 3:Android8.0新特性想要支持靜態廣播、須要添加intent.setComponent(new ComponentName()),詳情能夠自行查閱
問題:公共組件配置風險
  • Activity、Service、Provider、Receiver四大組件若配置爲android:exported =」true」,將能夠被外部應用調用,這樣存在安全隱患的風險。
解決方案:
  • 在應用的AndroidManifest.xml文件中,設置組件的android:exported 屬性爲false或者經過設置自定義權限來限制對這些組件的訪問。值得一提的是,若部分功能使用前提是配置必須使用exported爲true,這種狀況開發者應該根據實際狀況來進行集成
問題:數據越權備份風險
  • Android 2.1以上的系統能夠爲APP提供應用程序數據的備份和恢復功能,該功能由AndroidMainfest.xml文件中的allowBackup 屬性值控制,其默認值爲true。當該屬性沒有顯式設置爲false時,攻擊者可經過adb backupadb restore對APP的應用數據進行備份和恢復,從而可能獲取明文存儲的用戶敏感信息,如用戶的密碼、證件號、手機號、交易密碼、身份令牌、服務器通訊記錄等。利用此類信息攻擊者可僞造用戶身份,盜取用戶帳戶資產,或者直接對服務器發起攻擊。
解決方案:
  • 將AndroidMainfest.xml文件中的allowBackup屬性值設置爲false來關閉應用程序的備份和恢復功能;也可使用專業安全加固方案的本地數據保護功能,避免本地數據泄露。

數據存儲安全:加密和JNI寫入Native層

一、祕鑰及敏感信息

此類配置應當妥善存放,不要在類中硬編碼敏感信息,可使用JNI將敏感信息寫到Native層

二、SharePreferences

首先不該當使用SharePreferences來存放敏感信息,sharedpreferces存儲的xml文件數據可能被反編譯拿到。存儲一些配置信息時也要配置好訪問權限,如私有的訪問權限 MODE_PRIVATE(Activity.MODE_PRIVATE,//默認操做模式,表明該文件是私有數據,只能被應用自己訪問,在該模式下,寫入的內容會覆蓋原文件的內容),避免配置信息被篡改。

三、SQLite數據庫文件的安全性 – 描述:敏感信息是否明文存儲 – 檢測:檢測數據庫裏面的重要信息,好比帳號密碼之類的是否明文存儲 – 建議:重要信息進行加密存儲

日誌數據泄露:Log控制,正式環境不打印

問題:日誌數據泄露風險

  • 調試信息函數可能輸出重要的調試信息,常見的就是Log日誌類其中包含的信息可能會致使用戶信息泄露,泄露核心代碼邏輯等,爲發起攻擊提供便利,例如:Activity的組件名;通訊交互的日誌;跟蹤的變量值等
解決方案:
  • 應用內使用統一的Log控制基類,能夠靈活的控制Log的輸出打印。(測試環境容許打印日誌、正式環境不打印);或者使用第三方的日誌框架

參考:

www.jianshu.com/p/79b30238b…

zhuanlan.zhihu.com/p/35100057

網絡安全:HTTPS、使用簽名和數據加密加密

1.1 無處不在的安全隱患

  • 由於http協議是明文傳輸的,能夠採起MD5值傳輸和存儲,近幾年MD5破解能力提升,因此如今一般生成MD5值時都須要加鹽,例如MD5(name+pwd)做爲密碼存儲,一樣的密碼生成的值是不同的,在必定程度上提升了安全性。
  • 攻擊不必定須要用戶名密碼,或許能夠直接打token和uid的主意。,一旦用戶登陸後,服務器就經過token來標識身份。若是這個token被黑客劫持了,他就能夠冒充你的身份進行攻擊,若是token機制設計不合理,攻擊者甚至能夠直接暴力去撞token。大部分網站的機制也相似,服務器經過一個sessionId標識用戶,攻擊者一旦拿到這個sessionId,就能夠去冒充一個合法用戶。

1.2 使用https是否就萬事大吉

  • https分單向認證和雙向認證,大部分的應用場景是c/s模式,這時一般都是採用的單向認證的方式,也就是說能夠保證客戶端拿到的數據是後臺發送的,攻擊難度很大,除非你能忽悠別人安裝並信任你的證書
  • 可是,不少人蹭wifi時或者在網上下載一些資源,系統提示要信任什麼東西,看都不看就點肯定。
  • 使用抓包工具時,給目標設備安裝並信任裝包工具的自簽名證書,這時候就能夠分析https請求
    • 杜絕 HTTPS 抓包的原理很簡單,其實就是攔截非法的證書,只經過咱們信任的 HTTPS 證書的請求。
    • 還有一種比較簡單,直接設置okhttp禁用代理模式,也能夠避免一些抓包。可是用戶可能須要代理上網,這麼禁止會引來其餘問題
    • 參考:www.jianshu.com/p/11577eb0c…

1.3 使用簽名和加密數據

上面能夠看到,https並不能阻擋攻擊者分析請求接口併發起惡意請求攻擊,爲了增長攻擊者分析請求的難度,一般能夠採用兩種方式:

  • 使用簽名。

    • 即給你的請求參數添加一個簽名,後臺服務接收到請求時,先驗證簽名,簽名不正確的話,則不予處理。簽名規則五花八門,大體策略就是根據請求參數作一些運算最後生成一個惟一的字符串當作sign
    • 微信支付的簽名的規則能夠參考:pay.weixin.qq.com/wiki/doc/ap…
  • 數據加密。

    • post到服務器和從服務器返回的數據都作加密,這樣的話即便攻擊者拿到你的數據,他不知道你的加密算法就無能爲力了。
  • 祕鑰使用JNI將敏感信息寫到Native層

參考:

www.jianshu.com/p/fe0206f8b…

JNI:儲存敏感信息,核心算法和祕鑰

  • 一些常量是不會/不能被混淆的,這種敏感信息就須要額外保護
  • 核心算法和祕鑰,通常選擇放到native層

native代碼的安全性保證

  • 相對於java代碼容易被反編譯,使用NDK開發出來的原生C++代碼編譯後生成的so庫是一個二進制文件,這無疑增長了破解的難度。利用這個特性,能夠將客戶端敏感信息寫在C++代碼中,加強應用的安全性。
  • 萬一別人將你的so庫直接copy出來拿去用了呢?所以,咱們還須要在native層對應用的包名、簽名進行鑑權校驗,若是不是本身的應用,不返回相關信息,或者直接退出應用!

安全風險

  • 用ndk開發,將密鑰放在so文件,加密解密操做都在so文件裏,這從必定程度上提升了的安全性,擋住了一些逆向者,可是有經驗的逆向者仍是會使用IDA破解的。
  • 在so文件中不存儲密鑰,so文件中對密鑰進行加解密操做,將密鑰加密後的密鑰命名爲其餘普通文件,存放在assets目錄下或者其餘目錄下,接着在so文件裏面添加無關代碼(花指令),雖然能夠增長靜態分析難度,可是可使用動態調式的方法,追蹤加密解密函數,也能夠查找到密鑰內容。

參考:

www.jianshu.com/p/fe0206f8b…

zhuanlan.zhihu.com/p/34902225

即時通信安全篇(四):實例分析Android中密鑰硬編碼的風險

加殼與脫殼

不管是編譯java代碼生成的dex文件,仍是編譯C/C++代碼生成的so文件,反編譯成本都不是特別的高。

加殼直觀理解就是給程序加一層殼,能夠用來對原程序進行資源壓縮、防調試、防注入、防反編譯,也就是說經過一個殼把原來的程序保護了起來。

咱們知道一個常規Android程序它的全部代碼都在dex文件中,程序啓動時要先把這個dex文件載入到內存中,因此若是要加殼的話,主要工做就是把原dex文件加密或者隱藏起來,放一個新的殼dex到apk中,程序啓動時運行這個殼dex,而後這個殼dex在運行時再加載原dex,用一張圖表示以下:

微信圖片_20191207174907.png
  • xposed框架這樣的hook技術,相似於降維打擊,能夠繞過加固技術輕鬆獲取到dex文件。目前的樂固、360等大廠加固均可以繞過。

    • 加固也避免dex文件直接暴露在apk壓縮文件中,可是加固也有明確的缺點,可能會影響啓動的速度,apk體積增大,沒法使用補丁,依然能夠脫殼逆向。因此加固已經再也不被推薦使用,基本上大公司的apk都不會使用加固技術。

補充:hook和xposed

什麼是 Hook

Hook 又叫「鉤子」,它能夠在事件傳送的過程當中截獲並監控事件的傳輸,將自身的代碼與系統方法進行融入。這樣當這些方法被調用時,也就能夠執行咱們本身的代碼。

Xposed

  • 能夠在不修改APK的狀況下影響程序運行(修改系統)的框架服務。
  • 替換本身的代碼,使得程序加載Xposed的jar包,完成劫持
  • install的時候須要root權限,可是運行時不須要root權限

經過替換 /system/bin/app_process 程序控制 Zygote 進程,使得 app_process 在啓動過程當中會加載 XposedBridge.jar 這個 Jar 包,從而完成對 Zygote 進程及其建立的 Dalvik 虛擬機的劫持。 Xposed 在開機的時候完成對全部的 Hook Function 的劫持,在原 Function 執行的先後加上自定義代碼

Xposed框架介紹以及原理

XposedGithubrovo89大佬設計的一個針對Android平臺的動態劫持項目,經過替換/system/bin/app_process程序控制Zygote進程,使得app_process在啓動過程當中會加載XposedBridge.jar這個jar包,從而完成對Zygote進程及其建立的Dalvik虛擬機的劫持。

由於Xposed工做原理是在/system/bin目錄下替換文件,在install的時候須要root權限,可是運行時不須要root權限。

看到這裏不少人會很懵,什麼是Zygote?簡單來講在Android系統中,應用程序進程都是由Zygote進程孵化出來的,而Zygote進程是由Init進程啓動的。Zygote進程在啓動時會建立一個Dalvik虛擬機實例,每當它孵化一個新的應用程序進程時,都會將這個Dalvik虛擬機實例複製到新的應用程序進程裏面去,而一個應用程序進程被Zygote進程孵化出來的時候,不只會得到Zygote進程中的Dalvik虛擬機實例拷貝,還會與Zygote一塊兒共享Java運行時庫。這也就是能夠將XposedBridge這個jar包加載到每個Android應用程序中的緣由。XposedBridge有一個私有的Native(JNI)方法hookMethodNative,這個方法也在app_process中使用。這個函數提供一個方法對象利用JavaReflection機制來對內置方法覆寫。。。。等等這些都會借鑑各路大神的思路和分析,總而言之,就是從底層替換方法,可讓咱們在不修改APK源碼的狀況下,經過本身編寫的模塊來影響程序運行的框架服務,實現相似於自動搶紅包、微信消息自動回覆等功能。 其實,從本質上來說,Xposed模塊也是一個Android程序。但與普通程序不一樣的是,想要讓寫出的Android程序成爲一個``Xposed 模塊,要額外多完成如下四個硬性任務:

一、讓手機上的xposed框架知道咱們安裝的這個程序是個xposed模塊。

二、模塊裏要包含有xposed的API的jar包,以實現下一步的hook操做。

三、這個模塊裏面要有對目標程序進行hook操做的方法。

四、要讓手機上的xposed框架知道,咱們編寫的xposed模塊中,哪個方法是實現hook操做的。
複製代碼

參考:

www.jianshu.com/p/fe0206f8b…

加密算法

加密主要有對稱加密、非對稱加密,不可逆加密。

對稱加密AES

AES主要是用在數據自己的加密,即便傳輸過程當中被截取了,也是加密事後的數據。但AES的弊端的是,客戶端加密的話,密鑰確定是儲存在app中,若是app被成功破解了,數據也就被暴露了。因此只有app自己程序的安全也解決了,app才能相對安全。

非對稱加密RSA

由於RSA加密有個長度限制,這就致使了RSA加密不能用於全部的數據交互。可是能夠用到一些短數據,好比用戶我的信息之類的,在交易中,一次訂單的數據也不是很大等。

不可逆加密

好比MD5加密SHA加密等。所謂的不可逆加密就是,只能單向加密,不能反向解密。MD5把數據加密,最後獲得固定長度的16進制編碼。這個加密的做用通常是匹配驗證,驗證某個數據是否改變。好比密碼,在向服務器存儲密碼,通常不會存儲明文密碼。安卓本地存儲個標誌也通常不會明文存儲。

Android官方

推出了JetPack Security 。

確保數據安全 - 深刻解讀加密與安全開發 | AndroidDevSummit 中文字幕視頻

相關文章
相關標籤/搜索