1 前言
隨著無線客戶端的火熱發展,大家往往將所關注的重點放到了業務本身上,而忽視了安全問題。但是隨著近年來各種層出不窮的與客戶端相關的攻擊事件以及安全漏洞的曝出,客戶端安全已經不容忽視,忽視了安全必將會受到安全的懲罰。
而在各種安全之中數據安全更是重中之重,毫不誇張的說數據安全可以說是無線客戶端安全的靈魂。用戶的重要數據一旦損失掉,將會對應用乃至企業造成巨大的負麵影響。例如去年發生的CSDN的用戶名密碼泄露事件;和無線客戶端相關的有Skype Android版的用戶密碼、信用卡號泄露事件等,對於企業造成了不可估量的損失。
前麵會簡單介紹一下文件存儲可能存在的風險,後續會給出由於不注意這些安全問題在集團內和其他公司內所引發的血淋淋的例子。
不過大家了解之後主要是為了保護我們自身客戶端的安全以及一些功能的攻擊手法,不要幹壞事哦O(∩_∩)O~
2 Android客戶端安全風險
Android客戶端上數據的存儲主要分為四種:內部數據存儲、外部數據存儲、數據庫數據存儲、Content Provider數據存儲(其中數據庫的安全問題會有一篇文章單獨介紹、Content Provider的安全問題將會列入到組件安全的文章中去)
2.1 內部數據存儲
內部數據存儲主要分為兩種方式:SharedPreference存儲和文件存儲。
內部數據存儲的安全問題主要需要注意的是創建的模式以及向文件中寫入的內容。
SharedPreference : 是一種輕量級的數據存儲方式,它的本質是基於XML文件存儲key- value鍵值對數據,通常用來存儲一些簡單的配置信息。
File : 即常說的文件(I/O)存儲方法,常用存儲大量的數據。
內部數據存儲通常較為安全,因為他們可以受到Android係統的安全機製的保護。
Android的安全機製本質上就是Linux的安全機製,係統會為在Android係統上運行的每一個app創建一個進程,並為該進程分配一個UID。Android係統將會為每一個app創建一個特定的目錄/data/data/app_package_name,這個目錄的權限隻與UID相關,且隻有UID關聯的用戶才有該目錄相關的權限。
因此,在對應目錄下生成的SharedPreference文件與File文件如果以正確的方式去創建將會受到Android係統權限機製的保護。
這個正確的創建方式是指文件創建的模式,SharedPreference與文件的創建模式主要有以下三種:
MODE_PRIVATE:這個是默認的創建模式,該進程的UID對應的用戶將會對該文件擁有完全的控製的權限,而其他UID的用戶將沒有權限去讀/寫文件。
MODE_WORLD_WRITABLE:該權限將允許設備上所有的app對於該文件擁有寫的權限。
MODE_WORLD_READABLE:該權限將允許設備上所有的app對於該文件擁有讀的權限。
2.1.1 SharedPreference數據存儲實例
創建SharedPreference所使用的API為:
public abstract SharedPreferences getSharedPreferences (String name,
int mode)
(UI美化不太懂,大家湊合著看吧(*^__^*) )
就是通過點擊存儲按鈕將username:yaotong、password:tbsec以key-value對的形式存入到一個userinfo.xml的文件中(具體的代碼我會通過附件給出),注意這裏我創建SharedPreference的時候是以MODE_PRIVATE的模式進行創建的
創建後的文件的路徑為/data/data/com.yaotong.andgoat/shared_prefs/userinfo.xml
查看所創建的文件的權限可以通過兩種方式
1.通過DDMS查看,可以看到圖中紫色的方框為應用的權限,對於owner及owner所在組具有rw的完全的讀寫權限,而對於others用戶是沒有任何權限的

2.通過Shell來查看,可以看到通過shell查看看到的權限是與ddms中看到的權限是完全相同的,這樣代表應用是安全的

