應(yīng)用開發(fā)最佳實(shí)踐

引言

轉(zhuǎn)自 Application developer best practies纽窟。部分內(nèi)容有編輯。

正文

該文檔包含應(yīng)用程序開發(fā)人員的最佳實(shí)踐蝉衣,以幫助你為Android用戶和設(shè)備開發(fā)和釋放安全的應(yīng)用程序舒憾。最佳實(shí)踐涵蓋四個(gè)方面:
1.系統(tǒng)安全:確保核心操作系統(tǒng)的安全性
2.應(yīng)用安全:確保應(yīng)用的安全性
3.網(wǎng)絡(luò)安全:確保網(wǎng)絡(luò)通信的安全
4.隱私:允許用戶控制數(shù)據(jù)的處理

系統(tǒng)安全

本節(jié)包含確保核心Android操作系統(tǒng)安全性的建議。

Biometric authentication

一定要小心謹(jǐn)慎地處理用于用戶認(rèn)證的生物認(rèn)證數(shù)據(jù)居灯。從Android 9.0開始祭务,應(yīng)用程序可以利用新的BiometricPrompt API。支持在Android 8.1和更早的設(shè)備上使用support library的方式集成使用怪嫌。Android 9.0 CDD中包含關(guān)于生物認(rèn)證的更詳細(xì)和明確的要求义锥。

后門

Android應(yīng)用程序不應(yīng)該有任何后門或方法繞過正常安全機(jī)制來訪問系統(tǒng)或數(shù)據(jù)。為了防止后門喇勋,有以下可以做的:
1.使用行業(yè)認(rèn)可的應(yīng)用程序漏洞掃描工具來掃描應(yīng)用程序所使用的所有第三方庫和組件缨该。您對(duì)應(yīng)用程序中所有第三方組件的行為負(fù)責(zé)。
2.上傳應(yīng)用程序到google play掃描川背,然后使用google play保護(hù)贰拿。您可以上傳應(yīng)用程序而不發(fā)布。

設(shè)備驅(qū)動(dòng)程序訪問

只有可信代碼才有直接訪問設(shè)備驅(qū)動(dòng)程序的權(quán)限熄云。
首選架構(gòu)是提供一個(gè)單用途守護(hù)進(jìn)程膨更,該守護(hù)進(jìn)程代理對(duì)驅(qū)動(dòng)程序的調(diào)用并限制驅(qū)動(dòng)程序?qū)υ撌刈o(hù)進(jìn)程的訪問。確保驅(qū)動(dòng)設(shè)備節(jié)點(diǎn)不是全局可讀的或可寫的缴允。CTS包括檢查暴露的驅(qū)動(dòng)程序?qū)嵗臏y(cè)試荚守。

應(yīng)用安全

本節(jié)包含確保應(yīng)用程序安全性的建議。

源碼審查

源代碼審查可以檢測(cè)廣泛的安全問題练般。Android大力鼓勵(lì)手動(dòng)和自動(dòng)源代碼審查矗漾。
1.在所有使用Android SDK的應(yīng)用程序代碼上運(yùn)行Android Link,并糾正所有被標(biāo)識(shí)的問題薄料。
2.應(yīng)該使用能夠檢測(cè)內(nèi)存管理問題(如buffer overflows和off-by-one errors)的自動(dòng)化工具分析native code敞贡。
3.Android系統(tǒng)支持許多LLVM消毒器,例如AddressSanitizer和UndefinedBehaviorSanitizer摄职,它們可用于內(nèi)存相關(guān)問題的運(yùn)行時(shí)分析誊役。所有消毒器都應(yīng)該打開,除非有明確的理由谷市。在Android中通過libFuzzer結(jié)合fuzzing蛔垢,可以發(fā)現(xiàn)需要進(jìn)一步調(diào)查的不尋常的邊緣情況。

應(yīng)用權(quán)限

因?yàn)锳ndroid應(yīng)用程序彼此之間隔離迫悠。應(yīng)用程序必須明確地共享資源和數(shù)據(jù)鹏漆,需要通過聲明基本類型未提供的額外功能所需的權(quán)限來實(shí)現(xiàn)這一點(diǎn),包括訪問諸如照相機(jī)之類的設(shè)備特性。

請(qǐng)求權(quán)限

您應(yīng)盡量減少應(yīng)用程序請(qǐng)求的權(quán)限數(shù)量甫男。減少對(duì)敏感權(quán)限的訪問降低了無意中濫用這些權(quán)限的風(fēng)險(xiǎn)且改,提高了用戶的使用率验烧,并使應(yīng)用程序不易受到攻擊板驳。一般來說,如果一個(gè)權(quán)限不是必須的碍拆,請(qǐng)不要請(qǐng)求它若治。如果有一個(gè)功能必須使用某個(gè)權(quán)限,否則應(yīng)用程序不能運(yùn)行感混,請(qǐng)使用清單文件中的元素聲明它端幼。嘗試以不需要任何權(quán)限的方式設(shè)計(jì)應(yīng)用程序。下面是一些例子:
1.為您的應(yīng)用程序創(chuàng)建一個(gè)GUID弧满,而不是請(qǐng)求訪問設(shè)備信息來創(chuàng)建唯一的標(biāo)識(shí)符婆跑。有關(guān)的詳細(xì)信息,請(qǐng)參閱Handling user data
2.使用getExternalFilesDir將數(shù)據(jù)存儲(chǔ)在內(nèi)部存儲(chǔ)器或應(yīng)用程序的專用外部存儲(chǔ)器中庭呜,而不是使用需要權(quán)限的外部存儲(chǔ)器
3.使用標(biāo)準(zhǔn)Intent來避免請(qǐng)求權(quán)限滑进。例如,使用ACTION_IMAGE_CAPTURE而不是持有camera的權(quán)限募谎,使用ACTION_CALL而不是持有phone的權(quán)限扶关。
除了請(qǐng)求權(quán)限之外,您的應(yīng)用程序還可以使用清單中的element來保護(hù)暴露給其他應(yīng)用程序并對(duì)安全性敏感的IPC数冬,例如ContentProvider节槐。一般來說,我們建議盡可能使用訪問控制而不是讓用戶確認(rèn)權(quán)限拐纱,因?yàn)闄?quán)限可能讓用戶感到困惑铜异。例如,考慮使用Android提供的特定選擇器對(duì)話框進(jìn)行單個(gè)元素訪問秸架,或者揍庄,如果需要更廣泛的訪問,單個(gè)開發(fā)人員提供的多個(gè)應(yīng)用程序之間的IPC通信權(quán)限上咕宿,可以考慮使用簽名保護(hù)級(jí)別币绩。
不要泄漏受權(quán)限保護(hù)的數(shù)據(jù)。當(dāng)應(yīng)用程序通過IPC暴露數(shù)據(jù)時(shí)府阀,這就會(huì)發(fā)生缆镣。因?yàn)槟膽?yīng)用程序具有訪問IPC的權(quán)限。應(yīng)用程序的IPC接口的客戶端可能沒有相同的數(shù)據(jù)訪問權(quán)限试浙。關(guān)于這個(gè)問題的頻率和潛在影響的更多細(xì)節(jié)出現(xiàn)在USENIX發(fā)表的研究論文《Permission Re-Delegation: Attacks and Defenses》中董瞻。

