見(jiàn)過(guò)一些系統(tǒng)和應(yīng)用在裸奔,也見(jiàn)過(guò)一些簡(jiǎn)單的應(yīng)用設(shè)計(jì)了極其復(fù)雜的安全機(jī)制,不僅團(tuán)隊(duì)成員很難掌握,而且還影響到業(yè)務(wù)開(kāi)發(fā)。所以我經(jīng)常會(huì)想,什么樣的網(wǎng)絡(luò)請(qǐng)求才是合理的?
- 一個(gè)APP或者網(wǎng)站,怎么區(qū)分當(dāng)前用戶是誰(shuí)呢?我可以在請(qǐng)求參數(shù)里附帶UserID,通過(guò)UserID我可以知道返回什么樣的數(shù)據(jù)或者展示什么樣的內(nèi)容。這時(shí)只要我在請(qǐng)求時(shí)修改一下UserID,就能看到其他用戶的信息了,別笑,這樣的系統(tǒng)確實(shí)存在,只在登錄時(shí)確認(rèn)了下UserID。

網(wǎng)絡(luò)請(qǐng)求時(shí)序圖 .png
- 當(dāng)然能犯這么低級(jí)錯(cuò)誤的比較是少數(shù),為了防止這種情況,有些系統(tǒng)每次請(qǐng)求都附帶了用戶名和密碼(加密后的也可以直接使用),這樣你不知道別人密碼 ,很難冒充別人請(qǐng)求了,但是這種設(shè)計(jì)依然很差勁,即使你的用戶名和密碼是加密的,每天這么傳來(lái)傳去也不合適,傳輸過(guò)程中隨便有人抓個(gè)包,拿到你的用戶名和密碼,就可以冒用你身份了,關(guān)鍵還要把用戶名這么重要的東西存儲(chǔ)的客戶端。

網(wǎng)絡(luò)請(qǐng)求時(shí)序圖.png
- 于是有人更進(jìn)一步,通過(guò)登錄請(qǐng)求返回一個(gè)token,這個(gè)token有一個(gè)有效期,這樣后面所有請(qǐng)求都通過(guò)傳遞token標(biāo)識(shí)用戶身份。雖然登錄請(qǐng)求時(shí)依然要傳遞用戶名密碼,但是大部分情況下只需要傳遞token還是安全很多的,畢竟可以有很多token失效策略用來(lái)提高安全性。當(dāng)然token可以像上面改UserID一樣被暴力試出來(lái),尤其是量級(jí)很大的應(yīng)用,所以UserID+token比單純token被試出概率低很多。目前很多應(yīng)用都是采用這種方式,雖說(shuō)可以被抓包,畢竟這個(gè)門檻還是很高的,當(dāng)然前提是你不要輕易連接未知WIFI。

網(wǎng)絡(luò)請(qǐng)求時(shí)序圖 (3).png
- 怎么可以不怕被抓包呢?有一個(gè)簡(jiǎn)單的方法就是給請(qǐng)求加一個(gè)驗(yàn)簽,簡(jiǎn)單說(shuō)就是每個(gè)請(qǐng)求都加一個(gè)簽名用來(lái)證明是你發(fā)出的請(qǐng)求,而不是惡意第三方。最常見(jiàn)的一個(gè)方法就是根據(jù)請(qǐng)求的參數(shù)生成一個(gè)簽名附帶到請(qǐng)求中,那么即使有人抓包拿到了你的請(qǐng)求,他也很難冒充你去發(fā)請(qǐng)求,因?yàn)樗恢篮灻刹呗?,而攔截到的簽名,通常也都跟時(shí)間戳相關(guān),所以也很難再繼續(xù)使用。例如下面的截圖,是嗶哩嗶哩APP的請(qǐng)求,如果你覺(jué)得現(xiàn)在你就可以自己直接發(fā)請(qǐng)求去拉他們數(shù)據(jù),那只能說(shuō)你圖樣圖森破,仔細(xì)看一下它的url:http://api.live.bilibili.com/AppNewIndex/common?_device=android&appkey=1d8b6e7d45233436&build=505000&mobi_app=android&platform=android&scale=xxhdpi&ts=1495789431&sign=cb2bd248088aee941a0a8f5d75fbb091 看到后面那個(gè)sign=xxxx了么?這個(gè)就是延簽,你不知道它的生成算法,你的所以請(qǐng)求它都不鳥(niǎo)你的。當(dāng)然也可以把所有數(shù)據(jù)都加密,抓包抓到的就是一堆亂碼。目前主流的網(wǎng)絡(luò)請(qǐng)求基本都是采用這種策略。攻擊者可以通過(guò)分析前端代碼或者分析反編譯后的客戶端代碼,獲取加密或者生成驗(yàn)簽的算法來(lái)破解這種安全方案。