2.1.2 SharedPreference攻擊實例
下麵我來模擬一下攻擊者來盜取以MODE_PRIVATE模式和非MODE_PRIVATE模式所創建的文件會出現什麼樣的效果
(1).盜取以MODE_PRIVATE模式所創建的文件
盜取的代碼如下所示:
01 |
package com.yaotong.andattack; |
03 |
import android.os.Bundle; |
04 |
import android.app.Activity; |
05 |
import android.content.Context; |
06 |
import android.content.SharedPreferences; |
07 |
import android.content.pm.PackageManager.NameNotFoundException; |
08 |
import android.view.Menu; |
09 |
import android.view.View; |
10 |
import android.view.View.OnClickListener; |
11 |
import android.widget.Button; |
12 |
import android.widget.EditText; |
14 |
public class MainActivity extends Activity { |
16 |
private EditText btn_showtext;
|
17 |
private Button btn_submit;
|
19 |
public void onCreate(Bundle savedInstanceState) {
|
20 |
super .onCreate(savedInstanceState);
|
21 |
setContentView(R.layout.activity_main);
|
22 |
btn_showtext=(EditText) this .findViewById(R.id.showtext);
|
23 |
btn_submit=(Button) this .findViewById(R.id.submit);
|
24 |
btn_submit.setOnClickListener( new
OnClickListener() {
|
25 |
public void onClick(View v) {
|
26 |
// TODO Auto-generated method stub
|
28 |
Context andgoatContext = createPackageContext( 'com.yaotong.andgoat' , Context.CONTEXT_IGNORE_SECURITY);
|
29 |
SharedPreferences sharedPreferences = andgoatContext.getSharedPreferences( 'userinfo' , Context.MODE_WORLD_READABLE);
|
30 |
String username = sharedPreferences.getString( 'name' ,
'' );
|
31 |
String password = sharedPreferences.getString( 'password' , '' );
|
32 |
btn_showtext.setText(username+ '|' +password);
|
33 |
} catch (NameNotFoundException e){
|
41 |
public boolean onCreateOptionsMenu(Menu menu) {
|
42 |
getMenuInflater().inflate(R.menu.activity_main, menu);
|
當點擊按鈕盜取信息的時候,出現了如下的提示信息'Attempt to read preferences file /data/data/com.yaotong.andgoat/shared_prefs/userinfo.xml without permission',可以看到權限不夠,無法讀取文件

(2).盜取以非MODE_PRIVATE模式所創建的文件(MODE_WORLD_READABLE)
可以看到這時候others組有了對該文件讀的權限

再次點擊按鈕盜取信息,發現盜取成功

2.1.3 總結
由上麵的分析我們可以得出幾個重要的安全相關的結論:
(1).創建文件時的權限控製
如果在創建文件的時候沒有注意控製權限,那麼該文件的內容將會被其他的應用程序所讀取,這樣就造成了用戶相關信息的泄露,SharedPreference中存儲的往往是一些免登token、session id等和用戶身份息息相關的重要信息,因此在創建的時候一定要注意選取好創建的模式;注意免登token也一定要具有時效性,否則與存儲了明文的用戶名、密碼無異。
(2).SharedPreference中不要存入明文密碼等重要信息
由於有root的存在,那麼root過後的手機就打破了Linux提供的沙箱機製,那麼無論我們以何種方式去創建SharedPreference都已經不在安全了,如果存儲的是用戶明文的密碼,那麼用戶的密碼將會泄露,因此絕對不要向SharedPreference中寫入任何無時效性的重要的數據;
2.1.4 File存儲實例
創建文件所使用的API為:
public abstract FileOutputStream openFileOutput (String name,
int mode)
由於SharedPreference的本質就是一個xml文件,隻是Android係統單獨為它提供了一些列便於操作的API,因此文件存儲的本質與SharedPreference完全相同,所麵臨的安全風險和注意事項與SharedPreference完全相同,在此不再贅述。
唯一的區別是在讀取文件的時候我們在SharedPreference中使用了係統的操作
SharedPreference的相關API,而在這裏,我們完全采用JAVA I/O的方式去操作文件,例子如下所示:
1 |
File xmlFile = new
File(“/data/data/com.yaotong.andgoat/shared_prefs/userinfo.xml”)
|
2.2 外部數據存儲
外部存儲,通常是指將數據存入到設備的SD卡上。
外部存儲是一種不安全的數據存儲機製,因為存儲到SD卡上的文件默認是提供給others讀文件的權限的,設備上安裝的其他app隻要在其AndroidMenifest.xml上聲明如下的語句<uses-permission android:name='android.permission.WRITE_EXTERNAL_STORAGE'></uses-permission>,那麼該app就具有了對於SD卡的完全的讀寫權限,即是說一個app放在SD卡上的任何數據都可以被其他的app進行讀/寫操作,所以將重要數據存儲在SD卡上具有相當大的安全隱患。
2.2.1 外部數據存儲實例
操作界麵和代碼如下所示:當點擊存儲按鈕的時候,'yaotong|tbsec'字符串將會被存儲到相應的SD卡目錄下的userinfo.txt文件中

相關代碼:
01 |
public boolean WriteToSDcard(String file, String destDir, String szInText) throws IOException { |
02 |
if (mExternalStorageWriteable ==
true ) {
|
03 |
File mSDPath = android.os.Environment.getExternalStorageDirectory();
|
04 |
File mDestPath =
new File(mSDPath.getAbsoluteFile() + File.separator + destDir);
|
05 |
Log.e( 'ExternalStorageDirectory' ,mSDPath.getAbsoluteFile() + File.separator + destDir);
|
07 |
if (!mDestPath.exists()) {
|
10 |
mFile =
new File(mDestPath + File.separator + file);
|
13 |
mFile.createNewFile();
|
14 |
}
catch (IOException e) {
|
18 |
FileOutputStream mOutputStream;
|
19 |
mOutputStream =
new FileOutputStream(mFile);
|
20 |
mOutputStream.write(szInText.getBytes());
|
21 |
mOutputStream.close();
|
查看SD卡中文件的方法:
通過shell查看,可以看到SD卡下所有目錄others都具有讀的權限

接下來查看我們所創建的文件,發現文件others擁有讀的權限

2.2.2 總結
由上麵的分析我們可以得出如下的安全結論:
(1).存儲在SD卡中的數據是不安全的
SD卡中所創建的文件默認對於others具有可讀的權限,這就意味著你存儲在SD卡上的一切內容是可以被其他應用所讀取的;此外,隻要app在其AndroidMenifest.xml文件中聲明了寫SD卡的權限,那麼你存儲在SD卡上的數據也都可以被人修改。所以,一定不要在SD卡上存儲任何重要的數據,SD卡上的數據是不受Linux默認保護機製保護的。
3 和數據存儲相關的客戶端安全事件
不要以為安全很遙遠,安全就在你的身邊,包括一些大廠商都發生過類似的安全事件,我們要引以為鑒,不讓類似的問題發生在我們的身上。
內部數據存儲安全事件:
網易Android客戶端導致賬號密碼泄露
傳送門:https://www.wooyun.org/bugs/wooyun-2010-010056
Android手機明文存儲使用過的wifi密碼
外部數據存儲安全事件:
手機QQ2012(Android 3.0)導致用戶聊天記錄泄露
傳送門:https://www.wooyun.org/bugs/wooyun-2010-012838
小米MIUI係統造成用戶大量敏感數據泄露
傳送門:https://www.wooyun.org/bugs/wooyun-2010-08187