創(chuàng)建權(quán)限

盡量在滿足安全要求的同時(shí)定義盡可能少的權(quán)限。對(duì)于大多數(shù)應(yīng)用程序來說,創(chuàng)建新權(quán)限相對(duì)來說并不常見钠糊,因?yàn)橄到y(tǒng)定義的權(quán)限覆蓋了許多情況挟秤。在合適的情況下,使用現(xiàn)有權(quán)限執(zhí)行訪問檢查抄伍。如果必須創(chuàng)建新的權(quán)限艘刚,請(qǐng)考慮是否可以用簽名保護(hù)級(jí)別來完善簽名權(quán)限對(duì)用戶是透明的截珍,并且只允許由與執(zhí)行權(quán)限檢查的應(yīng)用程序相同簽名的應(yīng)用程序訪問攀甚。如果仍然需要新的權(quán)限,則使用標(biāo)簽在應(yīng)用程序清單中聲明岗喉。希望使用新權(quán)限的應(yīng)用程序可以通過在各自的清單文件中添加一個(gè)標(biāo)簽來引用它秋度。
如果你創(chuàng)建的是危險(xiǎn)權(quán)限,則需要考慮的復(fù)雜性有很多:1.權(quán)限必須有一個(gè)字符串钱床,該字符串簡潔地向用戶表達(dá)他們做出的安全決策荚斯。
2.權(quán)限字符串必須本地化到許多不同的語言。
3.應(yīng)用程序可能在未安裝權(quán)限的創(chuàng)建者時(shí)請(qǐng)求權(quán)限查牌。
所有這些都對(duì)作為開發(fā)人員的您提出了重大的非技術(shù)挑戰(zhàn)事期,同時(shí)這也使您的用戶感到困惑,這就是為什么我們不鼓勵(lì)使用危險(xiǎn)權(quán)限僧免。

數(shù)據(jù)存儲(chǔ)

Android上應(yīng)用程序最常見的安全問題是刑赶,您保存在設(shè)備上的數(shù)據(jù)是否可被其他應(yīng)用程序訪問。在設(shè)備上保存數(shù)據(jù)有三種基本方法:
1.Internal storage
2.External storage
3.Content providers

Internal storage

默認(rèn)情況下懂衩,在內(nèi)部存儲(chǔ)中創(chuàng)建的文件只能應(yīng)用程序自身訪問撞叨。Android實(shí)現(xiàn)了這種保護(hù),這對(duì)大多數(shù)應(yīng)用程序來說都是足夠的浊洞。
一般來說牵敷,避免IPC文件的MODE_WORLD_WRITEABLE或MODE_WORLD_READABLE模式,因?yàn)樗鼈儾惶峁┫拗茖?duì)特定應(yīng)用程序的數(shù)據(jù)訪問的能力法希,也不提供數(shù)據(jù)格式的任何控制枷餐。如果希望與其他應(yīng)用程序進(jìn)程共享數(shù)據(jù),可以考慮使用content provider苫亦,它為其他應(yīng)用程序提供讀寫權(quán)限毛肋,并且可以根據(jù)具體情況動(dòng)態(tài)授予權(quán)限。
為了對(duì)敏感數(shù)據(jù)提供額外的保護(hù)屋剑,可以使用應(yīng)用程序不能直接訪問的密鑰對(duì)本地文件進(jìn)行加密润匙。例如,可以將密鑰放在密鑰存儲(chǔ)庫中唉匾,并用未存儲(chǔ)在設(shè)備上的用戶密碼來保護(hù)密鑰孕讳。雖然這不能保護(hù)數(shù)據(jù)免遭可能監(jiān)視用戶輸入密碼的根本危害,但是它可以在沒有文件系統(tǒng)加密的情況下為丟失的設(shè)備提供保護(hù)。還可以使用StorageManager.isEncrypted()來確定文件路徑是否已經(jīng)被系統(tǒng)加密厂财,以避免雙重加密的性能開銷芋簿。

External storage

在外部存儲(chǔ)(例如SD卡)上創(chuàng)建的文件是全局可讀和可寫的。因?yàn)橥獠看鎯?chǔ)可以由用戶移除璃饱,也可以由任何應(yīng)用程序修改与斤,所以不要使用外部存儲(chǔ)來存儲(chǔ)敏感信息。

在處理來自外部存儲(chǔ)的數(shù)據(jù)時(shí)帜平,您應(yīng)該執(zhí)行輸入驗(yàn)證幽告,就像從任何不受信任的源中獲取數(shù)據(jù)一樣梅鹦。在動(dòng)態(tài)加載之前裆甩,不應(yīng)將可執(zhí)行文件或類文件存儲(chǔ)在外部存儲(chǔ)中。如果您的應(yīng)用程序確實(shí)從外部存儲(chǔ)中檢索可執(zhí)行文件齐唆,那么在動(dòng)態(tài)加載之前嗤栓,應(yīng)該對(duì)文件進(jìn)行簽名和加密驗(yàn)證。

Content providers

