1. 程式人生 > >最佳實踐-android程式安全

最佳實踐-android程式安全

自文章主要是翻譯的官網文章,同時也加入了自己的理解,如有不準確之處,請指正
http://developer.android.com/guide/practices/security.html


一些虛擬機器執行在一個安全邊界內,與所在的作業系統的程式隔離開來,比如java虛擬機器和.net 執行環境。
在android上,Dalvik虛擬機器沒有這樣的安全邊界,應用程式沙箱是實現在作業系統級別的,因此
在同一個程式,Dalvik與native code進行互動沒有任何的安全邊界。


給移動裝置閒置儲存策略。正常情況下,開發者想建立模組化的應用程式,通過動態類載入實現。當做這件事的
時候要考慮兩個問題:程式邏輯和儲存位置。不要使用沒有檢查的class資源,比如不安全的網路資源或者外部儲存
裝置上的資源,因為這樣的資源可以被修改,可以包含進惡意的動作。


使用native code



一般情況下,我們建議開發者使用android sdk開發大多數的程式,而不是使用native code。程式使用native code去
構建會更加的複雜,龐大,還有可能會有一些常見的記憶體使用錯誤,比如緩衝區異常。


android是構建在Linux核心之上的,如果你熟悉Linux開發的話,使用native code是比較好。這個文件只是用了很少的篇幅
介紹了這個最近實踐,要想了解更多關於為LInux和Unix程式設計安全的資源,請訪問這個網址http://www.dwheeler.com/secure-programs


android與其他的大多數Linux執行環境一個重要的不同是:程式沙箱。在android上,所有的程式都是在沙箱內執行,即使程式包含
native 程式碼。熟悉Linux的開發者都知道每個程式被分配一個唯一的UID和有限的許可權,當然即使你對Linux不熟悉,也要明白這一點。
如果你使用native code需要熟悉程式許可權的內容。http://source.android.com/tech/security/index.html


儲存資料

使用程式內部儲存
預設情況下,在程式內部建立的檔案只能被本程式使用。對於大多數程式的安全儲存已經足夠了。


在程序間使用全域性的讀或者寫許可權不建議,這樣的話不能限制一些特定的程式去訪問資料,同時也不能控制資料格式。
做為一種選擇是,使用ContentProvider同讀寫允許,也可以根據具體情況動態的授予是否允許訪問資料。


為了給敏感資料提供更多的保護,一些程式選擇使用金鑰對本地檔案加密的方式。比如,金鑰放在keystore中,用
來保護使用者的密碼,而不是直接儲存在裝置上。然而這樣的情況下不能保護資料:裝置是root過的,使用者的輸入的密碼
可以被監聽到。可以保護有檔案加密系統的裝置丟失的情況。


使用外部儲存



在外部儲存裝置上儲存檔案時全域性的讀寫許可權,比如在SD卡上。因為外部儲存裝置可以使用者移除,可以被任何程式修改,
不要把敏感的資料使用外部儲存裝置儲存。


對於從任何不可以信任的源獲取的資料,程式從外部儲存獲取的都應該對輸入進行檢查。我們強烈的建議不要在外部儲存裝置上
儲存動態載入的可執行檔案或者類檔案。如果程式從外部儲存載入可執行的檔案,檔案必須是簽過名的和加密的,並且在載入前檢查。


使用內容提供者


ContentProvider提供一個儲存機制,這個機制可以限制自己的程式,也可以為其他程式提供一個訪問入口。預設情況下,
一個ContentProvider是其他程式提供給使用者的入口。如果你不想讓其他程式訪問你的ContentProvider,在manifest檔案中
這樣表明android:exported=false.


建立一個ContentProvider,將會為其他程式開啟了一個入口,你可以指定一個讀寫許可權或者把讀寫許可權分開指定。我們建議
你把許可權分開,按需分配。記住,通常情況為以後的新功能增加許可權更容易一些,而不是去移走他們,而影響已經存在的使用者。


如果ContentProvider是用來在同一個開發者開發的兩個程式之間共享資料,應該傾向於使用簽名級別的許可權,簽名許可權不需要使用者確認,
因此會有更加好的使用者體驗,更多對ContentProvider的訪問控制。