image.png
- 還有一種方法,就是使用https,它能保證數(shù)據(jù)傳輸過(guò)程中實(shí)安全的。盡管有中間者攻擊,但是只要客戶端驗(yàn)證服務(wù)器證書(shū),就可以很容易識(shí)破攻擊者。瀏覽器默認(rèn)可以驗(yàn)證CA簽署的證書(shū)的,自簽名或者攻擊者的簽名,瀏覽器會(huì)有安全警告。手機(jī)APP的話需要自己實(shí)現(xiàn)證書(shū)驗(yàn)證步驟。各方面來(lái)講,https還是很安全的,目前各個(gè)大廠都在推https,如果說(shuō)缺點(diǎn)的話,那就是可以通過(guò)抓包工具分析請(qǐng)求,上面說(shuō)了可以防止中間者攻擊,但是用戶安裝中間者證書(shū)并且信任它那就沒(méi)辦法了,并且通常場(chǎng)景https都是單向驗(yàn)證,那么如果接口設(shè)計(jì)不合理,攻擊者就可以通過(guò)直接發(fā)送請(qǐng)求完成攻擊。

網(wǎng)絡(luò)請(qǐng)求時(shí)序圖 (6).png
- 根據(jù)上面分析,可以把5和4組合使用,達(dá)到類似于雙向驗(yàn)證的效果來(lái)提高安全性。那么這種方案唯一的攻擊入口就在于破解4中提到的加密算法。
- 前端代碼通過(guò)混淆實(shí)現(xiàn)算法保護(hù),android也是通過(guò)混淆對(duì)java代碼進(jìn)行保護(hù),不過(guò)它的反射機(jī)制暴露了每一個(gè)Activity,給破解者提供了一個(gè)很好的切入點(diǎn),所以為了提高安全性,很多Android開(kāi)發(fā)者都把一些核心算法的實(shí)現(xiàn)放到lib.so中實(shí)現(xiàn)。放lib.so中就很安全嗎?答案肯定是否定的,但是它把破解難度提高了很多,它是ELF文件格式,通過(guò)工具可以拿到匯編代碼,尤其android中native方法名不能混淆,也暴露了默認(rèn)C/C++實(shí)現(xiàn)的函數(shù)名。不少Android應(yīng)用僅僅通過(guò)lib.so獲取字符串方式隱藏加密密鑰或者特殊code,這種方式破解難度就更低了,找到特殊關(guān)鍵字直接從匯編代碼中搜索,更有甚者破解者直接寫(xiě)代碼調(diào)用你的lib.so獲取結(jié)果,可以看下面的截圖,是默認(rèn)JNI的例子生成的so反編譯后的結(jié)果。為了再次提高安全等級(jí),就出現(xiàn)了加殼技術(shù)。IOS程序就是加殼后的ELF文件,如上分析Android做了這么多工作才達(dá)到了IOS的安全程度,這也是為啥大家都說(shuō)IOS難破解,當(dāng)然加殼后也不是絕對(duì)安全,大家應(yīng)該經(jīng)常聽(tīng)到脫殼技術(shù)。梆梆和360都推出了針對(duì)Android的加固服務(wù),但是很快就被安全愛(ài)好者脫殼并公布方法(當(dāng)然它們肯定會(huì)推出新的加固方案),所以安全沒(méi)有絕對(duì)的,就看你要做到什么地步了。下一篇我會(huì)按照上述思路實(shí)現(xiàn)一套網(wǎng)絡(luò)數(shù)據(jù)安全方案。

image.png

image.png