Content providers提供了一個(gè)結(jié)構(gòu)化的存儲(chǔ)機(jī)制箍邮,可以只限于您自己的應(yīng)用程序茉帅,也可以暴露出來以允許其他應(yīng)用程序訪問。如果不打算為其他應(yīng)用程序提供對(duì)ContentProvider的訪問锭弊,請(qǐng)?jiān)趹?yīng)用程序清單中將它們標(biāo)記為android:export=false堪澎。否則,將Android導(dǎo)出屬性設(shè)置為true味滞,以允許其他應(yīng)用程序訪問存儲(chǔ)的數(shù)據(jù)樱蛤。
創(chuàng)建供其他應(yīng)用程序使用的ContentProvider時(shí),可以指定單個(gè)讀寫權(quán)限剑鞍,也可以指定不同的讀寫權(quán)限昨凡。您應(yīng)該將權(quán)限限制在完成手頭任務(wù)所需的權(quán)限上。請(qǐng)記住蚁署,稍后添加權(quán)限以公開新功能通常比取消權(quán)限并影響現(xiàn)有用戶更容易便脊。
如果使用Content providers僅在自己的應(yīng)用程序之間共享數(shù)據(jù)光戈,則最好使用android:protectionLevel屬性設(shè)置簽名保護(hù)。簽名權(quán)限不需要用戶確認(rèn)乎莉,因此當(dāng)訪問數(shù)據(jù)的應(yīng)用程序使用相同的密鑰簽名時(shí),它們能提供更好的用戶體驗(yàn)和更加受控的對(duì)內(nèi)容提供商數(shù)據(jù)的訪問异希。
Content providers還可以通過聲明android:grantUriPermissions屬性并在激活組件的Intent對(duì)象中使用FLAG_GRANT_READ_URI_PERMIS.和FLAG_GRANT_WRITE_URI_PERMIS標(biāo)志來提供更細(xì)粒度的訪問。這些權(quán)限的范圍可以進(jìn)一步受標(biāo)簽限制憨降。
訪問Content providers時(shí),選擇參數(shù)始終過濾不可信輸入,以避免可能的SQL注入攻擊睹晒。在實(shí)現(xiàn)內(nèi)容提供程序時(shí),始終使用啟用了setStrict()的SQLITQueryBuilder構(gòu)造查詢键痛,以防止SQL注入攻擊。
不要對(duì)寫權(quán)限有錯(cuò)誤的安全感邑贴。寫權(quán)限允許SQL語句繁疤,這些語句允許使用創(chuàng)造性WHERE子句和解析結(jié)果來確認(rèn)某些數(shù)據(jù)。例如鸣哀,攻擊者可以通過僅在電話號(hào)碼已經(jīng)存在的情況下修改一行來探測(cè)呼叫日志中特定電話號(hào)碼的存在。如果Content provider數(shù)據(jù)具有可預(yù)測(cè)的結(jié)構(gòu)褥赊,則寫入權(quán)限可以等效于同時(shí)提供讀取和寫入。

輸入驗(yàn)證

輸入驗(yàn)證不足是影響應(yīng)用程序的最常見安全問題之一捶惜,無論它們運(yùn)行在什么平臺(tái)上。Android有平臺(tái)級(jí)別的對(duì)策吝岭,可以減少應(yīng)用程序?qū)斎腧?yàn)證問題的暴露,您應(yīng)該盡可能使用這些特性谋币。還要注意,類型安全語言的選擇往往會(huì)降低輸入驗(yàn)證問題的可能性症概。
如果使用native code蕾额,則從文件讀取、通過網(wǎng)絡(luò)接收或從IPC接收的任何數(shù)據(jù)都有可能引入安全問題彼城。最常見的問題是緩沖區(qū)溢出诅蝶、釋放后使用和off-by-one錯(cuò)誤。Android提供了許多技術(shù)募壕,如ASLR和DEP调炬,它們降低了這些錯(cuò)誤的可利用性,但是它們并不能解決根本問題舱馅。通過仔細(xì)處理指針和管理緩沖區(qū)缰泡,可以防止這些漏洞。
基于字符串的動(dòng)態(tài)語言代嗤,如JavaScript和SQL棘钞,由于轉(zhuǎn)義字符和腳本注入,也會(huì)遇到輸入驗(yàn)證問題干毅。
如果您正在使用的數(shù)據(jù)包含提交給SQL數(shù)據(jù)庫或內(nèi)容提供者的查詢宜猜,SQL注入可能是一個(gè)問題。最好的防御是使用參數(shù)化查詢硝逢,正如上面關(guān)于Content providers的討論中所討論的姨拥。將權(quán)限限制為只讀或只寫也可以減少與SQL注入有關(guān)的危害。
如果不能使用上述安全特性趴捅,則應(yīng)確保使用結(jié)構(gòu)良好的數(shù)據(jù)格式垫毙,并驗(yàn)證數(shù)據(jù)是否符合預(yù)期格式。雖然黑名單字符或字符替換可以是一個(gè)有效的策略拱绑,但這些技術(shù)在實(shí)踐中容易出錯(cuò)综芥,應(yīng)該盡可能避免。

動(dòng)態(tài)代碼加載

我們強(qiáng)烈反對(duì)從應(yīng)用程序APK外部加載代碼猎拨。這樣做顯著地增加了由于代碼注入或代碼篡改導(dǎo)致的APP妥協(xié)的可能性膀藐。它還增加了版本管理和應(yīng)用程序測(cè)試的復(fù)雜性屠阻。會(huì)使得無法驗(yàn)證應(yīng)用程序的行為,因此在某些環(huán)境中它可能被禁止额各。
如果您的應(yīng)用程序確實(shí)動(dòng)態(tài)加載代碼国觉,那么關(guān)于動(dòng)態(tài)加載的代碼,要記住的最重要的事情是它以與應(yīng)用程序APK相同的安全權(quán)限運(yùn)行虾啦。用戶根據(jù)您的身份決定安裝應(yīng)用程序麻诀,并且用戶希望您提供的任何代碼,包括動(dòng)態(tài)加載的代碼傲醉,在該應(yīng)用程序中運(yùn)行蝇闭。
與動(dòng)態(tài)加載代碼相關(guān)的主要安全風(fēng)險(xiǎn)是代碼需要來自可驗(yàn)證的源。如果模塊直接包含在您的APK中硬毕,則它們不能被其他應(yīng)用程序修改呻引。無論代碼是本地庫還是使用DexClassLoader加載的類,都是如此吐咳。許多應(yīng)用程序試圖從不安全的位置加載代碼逻悠,例如通過未加密協(xié)議從網(wǎng)絡(luò)下載,或者從外部存儲(chǔ)等可寫位置下載代碼韭脊。這些位置可以允許網(wǎng)絡(luò)上的人修改傳輸中的內(nèi)容童谒,或者允許用戶設(shè)備上的其他應(yīng)用程序修改設(shè)備上的內(nèi)容。

Native code