ContentProvider還尅提供更多反問宣告,通過grantUriPermison元素指定,使用FLAG_GRANT_READ_URI_PERMISSION 和 FLAG_GRANT_WRITE_URI_PERMISSION
這些標誌在Intent物件上。許可權的範圍可以同grant-uri-permisstion元素進一步限制。


當訪問ContentProvider的時候,使用帶引數的方法,例如query(),update()和delete(),可以防止不信任資料潛在的sql注入風險。
注意,如果使用組裝起來的資料提交到這些方法的話,使用引數化的方法還不夠安全。




不要有對寫許可權有這樣一個錯誤的看法,可以想象一下,寫許可權允許使用sql語句,使一些資料可以使用where子句組裝結果。
舉個例子,一個攻擊者可能為了檢視一個已經存在的電話號碼,如果那個號碼已經存在的話,就在call-log修改一行資料。
如果這個內容提供者有個可被預見的結構的話,這個寫許可權會相當於同時提供了讀與寫許可權。


Using Interprocess Communication (IPC)
使用程序間通訊


一些android程式企圖使用傳統的Linux程序間通訊技術,比如網路socket和共享檔案。我們強烈件事使用android系統的程序
通訊技術,不如Intent,Binder,Service和Receiver.android的IPC機制允許你驗證程式連線你的IPC程式是否合法,可以
為IPC設定安全策略。


很多安全元件都是通過IPC機制共享資料的。廣播接收者,活動,服務都是在程式的manifest中宣告的。如果你的IPC機制不想
讓其他的程式訪問,設定android:exported的屬性為false。這是非常有用處,對於多個程式的多個程序使用同一UID,或者
你後來決定不想通過IPC共享資料,就不需要重寫程式碼了。


如果你的IPC是為了讓其他的程式器訪問的,你可以通過設定許可權標誌作為安全策略。如果IPC是同一個開發者的程式,
應該使用簽名級別的許可權控制,簽名許可權不需要使用者確認,因此會有一個更好的使用者體驗,更多的IPC訪問控制。




使用intent過濾的地方容易混淆,注意,intent過濾不應該認為是安全的特徵,這個元件可以被直接呼叫,並且不會有
對intent過濾的確認。你應該執行輸入驗證,確保你的intent接受者接到receiver,service,和activity傳送的格式正確。
 
Using intents


意圖是android中推薦的非同步IPC機制。基於你的程式需求,你可以使用sendBroadcaset(),sendOrderedBraodcast()或者
直接傳送intent給指定的程式元件。


注意,ordered broadcast可以被所有的接收者消費掉,可能不會發送到所有的程式。如果你想傳送給一個指定的接收者一個intent,這個intent必須直接傳送
給指定的這個接受者。


如果沒有指定許可權限制的intent,可能會被別的接收者收到。限制成只有指定許可權的接收者才能收到這個intent.設定intent的許可權,可以
提高安全性。


使用 binder 和 AIDL 介面
binder是android遠端呼叫IPC的推薦機制。


We strongly encourage designing interfaces in a manner that does not require interface specific
 permission checks. Binders are not declared within the application manifest, and therefore you 
cannot apply declarative permissions directly to a Binder. Binders generally inherit permissions 
declared in the application manifest for the Service or Activity within which they are implemented. 
If you are creating an interface that requires authentication and/or access controls on a specific 
binder interface, those controls must be explicitly added as code in the interface.


If providing an interface that does require access controls, use checkCallingPermission() 
to verify whether the caller of the Binder has a required permission. This is especially 
important before accessing a Service on behalf of the caller, as the identify of your 
application is passed to other interfaces. If invoking an interface provided by a Service, 
the bindService() invocation may fail if you do not have permission to access the given Service. 
If calling an interface provided locally by your own application, it may be useful to use the
 clearCallingIdentity() to satisfy internal security checks.


使用ip網路:
建議使用Https協議的網路,其他不安全協議的網路儘量不要使用。當使用公共wiff熱點的時候,這些開放的網路都是沒有
加密的網路。


