前言
在開(kāi)始談技術(shù)干貨之前,先大概說(shuō)一下這次公司APP安全風(fēng)波的始末,甩鍋的理由有三,其一:創(chuàng)業(yè)公司凡事講究敏捷開(kāi)發(fā),快速迭代上線,因此在完成功能需求之余無(wú)暇他顧;其二:安全問(wèn)題應(yīng)該為技術(shù)總監(jiān)著重考慮的一點(diǎn),但是(按照慣例,這里省略N字,不可描述);其三:后臺(tái)接口定義也沒(méi)有考慮到這一點(diǎn),然而,從不要隨便甩鍋的好習(xí)慣來(lái)說(shuō),我還是要負(fù)起責(zé)任的,畢竟自己是iOS負(fù)責(zé)人,要對(duì)APP有個(gè)全面的把握.
簡(jiǎn)單的講下事情經(jīng)過(guò),就是突然有一天下午,一個(gè)用戶打電話給客服說(shuō)自己買(mǎi)了一張998元的機(jī)票買(mǎi)錯(cuò)了,想退票,要求公司給他取消訂單退錢(qián),然后還把支付寶的網(wǎng)頁(yè)支付記錄發(fā)了過(guò)來(lái)(后來(lái)證實(shí)是PS過(guò)的).然后財(cái)務(wù)部那邊查賬之后發(fā)現(xiàn)這個(gè)用戶的支付寶賬號(hào)確實(shí)付款了,但實(shí)際付款的只有1元,然后公司財(cái)務(wù)就把事情反饋給了副總,然后整個(gè)技術(shù)部就炸鍋了,都在各抒己見(jiàn)分析這個(gè)1元錢(qián)是怎么通過(guò)APP付款到公司賬戶的,因?yàn)闄C(jī)票訂單是沒(méi)有1元的.而且APP和支付寶給后臺(tái)的回調(diào)都是支付成功的.根據(jù)唯物主義思想來(lái)推斷,支付寶出錯(cuò)的概率遠(yuǎn)小于我們APP出錯(cuò)的概率,而且后臺(tái)也沒(méi)有被攻入的跡象,因此就把問(wèn)題鎖定在APP上了,然后我們用的POST請(qǐng)求(一些人說(shuō)比較安全,其實(shí)不加密的話,安全性和GET請(qǐng)求比起來(lái)相差無(wú)幾),我們部門(mén)的首席科學(xué)家直接說(shuō)APP肯定是被反編譯了,原話是"我找我阿里的朋友幫忙,分分鐘就把APP反編譯了,然后隨便下單."當(dāng)時(shí)聽(tīng)了這話我是懵逼的,雖然從技術(shù)可操作性來(lái)說(shuō),存在反編譯的可能,但是分分鐘不費(fèi)吹灰之力就反編譯這種說(shuō)法我是不太能接受的,然后就有了后邊我自己攻擊自己APP的舉動(dòng).
正題
我的分析就是反編譯太麻煩,不容易實(shí)施,而且即使反編譯出來(lái)了,一個(gè)類名一個(gè)方法名的去解析APP也很累,所以就從相對(duì)好實(shí)施的篡改網(wǎng)絡(luò)請(qǐng)求及返回?cái)?shù)據(jù)下手!之前看過(guò)唐巧大神的一篇關(guān)于Charles的使用講解,不過(guò)當(dāng)時(shí)是用來(lái)簡(jiǎn)單的抓別人的包,用點(diǎn)數(shù)據(jù)就放下了,現(xiàn)在就拿來(lái)實(shí)踐一下篡改數(shù)據(jù)這個(gè)功能,首先安裝好Charles,然后按部就班的把Charles設(shè)置為自己mac電腦的代理,

然后手機(jī)連自己電腦wifi,或者跟電腦連接同一個(gè)wifi都可以,然后設(shè)置手機(jī)的代理,讓你手機(jī)的網(wǎng)絡(luò)請(qǐng)求都經(jīng)過(guò)Charles,服務(wù)器里填寫(xiě)的是電腦的IP地址,


這樣就可以抓到APP跟服務(wù)器之間的網(wǎng)絡(luò)請(qǐng)求了.然后在查看請(qǐng)求之后去使用篡改功能,這里就演示一下篡改一個(gè)頁(yè)面的數(shù)據(jù)






因?yàn)殚_(kāi)發(fā)壓力比較大,所以要考慮性價(jià)比比較高的方案,這里就暫時(shí)舍棄了HTTPS,運(yùn)用了實(shí)施起來(lái)相對(duì)簡(jiǎn)單的MD5加密,這里有兩種情況,下載加密和上傳加密,比如說(shuō)剛才看到的訂單列表就屬于下載加密,要確保訂單列表數(shù)據(jù)一旦被篡改就不去使用,而點(diǎn)擊立即支付的下單動(dòng)作就是上傳加密,要確保傳給服務(wù)器的下單參數(shù)一旦被篡改就不去使用,MD5加密的原理就不在這里講了,因?yàn)槲抑暗奈恼翵SPatch里已經(jīng)講過(guò)了,主要說(shuō)一下具體的實(shí)施細(xì)節(jié)以及過(guò)程中遇到的小坑,首先是下載加密:

我用的網(wǎng)絡(luò)請(qǐng)求是自己封裝的AFN,然后這里設(shè)置一下直接字符串取值,不要轉(zhuǎn)成JSON:
manager.responseSerializer = [AFHTTPResponseSerializer serializer];取出HTTP Header里的驗(yàn)證字串:
NSDictionary *headerDic = [operation.response allHeaderFields];NSString *rsaValue = headerDic[@"rsaValue"];然后取值:
NSString *responseObjectStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];加密:
NSString *md5Str = [NSString stringWithFormat:@"%@%@", responseObjectStr, md5SaltValue];然后進(jìn)行比對(duì)校驗(yàn)
[[md5Str getMd5_32Bit] isEqualToString:headerDic[@"rsaValue"]]然后是上傳加密:

把所有參數(shù)轉(zhuǎn)換為String:
String *jsonString = [self.orderModel yy_modelToJSONString];加密:
NSString *md5Value = [[NSString stringWithFormat:@"%@%@",jsonString,md5SaltValue] getMd5_32Bit];設(shè)置請(qǐng)求頭:
[manager.requestSerializer setValue:md5Value forHTTPHeaderField:@"rsaValue"];到這里,這篇文章算是告一段落,后邊應(yīng)該會(huì)更新一系列安全相關(guān)的文章,不過(guò)需要一個(gè)我去學(xué)習(xí)然后理解然后實(shí)踐的過(guò)程~下一篇是動(dòng)手去反編譯自己APP開(kāi)始踩坑之旅.當(dāng)然都是我自己的淺顯青銅操作,歡迎同學(xué)們指點(diǎn)及大神們一笑而過(guò).