一般來說乾蓬,您應(yīng)該使用Android SDK進(jìn)行應(yīng)用程序開發(fā)惠啄,而不是使用Android NDK使用native code。使用本機(jī)代碼構(gòu)建的應(yīng)用程序更復(fù)雜任内、可移植性更差,并且更可能包含常見的內(nèi)存損壞錯(cuò)誤融柬,例如緩沖區(qū)溢出死嗦。
Android是使用Linux內(nèi)核構(gòu)建的,如果您使用native code粒氧,那么熟悉Linux開發(fā)安全最佳實(shí)踐尤其有用越除。Linux的安全實(shí)踐超出了本文的范圍,但是最受歡迎的資源之一是Secure Programming HOWTO - Creating Secure Software外盯。
Android和大多數(shù)Linux環(huán)境之間的一個(gè)重要區(qū)別是應(yīng)用沙盒摘盆。在Android上,所有應(yīng)用程序都運(yùn)行在應(yīng)用程序沙箱中饱苟,包括那些用native code編寫的應(yīng)用程序孩擂。從最基本的層面來看,對(duì)于熟悉Linux的開發(fā)人員來說箱熬,考慮它的一個(gè)好方法就是知道每個(gè)應(yīng)用程序都被賦予了具有非常有限的權(quán)限的惟一UID类垦。Android Security Overview對(duì)此進(jìn)行了更詳細(xì)的討論狈邑,您應(yīng)該熟悉應(yīng)用程序權(quán)限,即使您正在使用native code蚤认。

虛擬機(jī)

Dalvik是Android的運(yùn)行時(shí)虛擬機(jī)(VM)米苹。Dalvik是專門為Android構(gòu)建的,但是關(guān)于其他虛擬機(jī)中安全代碼的許多關(guān)系也適用于Android砰琢。一般來說蘸嘶,您不應(yīng)該擔(dān)心與虛擬機(jī)有關(guān)的安全問題。您的應(yīng)用程序運(yùn)行在安全沙箱環(huán)境中陪汽,因此系統(tǒng)上的其他進(jìn)程無法訪問您的代碼或私有數(shù)據(jù)训唱。
如果您對(duì)學(xué)習(xí)更多有關(guān)虛擬機(jī)安全性的知識(shí)感興趣,請(qǐng)熟悉一些關(guān)于這個(gè)主題的現(xiàn)有文獻(xiàn)掩缓。兩個(gè)比較受歡迎的資源是:
Securing Java
Related third-party projects
本文檔著聚焦于Android的特性或不同于其他VM環(huán)境的部分雪情。對(duì)于在其他環(huán)境中具有VM編程經(jīng)驗(yàn)的開發(fā)人員來說,在為Android編寫應(yīng)用程序時(shí)你辣,存在兩個(gè)大問題:
一些虛擬機(jī)巡通,例如JVM或.NET運(yùn)行時(shí),充當(dāng)安全邊界舍哄,將代碼與底層操作系統(tǒng)功能隔離宴凉。在Android上,Dalvik VM不是一個(gè)安全邊界——Application Sandbox是在OS級(jí)別實(shí)現(xiàn)的表悬,因此Dalvik可以在沒有任何安全約束的情況下與相同應(yīng)用程序中的native code進(jìn)行互操作弥锄。
由于移動(dòng)設(shè)備上的存儲(chǔ)空間有限,開發(fā)人員通常希望構(gòu)建模塊化應(yīng)用程序并使用動(dòng)態(tài)類加載蟆沫。這樣做時(shí)籽暇,要考慮在哪里檢索應(yīng)用程序邏輯以及在本地存儲(chǔ)它。不要使用來自未驗(yàn)證的源(例如不安全的網(wǎng)絡(luò)源或外部存儲(chǔ))的動(dòng)態(tài)類加載饭庞,因?yàn)樵摯a可能被加入惡意的行為戒悠。

應(yīng)用發(fā)布

Google play提供了在不執(zhí)行完整系統(tǒng)更新的情況下更新應(yīng)用程序的能力。這可以加快對(duì)安全問題的響應(yīng)和新特性的交付舟山,同時(shí)也確保應(yīng)用程序具有唯一包名的方法绸狐。
1.上傳你的應(yīng)用程序到Google play,以允許自動(dòng)更新累盗,而不需要一個(gè)完整的空中(OTA)更新寒矿。上載但未發(fā)布的應(yīng)用程序不能直接由用戶下載,但Google play上的應(yīng)用程序仍然被更新若债。先前安裝應(yīng)用程序的用戶可以重新安裝或安裝在其他設(shè)備上符相。
2.創(chuàng)建一個(gè)與你的公司有關(guān)聯(lián)的應(yīng)用程序包名稱,例如使用公司商標(biāo)拆座。

應(yīng)用簽名

App簽名在設(shè)備安全中起著重要的作用主巍,也用于權(quán)限檢查以及軟件更新冠息。在選擇用于簽署應(yīng)用程序的密鑰時(shí),考慮應(yīng)用程序是否只在單個(gè)設(shè)備上使用還是在多個(gè)設(shè)備上通用是很重要的孕索。
1.應(yīng)用程序不能用公開的密鑰簽署逛艰。
2.用于簽署應(yīng)用程序的密鑰應(yīng)當(dāng)以與處理敏感密鑰的行業(yè)標(biāo)準(zhǔn)實(shí)踐相一致的方式進(jìn)行管理,包括提供有限搞旭、可審計(jì)訪問的HSM护奈。
3.應(yīng)用程序不應(yīng)用平臺(tái)密鑰進(jìn)行簽名碎紊。否則會(huì)讓應(yīng)用程序擁有訪問平臺(tái)的簽名權(quán)限喘蟆,這些權(quán)限非常強(qiáng)大季惯,并且僅供操作系統(tǒng)的組件使用。如果你有比普通應(yīng)用程序更需要特權(quán)的應(yīng)用程序翎嫡,你可以把它們變成一個(gè)特權(quán)應(yīng)用程序欠动。請(qǐng)確保使用白名單鎖定特權(quán)應(yīng)用程序權(quán)限。
4.如果您用Google托管您的APK簽名密鑰惑申,并且您的上傳密鑰丟失或受損具伍,那么您可以與Google聯(lián)系以撤銷舊的上傳密鑰并生成新的密鑰。這只適用于Google play上的應(yīng)用程序圈驼。
5.同一個(gè)包名的應(yīng)用程序不應(yīng)該用不同的密鑰簽名人芽。這經(jīng)常發(fā)生在為不同設(shè)備創(chuàng)建應(yīng)用程序時(shí),尤其是在使用平臺(tái)密鑰時(shí)绩脆。如果應(yīng)用程序是獨(dú)立于設(shè)備的萤厅,則在設(shè)備上使用相同的密鑰。如果應(yīng)用程序是特定于設(shè)備的靴迫,則在每個(gè)設(shè)備和密鑰上創(chuàng)建唯一的包名惕味。