使用電話網路
有sms這個技術是為了人對人之間的通訊設計的,所以對於某些程式來說並不合適,建議使用C2DM和ip網路傳送資料資訊到裝置。
sms在網路傳輸的過程中,沒有對資料加密,沒有很強的驗證機制。特別是,任何sms接收者都可以接收到惡意者傳送的資訊到你的程式,
不要使用沒有經過認證的sms執行操作敏感資訊的命令。還有認識到一點,sms可能會被截獲或者通過sms進行欺騙。在android的裝置
上,SMS資訊傳輸是通過廣播意圖的形式傳送的,因此訊息有可能被擁有能夠閱讀SMS許可權的程式給截獲閱讀。


動態載入程式碼


我們強烈的不推薦apk程式不要從外部動態載入程式碼。如果這樣做的話會增加程式碼注入和程式碼篡改的風險。
並且還會影響版本控制盒程式測試。最後,還會導致程式的行為不好驗證,因此在某些情況下程式會被阻止掉。


如果你的程式做了動態載入程式碼,最重要的一點,要時刻記住動態載入的程式碼所在的apk要和載入程式要有相同的安全許可權。使用者決定
安裝你的程式是基於統一的標示認證。


動態載入程式碼最大的安全風險是驗證程式碼來源。如果程式模組直接包含到你的apk中,那麼其他程式是不能去修改的。不管是native庫還是通過DexClassLoader載入的
程式碼都是如此。我們已經遇到過很多程式去試圖載入不安全位置的程式碼,比如像從網路上下載沒有經過安全協議加密的程式碼,或者從想外部儲存等
有全域性寫許可權的位置載入程式碼。這些位置會允許一些人在網路傳輸過程中修改資料的內容,或者安裝在裝置上的程式去修改資料內容。


使用 WebView


因為WebView這個元件可以解析HTML和Javascript等網頁內容,這樣可能會遇到一些常見的安全問題,比如跨站指令碼攻擊(cross-site-scripting,javascript注入)。
android包含了大量的安全機制用來減少這種跨域的譴責問題,像通過限制WebView使用最少功能這樣的措施。


如果你的程式中的WebView不直接使用Javascript的話,不要呼叫setJavaScriptEnabled()。預設情況下,WebView不會執行跨站指令碼
javascript的執行。


使用addJavaScriptInterface()時要特別注意,因為這樣可以允許javascript去呼叫android程式程式碼去執行程式。
只把addJavaScriptInterface()開放給信任的輸入源,如果不是這樣的話有時會使不信任的javascript去呼叫android的函式。
通常情況下,我們推薦只對本程式內的javascript開放addJavaScriptInterface()入口。


不要相信通過http下載的資料,要使用Https代替。如果你僅是訪問單個網站,即使是信任並且可控的,HTTP可能會受到中間過程的攻擊,
傳輸過程中資料被擷取。在使用addJavaScriptInterface()的時候要提高警惕,一定不要相信通過http下載的沒有經過驗證的指令碼。
注意:即使是用的https,addJavaScriptInterface()也會增加了程式被攻擊的可能性,雖然包括伺服器的進行了安全設定和android裝置擁有所有的信任的CA。


如果你同過WebView訪問敏感資訊,你應該通過clearCache()方法去刪除儲存在本地的任何快取檔案。伺服器端的小訊息頭可以使用
像no-cache這樣的標誌去告訴程式不要快取特定的內容。


執行輸入檢查


一個常見的安全問題是沒有對輸入進行充足的安全檢查就直接讓其執行。android有一個平臺級別的措施去減少暴露給程式沒有進行輸入檢查的問題,
你應該儘可能的在可以使用的任何地方去使用這個特性。同時要注意,選擇安全型別的語言可以減少輸入驗證的問題。我們強烈建議使用android SDK
去構建你的程式。


如果使用從檔案,網路,IPC上獲取的native code,也會增加潛在的安全問題。常見的問題是緩衝區溢位,使用者退出,off-by-one錯誤等。android
提供了很多像ASLR和DEP的技術去減少開發時的那些錯誤,但是他們不能解決這些潛在的錯誤。那些技術可以用來預防指標控制和快取區管理的問題。


