随着無線用戶端的火熱發展,大家往往将所關注的重點放到了業務本身上,而忽視了安全問題。但是随着近年來各種層出不窮的與用戶端相關的攻擊事件以及安全漏洞的曝出,用戶端安全已經不容忽視,忽視了安全必将會受到安全的懲罰。
而在各種安全之中資料安全更是重中之重,毫不誇張的說資料安全可以說是無線用戶端安全的靈魂。使用者的重要資料一旦損失掉,将會對應用乃至企業造成巨大的負面影響。例如去年發生的csdn的使用者名密碼洩露事件;和無線用戶端相關的有skype android版的使用者密碼、信用卡号洩露事件等,對于企業造成了不可估量的損失。
前面會簡單介紹一下檔案存儲可能存在的風險,後續會給出由于不注意這些安全問題在集團内和其他公司内所引發的血淋淋的例子。
不過大家了解之後主要是為了保護我們自身用戶端的安全以及一些功能的攻擊手法,不要幹壞事哦o(∩_∩)o~
android用戶端上資料的存儲主要分為四種:内部資料存儲、外部資料存儲、資料庫資料存儲、content provider資料存儲(其中資料庫的安全問題會有一篇文章單獨介紹、content provider的安全問題将會列入到元件安全的文章中去)
内部資料存儲主要分為兩種方式: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對于該檔案擁有讀的權限。
建立sharedpreference所使用的api為:
(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中看到的權限是完全相同的,這樣代表應用是安全的
下面我來模拟一下攻擊者來盜取以mode_private模式和非mode_private模式所建立的檔案會出現什麼樣的效果
(1).盜取以mode_private模式所建立的檔案
盜取的代碼如下所示:
<code>01</code>
<code>package com.yaotong.andattack;</code>
<code>02</code>
<code>03</code>
<code>import android.os.bundle;</code>
<code>04</code>
<code>import android.app.activity;</code>
<code>05</code>
<code>import android.content.context;</code>
<code>06</code>
<code>import android.content.sharedpreferences;</code>
<code>07</code>
<code>import android.content.pm.packagemanager.namenotfoundexception;</code>
<code>08</code>
<code>import android.view.menu;</code>
<code>09</code>
<code>import android.view.view;</code>
<code>10</code>
<code>import android.view.view.onclicklistener;</code>
<code>11</code>
<code>import android.widget.button;</code>
<code>12</code>
<code>import android.widget.edittext;</code>
<code>13</code>
<code>14</code>
<code>public class mainactivity extends activity {</code>
<code>15</code>
<code> </code>
<code>16</code>
<code> </code><code>private edittext btn_showtext;</code>
<code>17</code>
<code> </code><code>private button btn_submit;</code>
<code>18</code>
<code> </code><code>@override</code>
<code>19</code>
<code> </code><code>public void oncreate(bundle savedinstancestate) {</code>
<code>20</code>
<code> </code><code>super</code><code>.oncreate(savedinstancestate);</code>
<code>21</code>
<code> </code><code>setcontentview(r.layout.activity_main);</code>
<code>22</code>
<code> </code><code>btn_showtext=(edittext)</code><code>this</code><code>.findviewbyid(r.id.showtext);</code>
<code>23</code>
<code> </code><code>btn_submit=(button)</code><code>this</code><code>.findviewbyid(r.id.submit);</code>
<code>24</code>
<code> </code><code>btn_submit.setonclicklistener(</code><code>new</code>
<code>onclicklistener() { </code>
<code>25</code>
<code> </code><code>public void onclick(view v) {</code>
<code>26</code>
<code> </code><code>// todo auto-generated method stub</code>
<code>27</code>
<code> </code><code>try</code><code>{</code>
<code>28</code>
<code> </code><code>context andgoatcontext = createpackagecontext(</code><code>'com.yaotong.andgoat'</code><code>, context.context_ignore_security); </code>
<code>29</code>
<code> </code><code>sharedpreferences sharedpreferences = andgoatcontext.getsharedpreferences(</code><code>'userinfo'</code><code>, context.mode_world_readable); </code>
<code>30</code>
<code> </code><code>string username = sharedpreferences.getstring(</code><code>'name'</code><code>,</code><code>''</code><code>); </code>
<code>31</code>
<code> </code><code>string password = sharedpreferences.getstring(</code><code>'password'</code><code>,</code><code>''</code><code>);</code>
<code>32</code>
<code> </code><code>btn_showtext.settext(username+</code><code>'|'</code><code>+password);</code>
<code>33</code>
<code> </code><code>}</code><code>catch</code><code>(namenotfoundexception e){</code>
<code>34</code>
<code> </code><code>e.printstacktrace();</code>
<code>35</code>
<code> </code><code>}</code>
<code>36</code>
<code> </code><code>}</code>
<code>37</code>
<code> </code><code>});</code>
<code>38</code>
<code> </code><code>}</code>
<code>39</code>
<code>40</code>
<code>41</code>
<code> </code><code>public boolean oncreateoptionsmenu(menu menu) {</code>
<code>42</code>
<code> </code><code>getmenuinflater().inflate(r.menu.activity_main, menu);</code>
<code>43</code>
<code> </code><code>return</code>
<code>true</code><code>;</code>
<code>44</code>
<code>1</code>
<code>}</code>
當點選按鈕盜取資訊的時候,出現了如下的提示資訊'attempt to read preferences file /data/data/com.yaotong.andgoat/shared_prefs/userinfo.xml without permission',可以看到權限不夠,無法讀取檔案
(2).盜取以非mode_private模式所建立的檔案(mode_world_readable)
可以看到這時候others組有了對該檔案讀的權限
再次點選按鈕盜取資訊,發現盜取成功
由上面的分析我們可以得出幾個重要的安全相關的結論:
(1).建立檔案時的權限控制
如果在建立檔案的時候沒有注意控制權限,那麼該檔案的内容将會被其他的應用程式所讀取,這樣就造成了使用者相關資訊的洩露,sharedpreference中存儲的往往是一些免登token、session id等和使用者身份息息相關的重要資訊,是以在建立的時候一定要注意選取好建立的模式;注意免登token也一定要具有時效性,否則與存儲了明文的使用者名、密碼無異。
(2).sharedpreference中不要存入明文密碼等重要資訊
由于有root的存在,那麼root過後的手機就打破了linux提供的沙箱機制,那麼無論我們以何種方式去建立sharedpreference都已經不在安全了,如果存儲的是使用者明文的密碼,那麼使用者的密碼将會洩露,是以絕對不要向sharedpreference中寫入任何無時效性的重要的資料;
建立檔案所使用的api為:
由于sharedpreference的本質就是一個xml檔案,隻是android系統單獨為它提供了一些列便于操作的api,是以檔案存儲的本質與sharedpreference完全相同,所面臨的安全風險和注意事項與sharedpreference完全相同,在此不再贅述。
唯一的差別是在讀取檔案的時候我們在sharedpreference中使用了系統的操作
sharedpreference的相關api,而在這裡,我們完全采用java i/o的方式去操作檔案,例子如下所示:
<code>file xmlfile =</code><code>new</code>
<code>file(“/data/data/com.yaotong.andgoat/shared_prefs/userinfo.xml”)</code>
外部存儲,通常是指将資料存入到裝置的sd卡上。
外部存儲是一種不安全的資料存儲機制,因為存儲到sd卡上的檔案預設是提供給others讀檔案的權限的,裝置上安裝的其他app隻要在其androidmenifest.xml上聲明如下的語句<uses-permission android:name='android.permission.write_external_storage'></uses-permission>,那麼該app就具有了對于sd卡的完全的讀寫權限,即是說一個app放在sd卡上的任何資料都可以被其他的app進行讀/寫操作,是以将重要資料存儲在sd卡上具有相當大的安全隐患。
操作界面和代碼如下所示:當點選存儲按鈕的時候,'yaotong|tbsec'字元串将會被存儲到相應的sd卡目錄下的userinfo.txt檔案中
相關代碼:
<code>public boolean writetosdcard(string file, string destdir, string szintext) throws ioexception {</code>
<code> </code><code>if</code><code>(mexternalstoragewriteable ==</code><code>true</code><code>) {</code>
<code> </code><code>file msdpath = android.os.environment.getexternalstoragedirectory();</code>
<code> </code><code>file mdestpath =</code><code>new</code> <code>file(msdpath.getabsolutefile() + file.separator + destdir);</code>
<code> </code><code>log.e(</code><code>'externalstoragedirectory'</code><code>,msdpath.getabsolutefile() + file.separator + destdir);</code>
<code> </code><code>file mfile =</code><code>null</code><code>;</code>
<code> </code><code>if</code><code>(!mdestpath.exists()) {</code>
<code> </code><code>mdestpath.mkdirs();</code>
<code> </code><code>}</code>
<code> </code><code>mfile =</code><code>new</code> <code>file(mdestpath + file.separator + file);</code>
<code> </code><code>if</code><code>(!mfile.exists()) {</code>
<code> </code><code>try</code>
<code>{</code>
<code> </code><code>mfile.createnewfile();</code>
<code> </code><code>}</code><code>catch</code> <code>(ioexception e) {</code>
<code> </code><code>e.printstacktrace();</code>
<code> </code><code>}</code>
<code> </code><code>fileoutputstream moutputstream;</code>
<code> </code><code>moutputstream =</code><code>new</code> <code>fileoutputstream(mfile);</code>
<code> </code><code>moutputstream.write(szintext.getbytes());</code>
<code> </code><code>moutputstream.close();</code>
<code> </code><code>return</code>
<code> </code><code>}</code>
<code>false</code><code>;</code>
檢視sd卡中檔案的方法:
通過shell檢視,可以看到sd卡下所有目錄others都具有讀的權限
接下來檢視我們所建立的檔案,發現檔案others擁有讀的權限
由上面的分析我們可以得出如下的安全結論:
(1).存儲在sd卡中的資料是不安全的
sd卡中所建立的檔案預設對于others具有可讀的權限,這就意味着你存儲在sd卡上的一切内容是可以被其他應用所讀取的;此外,隻要app在其androidmenifest.xml檔案中聲明了寫sd卡的權限,那麼你存儲在sd卡上的資料也都可以被人修改。是以,一定不要在sd卡上存儲任何重要的資料,sd卡上的資料是不受linux預設保護機制保護的。
不要以為安全很遙遠,安全就在你的身邊,包括一些大廠商都發生過類似的安全事件,我們要引以為鑒,不讓類似的問題發生在我們的身上。
内部資料存儲安全事件:
網易android用戶端導緻賬号密碼洩露
傳送門:http://www.wooyun.org/bugs/wooyun-2010-010056
android手機明文存儲使用過的wifi密碼
外部資料存儲安全事件:
手機qq2012(android 3.0)導緻使用者聊天記錄洩露
傳送門:http://www.wooyun.org/bugs/wooyun-2010-012838
小米miui系統造成使用者大量敏感資料洩露
傳送門:http://www.wooyun.org/bugs/wooyun-2010-08187