網(wǎng)絡(luò)安全

本節(jié)包含確保網(wǎng)絡(luò)通信安全的建議。

網(wǎng)絡(luò)

網(wǎng)絡(luò)事務(wù)本質(zhì)上存在安全風(fēng)險(xiǎn)玉锌,因?yàn)樗鼈兩婕跋蛴脩魝鬏斂赡芩接械臄?shù)據(jù)赦拘。所有到目的地的網(wǎng)絡(luò)連接都應(yīng)該被正確地加密,以防止在途中竊聽和修改芬沉,無論連接的內(nèi)容如何,這都是真理阁猜。詳情請(qǐng)參閱我們的開發(fā)者峰會(huì)丸逸。

IP網(wǎng)絡(luò)

Android上的網(wǎng)絡(luò)與其他Linux環(huán)境沒有明顯不同。關(guān)鍵的考慮是確保使用適當(dāng)?shù)膮f(xié)議剃袍,例如用于安全通信的HttpsURLConnection 黄刚。考慮到Android設(shè)備與潛在的惡意無線網(wǎng)絡(luò)(例如不安全的Wi-Fi網(wǎng)絡(luò))連接的頻率民效,強(qiáng)烈鼓勵(lì)所有通過網(wǎng)絡(luò)進(jìn)行通信的應(yīng)用程序使用安全網(wǎng)絡(luò)憔维。至于Android P涛救,默認(rèn)情況下,嘗試使用未加密的連接將導(dǎo)致IOException业扒。
可以使用SSLSocket類實(shí)現(xiàn)經(jīng)過身份驗(yàn)證的检吆、加密的套接字級(jí)通信,但是正確驗(yàn)證服務(wù)器證書的主機(jī)名與目的地匹配是至關(guān)重要的程储,因?yàn)镾SLSocket在默認(rèn)情況下不這樣做蹭沛,這可以使用HttpsUrlConnection.getDefaultHostnameVerifier的標(biāo)準(zhǔn)HostnameVerifier來完成。
有些應(yīng)用程序使用本地主機(jī)網(wǎng)絡(luò)端口來處理敏感的IPC章鲤,這是不安全的摊灭,不能使用。這是因?yàn)檫@些接口可以由設(shè)備上的其他應(yīng)用程序訪問败徊。相反帚呼,使用Android IPC機(jī)制,在那里可以進(jìn)行身份驗(yàn)證皱蹦,例如使用服務(wù)煤杀。綁定到INADDR_ANY比使用回環(huán)更糟糕,因?yàn)槟膽?yīng)用程序可以從任何地方接收請(qǐng)求根欧。
不要盲目信任來自遠(yuǎn)程源的數(shù)據(jù)怜珍,特別是如果數(shù)據(jù)是通過HTTP或其他不安全協(xié)議傳遞的。這還包括在WebView中驗(yàn)證輸入凤粗。

電話網(wǎng)絡(luò)

SMS協(xié)議主要是為用戶通信設(shè)計(jì)的酥泛,并不適合希望傳輸數(shù)據(jù)的應(yīng)用程序。由于SMS的限制嫌拣,您應(yīng)該使用Firebase Cloud Messaging (FCM)和IP網(wǎng)絡(luò)將數(shù)據(jù)消息從Web服務(wù)器發(fā)送到用戶設(shè)備上的應(yīng)用程序柔袁。
當(dāng)心SMS既不加密也不在網(wǎng)絡(luò)或設(shè)備上進(jìn)行強(qiáng)認(rèn)證。特別是异逐,任何SMS接收器都應(yīng)該預(yù)期惡意用戶可能已經(jīng)將SMS發(fā)送到您的應(yīng)用程序捶索。不要依賴未經(jīng)認(rèn)證的SMS數(shù)據(jù)來執(zhí)行敏感命令或向設(shè)備傳送敏感數(shù)據(jù)。此外灰瞻,您應(yīng)該知道腥例,SMS可能會(huì)受到網(wǎng)絡(luò)上的欺騙和/或攔截。在Android驅(qū)動(dòng)的設(shè)備本身上酝润,SMS消息作為廣播意圖傳輸燎竖,因此它們可以被具有READ_SMS權(quán)限的其他應(yīng)用程序讀取或捕獲。

進(jìn)程間通信

一些應(yīng)用程序試圖使用傳統(tǒng)的Linux技術(shù)(如網(wǎng)絡(luò)套接字和共享文件)來實(shí)現(xiàn)IPC要销。但是构回,您應(yīng)該使用Android系統(tǒng)功能來IPC,比如Intent、Binder或Messenger with Service纤掸,以及BroadcastReceiver脐供。Android IPC機(jī)制允許您驗(yàn)證連接到IPC的應(yīng)用程序的身份,并為每個(gè)IPC機(jī)制設(shè)置安全策略借跪。
許多安全元素在IPC機(jī)制之間共享政己。如果IPC機(jī)制不打算供其他應(yīng)用程序使用,則在組件的manifest元素中將android:export屬性設(shè)置為false垦梆。這對(duì)于在同一UID中由多個(gè)進(jìn)程組成的應(yīng)用程序非常有用匹颤,或者如果您在開發(fā)后期決定不將功能公開為IPC,但是您不想重寫代碼托猩。
如果您的IPC對(duì)于其他應(yīng)用程序是可訪問的印蓖,您可以通過使用該元素來應(yīng)用安全策略。如果IPC是在您自己的使用相同密鑰簽名的獨(dú)立應(yīng)用程序之間京腥,那么最好在android:protectionLevel中使用簽名級(jí)別權(quán)限赦肃。

使用intents