動態的,基於字串的語言,像javascript和sql語言,進行輸入檢查可以防止特殊字元和指令碼注入問題。


如果經行資料查詢的時候有使用sql資料庫或者內容提供者的時候,sql注入會使一個問題。最後的反擊措施是使用引數化的查詢,就想在內容提供者
部分介紹的一樣。限制成只讀和只寫許可權也可以減少潛在的sql注入風險。


如果你使用WebView一定要考慮誇張指令碼攻擊(XSS)的可能性。如果你的程式,WebView不直接使用javascript,
不要呼叫setJavaScriptEnabled(),那麼XSS就不會發生。如果程式必須使用javascript,那麼要考慮其他的安全措施
去防止XSS。


如果你不能使用上述的安全特性,我們強烈建議使用良好結構的資料格式,並且充分驗證資料格式,同時要做好特殊字元黑名單,和字元替換庫,這樣
會使一個比較有效的策略。這些技術是使用的過程中非常容易出錯,所以一定要儘量的避免出現錯誤。


處理使用者資料


通常情況下,最有效的方式是儘量的少使用API去訪問敏感資料和個人資訊。如果真的訪問的了這些資料的話,那麼就不乣儲存和傳輸這些資料。
最後,考慮使用一種方式是,使用雜湊演算法或者不可逆的演算法方式去處理資料。比如,如果你的程式使用hash演算法用對email的雜湊值作為key,一定要
避免儲存和傳輸email地址。這樣可以防止因為疏忽而把資料暴露在外面,這樣也可以減少暴露在外面的程式被攻擊的機會。


如果你的程式要訪問想使用者名稱,密碼之類的個人資訊是,一定要記住使用隱私協議去解釋你使用和儲存的資訊。因此,
在後面的的安全最佳實踐中,要儘量的減少訪問使用者資料


你也需要考慮你的程式是否會在不經意間把個人資訊暴露給其他的程式部分,比如像在你的程式中使用的第三方廣告元件或者第三方服務等。
如果你不知道為什麼這些元件或者服務需要個人資訊幹什麼的話,就不要提供給程式。通常情況下,減少訪問個人資訊,可以減少程式潛在的
安全問題。


如果必須要訪問敏感資料,要評估一下這些資料是否要傳輸到伺服器,或者是否要在客戶端執行。允許在客戶端的程式碼用到敏感資料的
時候要儘量禁止使用者資料的傳輸。




同時要確保,不要把使用者資料通過寬鬆的IPC,全域性可寫的檔案,或者網路不經意間暴露給其他程式。這裡有一個關於許可權重複授權的特殊案例將在請求許可權
的部分討論。

建立一個數比較大,唯一的全域性唯一標識儲存它是非常必要的。不要使用像電話號碼或者IMEI這樣的電話的標識,因為這些關係到個人資訊。
這個話題的更多資訊在android開發者部落格上。http://android-developers.blogspot.com/2011/03/identifying-app-installations.html


程式開發者需要特別注意寫在裝置上的日誌資訊,在android上,日誌是共享資源,要防止程式擁有READ_LOGS許可權。
即使手機的日誌是臨時的或者重啟就刪除的,記錄使用者資訊的日誌有可能會洩露使用者的資訊給其他程式。


Handling Credentials
處理憑證
通常情況下,我建議最小頻率的要使用者的憑證資訊,可以減少釣魚攻擊的成功率。而是使用授權令牌的方式,並且要重新整理令牌。


不管任何情況下都不要把使用者名稱密碼儲存在裝置上。
只有在第一次認證的時候需要使用使用者提供的使用者名稱和密碼,並且使用短活動週期,指定服務的授權令牌。


如果一個服務需要訪問多個程式的話,應該需要使用AccountManager.如果可能的話,使用AcctountMangaer類去呼叫雲服務,不要把
密碼儲存在裝置上。http://developer.android.com/reference/android/accounts/AccountManager.html


After using AccountManager to retrieve an Account, check the CREATOR before passing in any credentials, 
so that you do not inadvertently pass credentials to the wrong application.
使用AccountManager取回賬號後,傳遞憑證之前都要檢查一下建立者,不要把憑證傳給錯誤的程式。