對(duì)于activities和broadcast receivers,intents是Android中異步IPC的首選機(jī)制公浪。根據(jù)您的應(yīng)用程序需求他宛,您可以使用sendBroadcast()、sendOrderedBroadcast()或明確intents發(fā)送給特定應(yīng)用程序組件欠气。出于安全目的厅各,首選的是明確的intent。
注意:如果使用intent綁定到服務(wù)预柒,請(qǐng)確保使用明確的intent的應(yīng)用程序是安全的队塘。使用隱式intents啟動(dòng)服務(wù)是一種安全隱患,因?yàn)槟荒艽_定什么服務(wù)將響應(yīng)該意圖宜鸯,并且用戶無法看到哪個(gè)服務(wù)啟動(dòng)憔古。從Android 5.0開始(API級(jí)別21),如果你用一個(gè)隱式的intent調(diào)用bdIdService()淋袖,系統(tǒng)會(huì)拋出一個(gè)異常鸿市。
請(qǐng)注意,有序廣播可以由接收者使用即碗,因此它們可能不會(huì)被傳遞到所有應(yīng)用程序焰情。如果發(fā)送的intent必須傳遞給特定的接收方,則必須使用通過名稱聲明接收方的顯式intent剥懒。
intent的發(fā)送者可以通過使用方法調(diào)用指定非空權(quán)限來驗(yàn)證收件人是否具有權(quán)限烙样。只有具有該權(quán)限的應(yīng)用程序才接收到該intent。如果廣播意圖內(nèi)的數(shù)據(jù)可能是敏感的蕊肥,則應(yīng)考慮應(yīng)用權(quán)限以確保惡意應(yīng)用程序在沒有適當(dāng)權(quán)限的情況下不能注冊(cè)以接收這些消息。在這種情況下,您也可以考慮直接調(diào)用接收方壁却,而不是發(fā)送廣播批狱。
intent過濾器不應(yīng)被認(rèn)為是安全特性。組件可以用顯式intent調(diào)用展东,并且可能沒有符合intent過濾器的數(shù)據(jù)赔硫。為了確認(rèn)它為被調(diào)用的接收機(jī)、服務(wù)或活動(dòng)進(jìn)行了適當(dāng)?shù)母袷交嗡啵?qǐng)?jiān)趇ntent接收機(jī)內(nèi)執(zhí)行輸入驗(yàn)證爪膊。

使用services

服務(wù)通常用于提供其他應(yīng)用程序使用的功能。每個(gè)服務(wù)類必須在其清單文件中有一個(gè)相應(yīng)的聲明砸王。
默認(rèn)情況下推盛,服務(wù)不會(huì)暴露,不能被任何其他應(yīng)用程序調(diào)用谦铃。但是耘成,如果向服務(wù)聲明添加任何intent篩選器,則默認(rèn)情況下暴露驹闰。最好是顯式聲明android:exported屬性瘪菌,以確保它的行為符合你的意愿。服務(wù)也可以使用android:permission屬性來保護(hù)嘹朗。通過這樣做师妙,其他應(yīng)用程序需要在自己的清單中聲明相應(yīng)的元素,以便能夠啟動(dòng)屹培、停止或綁定到服務(wù)默穴。
提示:如果應(yīng)用程序針對(duì)Android 5.0(API級(jí)別21)或更高版本,則應(yīng)該使用JobScheduler來執(zhí)行后臺(tái)服務(wù)惫谤。有關(guān)JobScheduler的更多信息壁顶,請(qǐng)參見其API參考文檔。
服務(wù)可以通過在執(zhí)行調(diào)用實(shí)現(xiàn)之前調(diào)用checkCallingPermission()來保護(hù)具有權(quán)限的單個(gè)IPC調(diào)用溜歪。您應(yīng)該使用清單中聲明的權(quán)限若专,因?yàn)槟切┎惶菀妆皇韬觥?br>注意:不要混淆客戶端和服務(wù)器權(quán)限;確保被調(diào)用的應(yīng)用程序具有適當(dāng)?shù)臋?quán)限蝴猪,并驗(yàn)證是否向調(diào)用的應(yīng)用程序授予了相同的權(quán)限调衰。

使用binder和messenger接口

使用binder或Messenger是Android中 RPC-style IPC的首選機(jī)制。它們提供了一個(gè)定義良好的接口自阱,如果需要的話嚎莉,可以實(shí)現(xiàn)端點(diǎn)的相互認(rèn)證。
您應(yīng)該以不需要特定于接口的權(quán)限檢查的方式設(shè)計(jì)應(yīng)用程序接口沛豌。 Binder and Messenger沒有在應(yīng)用程序清單中聲明趋箩,因此您不能直接向它們應(yīng)用聲明性權(quán)限赃额。它們通常繼承實(shí)現(xiàn)它們的Service或Activity的應(yīng)用程序清單中聲明的權(quán)限。如果正在創(chuàng)建需要身份驗(yàn)證或訪問控制的接口叫确,則必須顯式地將這些控件作為代碼添加到Binder或Messenger接口中跳芳。
如果提供的接口確實(shí)需要訪問控制,則使用checkCallingPermission()來驗(yàn)證調(diào)用方是否具有所需的權(quán)限竹勉。在代表調(diào)用者訪問服務(wù)之前飞盆,這一點(diǎn)特別重要,因?yàn)閼?yīng)用程序的標(biāo)識(shí)被傳遞到其他接口次乓。如果正在調(diào)用服務(wù)提供的接口吓歇,當(dāng)沒有權(quán)限訪問給定服務(wù)時(shí),則bindService()調(diào)用可能會(huì)失敗票腰。如果調(diào)用您自己的應(yīng)用程序在本地提供的接口城看,那么使用clearCallingIdentity()方法滿足內(nèi)部安全檢查可能是有用的,該方法將調(diào)用者權(quán)限屏蔽為應(yīng)用程序的權(quán)限丧慈。您可以通過使用RealCeCalpIdItId()方法來恢復(fù)調(diào)用方權(quán)限析命。
有關(guān)使用服務(wù)執(zhí)行IPC的更多信息,請(qǐng)參見綁定服務(wù)逃默。

使用廣播接收器

廣播接收器處理intent發(fā)起的異步請(qǐng)求鹃愤。
默認(rèn)情況下,接收器被暴露并可以被任何其他應(yīng)用程序調(diào)用完域。如果BroadcastReceiver打算供其他應(yīng)用程序使用软吐,你需要在應(yīng)用清單中聲明安全權(quán)限。這阻止了沒有適當(dāng)權(quán)限的應(yīng)用程序向廣播接收器發(fā)送意圖吟税。

安全監(jiān)聽套接字