如果憑證資訊之允許自己程式使用,當程式訪問AccounManager的時候要使用checkSignature()這個方法去雁陣程式的簽名。
如果只有一個程式訪問憑證資訊,可以使用KeyStore去儲存憑證資訊。


Using Cryptography
使用加密技術


增加資料的隔離,可以支援全檔案系統的加密,提供安全通道訪問。android提供了多種陣列加密演算法保護資料。


通常情況下,使用已經存在的高級別的框架可以支援大多數使用情況。如果你需要安全的從一個位置取回檔案,簡單的Https URI已經足夠滿足了。
如果你需要一個安全通道,考慮使用HttpsURLConnection or SSLSocket,而不是去寫自己的協議。


If you do find yourself needing to implement your own protocol, we strongly recommend that you not implement your
 own cryptographic algorithms. Use existing cryptographic algorithms such as those in the implementation of AES or 
RSA provided in the Cipher class.
如果你需要實現自己的協議,強烈建議不要實現自己的加密演算法。通過Cipher類使用已經存在的加密演算法,比如AES或者RSA。


使用安全的隨機數生成器(SecureRandom)去初始化任何加密的key(KeyGenerator).如果使用的key不是用安全生成的隨機數的話,會減少加密強度,
並且會允許離線攻擊。


如果你想把key存起來重複使用的話,可以使用想KeyStore之類的機制,通過加密金鑰進行長期的存取。


結論
android為開發者提哦那個了設計程式安全多種措施。這些最佳實踐確保你的程式能從安全獲取一些受益。


You can receive more information on these topics and discuss security best practices with 
other developers in the Android Security Discuss Google Group


你可以在Android Security Discuss Google Group中看到更多關於安全的話題或者討論。

相關推薦

最佳實踐-android程式安全

自文章主要是翻譯的官網文章,同時也加入了自己的理解,如有不準確之處,請指正http://developer.android.com/guide/practices/security.html 一些虛擬機器執行在一個安全邊界內,與所在的作業系統的程式隔離開來,比如java虛擬

安卓專案實戰之Gif圖片載入的最佳實踐android-gif-drawable開源庫的使用

前言 在平時的專案開發中,我們或多或少會遇到載入gif圖片這樣的需求,但是Android的ImageView又無法直接載入Gif圖片,面對這樣的需求我們一般都會想到使用支援載入gif動圖的Glide第三方庫來進行實現,但是使用過程中發現Glide在載入大的gif

《開源安全運維平臺--OSSIM最佳實踐》新書五折搶購(限時2天)

1-1 height lis ima pro ros nor none 分享圖片 《開源安全運維平臺--OSSIM最佳實踐》新書五折搶購,售完為止(該活動限時2天)當當自營店購買地址:http://product.dangdang.com/23903741.html LIN

Android最佳實踐之性能 - 多線程

ndt andro 單位 多線程 same Coding amount other err 在單獨線程執行代碼 參考地址:http://developer.andr

Android 應用兼容性最佳實踐 | 中文教學視頻

-s 播放 新特性 cmp 一起 更多 ide tar video 本期中文視頻向各位開發者介紹如何現代化您的應用,其中包括 Android?O、Android P?(預覽版)?的新特性、行為變更、應用開發中常見的兼容性最佳實踐,以及測試、兼容系統時需要註意的一些事項。希

[譯] Node.js 高效能和可擴充套件應用程式最佳實踐 [第 2/3 部分]

原文地址:Good practices for high-performance and scalable Node.js applications [Part 2/3] 原文作者:virgafox 譯文出自:掘金翻譯計劃 本文永久連結:github.com/xitu/gold

微信小程式開發最佳實踐

作者: skylor https://segmentfault.com/a/1190000012955804 專案地址:https://github.com/skyFi/weapp-starter 為什麼會有這個 repo 在小程式之初便開發應用了,現

Android MVP 最佳實踐

作者 Tamic MVC 起源和發展! MVP其實我接觸已經三年了,本文的實踐也是在17年實踐的,今天放出來也是為了分享給需要這快東西的同學,面試足夠了,好東西不能雪藏。 1 起源 MVC:全稱:Model - View - Controller,它是於1970年的時候有TrygveReen