監(jiān)聽套接字應(yīng)該謹(jǐn)慎使用凹耙,并且通常不應(yīng)該有任何開放式監(jiān)聽套接字被Android應(yīng)用程序暴露。
在沒有空中(OTA)更新的情況下肠仪,監(jiān)聽套接字必須能夠被禁用肖抱。這可以使用服務(wù)器或用戶設(shè)備配置更改來執(zhí)行。
對(duì)于使用套接字的本地IPC异旧,應(yīng)用程序必須使用UNIX域套接字意述,其訪問權(quán)限僅限于組。為IPC創(chuàng)建文件描述符吮蛹,并為特定UNIX組生成+RW荤崇。任何客戶端應(yīng)用程序必須在UNIX組內(nèi)。
具有多個(gè)處理器(例如潮针,與應(yīng)用程序處理器分離的無線電/調(diào)制解調(diào)器)的一些設(shè)備使用網(wǎng)絡(luò)套接字在處理器之間進(jìn)行通信术荤。在這種情況下,用于處理器間通信的網(wǎng)絡(luò)套接字必須使用隔離的網(wǎng)絡(luò)接口來防止設(shè)備上的未經(jīng)授權(quán)的應(yīng)用程序訪問(即每篷,使用iptables來防止設(shè)備上的其他應(yīng)用程序訪問)瓣戚。
處理偵聽端口的守護(hù)進(jìn)程必須對(duì)錯(cuò)誤的數(shù)據(jù)保持健壯性端圈。谷歌可以使用未經(jīng)授權(quán)的客戶端對(duì)端口進(jìn)行模糊測(cè)試,并且在可能的情況下带兜,授權(quán)客戶端枫笛。任何崩潰都將被歸類為錯(cuò)誤的嚴(yán)重程度。
CTS包括檢查是否存在打開監(jiān)聽端口的測(cè)試刚照。

WebView

因?yàn)閃ebView使用包括HTML和JavaScript的web內(nèi)容,所以不恰當(dāng)?shù)氖褂每赡軙?huì)引入常見的web安全問題喧兄,比如跨站點(diǎn)腳本(JavaScript注入)无畔。Android包括許多機(jī)制,通過將WebView的能力限制到應(yīng)用程序所需的最小功能來減少這些潛在問題的范圍吠冤。
如果您的應(yīng)用程序在WebVIEW中不直接使用JavaScript浑彰,請(qǐng)不要調(diào)用StjJavaSpRIPabDebug()。一些示例代碼使用此方法拯辙,您可能會(huì)在生產(chǎn)應(yīng)用程序中重新使用它郭变,因此如果不需要,請(qǐng)刪除該方法調(diào)用涯保。默認(rèn)情況下诉濒,WebView不執(zhí)行JavaScript,因此跨站點(diǎn)腳本是不可能的夕春。
特別小心使用addJavaScriptInterface()未荒,因?yàn)樗试SJavaScript調(diào)用通常為Android應(yīng)用程序保留的操作。如果使用它及志,只將AdjJavaScript接口()公開到所有輸入都值得信任的網(wǎng)頁片排。如果允許不受信任的輸入,不可信的JavaScript可以在應(yīng)用程序中調(diào)用Android方法速侈。一般來說率寡,我們建議將AdjJavaScript接口()僅暴露在應(yīng)用程序APK內(nèi)的JavaScript中。
如果應(yīng)用程序使用WebView訪問敏感數(shù)據(jù)倚搬,則可能希望使用clearCache()方法刪除本地存儲(chǔ)的任何文件冶共。還可以使用服務(wù)器端頭(如無緩存)來指示應(yīng)用程序不應(yīng)該緩存特定的內(nèi)容。
為了確保您的應(yīng)用程序沒有暴露SSL中的潛在漏洞潭枣,請(qǐng)使用可更新的安全提供程序?qū)ο蟊饶绺履陌踩峁┏绦蛞苑乐筍SL漏洞。

憑證處理

為了使釣魚攻擊更加明顯盆犁,并且不太可能成功命咐,請(qǐng)最小化請(qǐng)求用戶憑證的頻率相反谐岁,使用授權(quán)令牌并刷新它醋奠。
在可能的情況下榛臼,不要在設(shè)備上存儲(chǔ)用戶名和密碼。相反窜司,使用用戶提供的用戶名和密碼執(zhí)行初始身份驗(yàn)證沛善,然后使用短期的、特定于服務(wù)的授權(quán)令牌塞祈。
可以使用Access管理器訪問多個(gè)應(yīng)用程序可訪問的服務(wù)金刁。如果可能的話,使用ActualMe管管理類調(diào)用基于云的服務(wù)议薪,不要在設(shè)備上存儲(chǔ)密碼尤蛮。
在使用AccountManager檢索帳戶之后,在傳遞任何憑據(jù)之前使用CREATOR斯议,這樣就不會(huì)無意中將憑據(jù)傳遞給錯(cuò)誤的應(yīng)用程序产捞。
如果憑證僅由您創(chuàng)建的應(yīng)用程序使用,則可以使用checkSignature()驗(yàn)證訪問AccountManager的應(yīng)用程序哼御∨髁伲或者,如果只有一個(gè)應(yīng)用程序使用憑據(jù)恋昼,則可以使用密鑰庫進(jìn)行存儲(chǔ)看靠。

隱私

本節(jié)包含確保Android用戶對(duì)數(shù)據(jù)的處理有控制權(quán)的建議

處理用戶數(shù)據(jù)

通常,用戶數(shù)據(jù)安全的最佳方法是最小化日志記錄和訪問敏感或個(gè)人用戶數(shù)據(jù)的API的使用焰雕。如果您可以訪問用戶數(shù)據(jù)衷笋,并且可以避免存儲(chǔ)或傳輸,則不要存儲(chǔ)或傳輸數(shù)據(jù)矩屁”僮冢考慮使用散列或其他不可逆形式的數(shù)據(jù)來實(shí)現(xiàn)邏輯。例如吝秕,您的應(yīng)用程序可能使用電子郵件地址的不可逆散列作為主鍵泊脐,以避免發(fā)送或存儲(chǔ)電子郵件地址。這減少了無意中暴露數(shù)據(jù)的機(jī)會(huì)烁峭,也減少了攻擊者試圖利用您的應(yīng)用程序的機(jī)會(huì)容客。

如果您的應(yīng)用程序訪問個(gè)人信息,如密碼或用戶名约郁,請(qǐng)記住缩挑,一些司法管轄區(qū)可能要求您提供隱私政策,解釋您使用和存儲(chǔ)這些數(shù)據(jù)鬓梅。遵循安全性的最佳做法供置,最大限度地減少對(duì)用戶數(shù)據(jù)的訪問也可以簡化依從性。