安全程式設計(九)- Java集合類框架的最佳實踐

1.引言         根據應用的需要正確選定集合型別對效能非常重要! 2.例項         2.1假如集合元素的大小是固定的,而且能事先知道,我們就應該用Array而不是用ArrayList。文章

[譯] Node.js 高效能和可擴充套件應用程式最佳實踐 [第 1/3 部分]

原文地址:Good practices for high-performance and scalable Node.js applications [Part 1/3] 原文作者:virgafox 譯文出自:掘金翻譯計劃 本文永久連結:github.com/xitu/gold

Android效能最佳實踐:為您的APK進行瘦身

大家都知道開發中應用程式的效能是非常重要的,但是這也是優化提升的難點,本章針對 Android效能實踐——從減少APK的大小開始,提升使用者的體驗。 原文地址 https://developer.android.com/topic/performance/reduce-apk-

Android第一行程式碼實驗一)活動的最佳實踐

活動的最佳實踐    1.知曉當前是在哪一個活動         這個技巧將教會你,如何根據程式當前的介面就能判斷出這是哪一個活動。  首先需要新建一個 BaseActivity 繼承自

Android學習之基礎知識七—碎片的最佳實踐

一、Android碎片(Fragment)的最佳實踐——簡易版新聞應用 第一步:新建FragmentBestPractice專案,在app/build.gradle當中新增:RecyclerView 依賴庫,注意:新增完成後,一定要記住點選右上角的:Sync now 第二步:建立新聞實體類 第三

微信小程式客服訊息實時通知之最佳實踐

我們做微信小程式開發的都知道,只要在小程式頁面中新增如下程式碼即可進入小程式的客服會話介面:  <button open-type="contact" >聯絡我們</button>  微信小程式客服會話介面如下圖所示: 但是,客戶給我們小程式發的訊息,微信伺服器並不會通知小程式管

最佳實踐】微信小程式客服訊息實時通知如何快速低成本實現?

我們做微信小程式開發的都知道,只要在小程式頁面中新增如下程式碼即可進入小程式的客服會話介面: <button open-type="contact" >聯絡我們</button> 微信小程式客服會話介面如下圖所示:

TensorFlow學習筆記(6) TensorFlow最佳實踐樣例程式

在第三篇中編寫了一個程式來解決MNIST問題,這是一個沒有持久化訓練好的模型。當程式退出時,訓練好的模型就再也無法使用了,這導致得到的模型無法被重用。結合變數管理機制及模型持久化機制,對該程式進行進一步的優化重構。 優化重構之後的程式分為三個:第一個是mnist_inference.py,定義前

Android 底部導航欄(底部Tab)最佳實踐

  本文目錄.png 當開始一個新專案的時候,有一個很重要的步驟就是確定我們的APP首頁框架,也就是使用者從桌面點選APP 圖示,進入APP 首頁的時候展示給使用者的框架,比如微信,展示了有四個Tab,分別對應不同的板塊(微信、通訊錄、發現、我),現在市面出了少部分的Mate

聽說你還不會用Dagger2?Dagger2 For Android最佳實踐教程

前言 Dagger2是現在非常火的一個依賴注入框架,目前由Google維護,在Github上面已經有12K star了。Dagger2的入門門檻其實是比較高的,據瞭解,目前有很多Android工程師對Dagger2還不甚瞭解,沒有用上Dagger2或者是用法有問題,本文的主旨就是讓Android工程

Android 開發最佳實踐經驗分享

從Futurice公司Android開發者中學到的經驗。 遵循以下準則,避免重複發明輪子。若你對開發iOS或Windows Phone 有興趣, 請看iOS Good Practices 和 Windows client Good Practices 這兩篇文章。 摘要

Android 快速開發系列 ORMLite 框架最佳實踐

                上一篇已經對ORMLite框架做了簡單的介紹:Android ORMLite 框架的入門用法~~本篇將介紹專案可能會使用到的一些用法,也為我們的使用ORMLite框架總結出一個較合理的用法。通過上一篇的瞭解,我們使用ORMLite,需要自己寫一個DatabaseHelper去繼