您還應(yīng)該考慮您的應(yīng)用程序是否可能無意中將個(gè)人信息暴露給其他方绽快,例如用于廣告的第三方組件或應(yīng)用程序使用的第三方服務(wù)芥丧。如果你不知道為什么一個(gè)組件或服務(wù)需要個(gè)人信息紧阔,不要提供它。一般來說续担,減少應(yīng)用程序?qū)€(gè)人信息的訪問減少了該領(lǐng)域的潛在問題擅耽。

如果應(yīng)用程序需要訪問敏感數(shù)據(jù),請(qǐng)?jiān)u估是否需要將其發(fā)送到服務(wù)器或是否可以在客戶端上運(yùn)行該操作物遇。只要可能乖仇,使用客戶端上的敏感數(shù)據(jù)運(yùn)行任何代碼,以避免發(fā)送用戶數(shù)據(jù)询兴。此外这敬,請(qǐng)確保您不會(huì)無意中通過過度許可的IPC、可寫文件或網(wǎng)絡(luò)套接字將用戶數(shù)據(jù)暴露到設(shè)備上的其他應(yīng)用程序蕉朵。過度許可的IPC是泄漏許可保護(hù)數(shù)據(jù)的特殊情況,在請(qǐng)求權(quán)限部分中討論阳掐。

如果需要一個(gè)GUID始衅,則創(chuàng)建一個(gè)大的、唯一的數(shù)字并存儲(chǔ)它缭保。不要使用電話標(biāo)識(shí)符汛闸,如電話號(hào)碼或IMEI,這是個(gè)人可識(shí)別的艺骂。本主題將在Android開發(fā)者博客中詳細(xì)討論诸老。

在寫入設(shè)備日志時(shí)要小心。在Android中钳恕,日志是一個(gè)共享資源别伏,擁有READ_LOGS權(quán)限的應(yīng)用程序可以訪問它。盡管電話日志數(shù)據(jù)是臨時(shí)的忧额,并且在重新啟動(dòng)時(shí)擦除厘肮,但是用戶信息的不當(dāng)日志記錄可能無意中將用戶數(shù)據(jù)泄露給其他應(yīng)用程序。除了不記錄PII睦番,生產(chǎn)應(yīng)用程序應(yīng)該限制日志使用类茂。為了方便地實(shí)現(xiàn)這一點(diǎn),使用調(diào)試標(biāo)志和自定義日志類具有易于配置的日志記錄級(jí)別托嚣。

Logging數(shù)據(jù)

Logging數(shù)據(jù)增加了暴露該數(shù)據(jù)的風(fēng)險(xiǎn)巩检,并降低了系統(tǒng)性能。由于敏感用戶數(shù)據(jù)的記錄示启,發(fā)生了多起公共安全事件兢哭。
應(yīng)用程序不應(yīng)記錄可能包含敏感信息的第三方應(yīng)用程序提供的數(shù)據(jù)。
除非絕對(duì)需要提供應(yīng)用程序的核心功能丑搔,否則應(yīng)用程序不能將任何個(gè)人可識(shí)別信息(PII)作為正常操作的一部分進(jìn)行日志記錄厦瓢。
CTS包括檢查日志中是否存在潛在敏感信息的測(cè)試提揍。

Metrics收集

確保Android應(yīng)用程序中任何度量集合的最佳實(shí)踐是很重要的,包括:
確保未經(jīng)明確煮仇、知情和有意義的用戶同意劳跃,不收集和報(bào)告Metrics標(biāo)準(zhǔn)。
除了少數(shù)例外浙垫,僅收集支持服務(wù)可靠性所必需的Metrics刨仑。
避免盡可能收集可識(shí)別或潛在敏感的數(shù)據(jù),如硬件標(biāo)識(shí)符夹姥。
盡可能確保數(shù)據(jù)足夠的聚集和匿名杉武。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辙售,隨后出現(xiàn)的幾起案子轻抱,更是在濱河造成了極大的恐慌,老刑警劉巖旦部,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祈搜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡士八,警方通過查閱死者的電腦和手機(jī)容燕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婚度,“玉大人蘸秘,你說我怎么就攤上這事』茸拢” “怎么了醋虏?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長评甜。 經(jīng)常有香客問我灰粮,道長,這世上最難降的妖魔是什么忍坷? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任粘舟,我火速辦了婚禮,結(jié)果婚禮上佩研,老公的妹妹穿的比我還像新娘柑肴。我一直安慰自己,他們只是感情好旬薯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布晰骑。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硕舆。 梳的紋絲不亂的頭發(fā)上秽荞,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音抚官,去河邊找鬼扬跋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凌节,可吹牛的內(nèi)容都是我干的钦听。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼倍奢,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼朴上!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起卒煞,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤痪宰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后畔裕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酵镜,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年柴钻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垢粮。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贴届,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜡吧,到底是詐尸還是另有隱情毫蚓,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布昔善,位于F島的核電站元潘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏君仆。R本人自食惡果不足惜翩概,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望返咱。 院中可真熱鬧钥庇,春花似錦、人聲如沸咖摹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萤晴。三九已至吐句,卻和暖如春胁后,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗦枢。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工攀芯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人净宵。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓敲才,卻偏偏與公主長得像,于是被迫代替她去往敵國和親择葡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子紧武,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評(píng)論 25 707
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料敏储? 從這篇文章中你...
    hw1212閱讀 12,693評(píng)論 2 59
  • (李克富老師點(diǎn)評(píng)訓(xùn)練營25/90) 李克富||學(xué)生是心理老師的掘墓人而非跪拜者 - 簡書 李克富||吾愛吾師阻星,吾更...
    人生心經(jīng)閱讀 559評(píng)論 0 1
  • 為何選擇 Flux 設(shè)計(jì)上遇到的問題 最初在接觸 Flux 時(shí)就有一種驚艷的感覺,長久以來在設(shè)計(jì)上所出現(xiàn)的困擾似乎...
    _WZ_閱讀 7,940評(píng)論 2 9
  • 感恩媽媽一早就過來帶光寶并辛苦的做家務(wù)已添,感恩妥箕,感恩老婆光寶的快樂成長,感恩早起運(yùn)用種子法則更舞,感恩覺察內(nèi)心的感受使我...
    2月31日閱讀 187評(píng)論 0 4