iOS开发如何避免安全隐患
<p id="toc_0">现在很多iOS的APP没有做任何的安全防范措施,导致存在很多安全隐患和事故,今天我们来聊聊iOS开发人员平时怎么做才更安全。</p><h2 id="toc_1">一、网络方面</h2>
<p>用抓包工具可以抓取手机通信接口的数据。以Charles为例,用Charles可以获取http的所有明文数据,配置好它的证书后就可以模拟中间人攻击,获取https加密前的明文数据。</p>
<h3 id="toc_2">1.1 中间人攻击</h3>
<p>先简要地说下什么是中间人攻击:</p>
<p>①客户端:“我是客户端,给我你的公钥” -> 服务端(被中间人截获)。</p>
<p>所以现在是:</p>
<p>客户端->中间人</p>
<p>②然后中间人把消息转给服务端,也就是:</p>
<p>中间人->服务端</p>
<p>③服务端把带有公钥的信息发送给客户端,但是被中间截获。所以是:</p>
<p>服务端-[服务端的公钥] ->中间人</p>
<p>④中间人把服务端的公钥替换成自己的公钥,发送给客户端,声称是服务端的公钥:</p>
<p>中间人-[中间人的公钥] ->客户端</p>
<p>⑤客户端用得到的公钥加密,实际是用中间人的公钥进行加密,所以中间人可以用自己的私钥解密,获取原始数据,然后再用服务端的公钥对原始数据(或者修改原始数据内容)加密后发送给服务端。</p>
<p>这样中间人就可以获取到双方的通信数据,并可以制造虚假数据。</p>
<h3 id="toc_3">1.2 如何防范中间人攻击?</h3>
<p>下面开始说如何防范:</p>
<h4 id="toc_4">1.2.1 SSL Pinning</h4>
<p>SSL Pinning的原理就是把服务端的公钥存到客户端中,客户端会校验服务端返回的证书是否和客户端保存的一致,这样就避免了中间人替换证书进行的攻击。</p>
<p>SSL Pinning的实现比较简单,只需要把CA证书放入项目中,通过Security framework实现NSURLSession上的SSL Pinning。如果用的是AFNetworking,代码更简单一点:</p>
<p><img src="http://college.creditease.cn/resources/upload/image/20180801/1533094257087038718.png"></p>
<p>这样通过Charles抓包就会报错。</p>
<p><img src="http://college.creditease.cn/resources/upload/image/20180801/1533094266625068937.png"></p>
<p>证书验证有可以只验证公钥(AFSSLPinningModePublicKey),也可以完全验证证书(AFSSLPinningModeCertificate)。</p>
<p>但是用SSL Pinning有个很严重的问题,就是如果证书有问题,只有发布新版本才能解决。如果新版本一直审核不通过,app的网络通信就全部挂掉了。</p>
<p>比如赛门铁克(Symantec)证书被google和iOS12不信任的问题。如果app内置了证书,就必须要重新发版。</p>
<h4 id="toc_5">1.2.2 接口内容进行加密</h4>
<p>很多的app接口只对请求的参数进行加密和各种验证,而接口返回过来的数据就是明文。如果不用SSL Pinning来防止中间人攻击,也可以把接口返回的数据也进行加密,这样抓包工具抓到包后也依然不能破解。</p>
<p>比如微信,微信中的接口用的是http协议,但是内容全部进行了加密。</p>
<p><img src="http://college.creditease.cn/resources/upload/image/20180801/1533094285919024988.png"></p>
<p>现在常用的是对称加密,加密效率比较快。如果app里有的数据特别重要,还是要用非对称加密,非对称加密更安全,但是效率会比较慢。</p>
<h2 id="toc_6">二、日志</h2>
<h3 id="toc_7">2.1 Swift日志</h3>
<p>Swift中打印日志的语法可以用print,也可以用NSLog。但是尽量别用NSLog,因为Swift中用NSLog,系统日志中是能查到的。可以通过pp助手、iTools或者Xcode的Devices and Simulators 来查看系统日志。</p>
<p>用print打印日志就不会出现在系统日志中。</p>
<h3 id="toc_8">2.2 OC日志</h3>
<p>在release环境下不要输出NSLog日志。一般大家都会用宏定义解决,如下:</p>
<p><img src="http://college.creditease.cn/resources/upload/image/20180801/1533094313744072855.png"></p>
<h2 id="toc_9">三、信息的存储</h2>
<h3 id="toc_10">3.1 密钥</h3>
<p>大部分的程序员喜欢直接把密钥放到宏或者常量里。</p>
<p>如:#define AES_KEY @“aaa123"</p>
<p>这样做很容易就可以被反编译出来。安全性比较差。可以用以下方法加强安全,增加破解的难度。</p>
<p><strong>对密钥(A)进行加密后定义为宏(B),使用的时候进行解密得到密钥(A)。其中对密钥A加密的密钥为C。</strong></p>
<p>因为在宏定义的时候我们如果定义成字符串,会直接存在data段,这样破解者很容易获取到。比较安全的做法是把C和B定义成uint8_t[]数组,这样每个字符就会放到text段的每个单独指令中。指令执行后生成字符串。这样就会很安全。</p>
<p><strong>用一段长文本,按规则提取出里面的密钥,密钥是随机的。</strong></p>
<p>在服务端和客户端定义一段长文本,app端随机生成起始位置和长度,把起始位置和长度进行移位等操作,生成相应的数字,对数字进行Base64编码,生成的字符串 传给服务端,服务端根据这个字符串 就能 解析出相关的密钥。</p>
<p>代码如下:</p>
<p><img src="http://college.creditease.cn/resources/upload/image/20180801/1533094370432083916.png"></p>
<p>这样只是增加了破解者获取密钥的难度,其实并不能完全阻止破解者获取。</p>
<h3 id="toc_11">3.2 Keychain</h3>
<p>越狱的iPhone可以查看导出Keychain保存的信息。Keychains的内容存放在sqlite中,目录为:/private/var/Keychains。可以通过keychain-dump可以查看钥匙串里存放的的内容。</p>
<p>所以保存到Keychain的数据一定要是加密之后的数据。<span class="Apple-converted-space"> </span></p>
<h3 id="toc_12">3.3 plist、sqlite</h3>
<p>plist、sqlite可以直接在ipa安装文件中获取到,所以不要在这些文件中存放重要信息,如果要保存,就进行加密后再存放。</p>
<h2 id="toc_13">四、app加固</h2>
<h3 id="toc_14">4.1 代码混淆</h3>
<p>代码混淆就是把易读的类名、方法名替换成不易读的名字。常用的方法有宏替换和脚本替换。</p>
<p>比如本来方法名为:- (void)loadNetData; 进行代码混淆后,用class-dump导出头文件后会显示成修改后的方法名:- (void)showxhevaluatess;</p>
<h3 id="toc_15">4.2 用C语言</h3>
<p>核心代码用C语言写,但是C语言的函数也可以被hook,比如用fishhook。开发人员可以用静态内联函数来防止hock,破解者就只能去理解代码的逻辑。</p>
<h3 id="toc_16">4.3 检测tweak</h3>
<p>可以检测 /Library/MobileSubstrate/DynamicLibraries 下的 plist 文件里是否包含自己app的bundle id。如果包含,可以进行限制app的功能、提示该手机不安全 等。</p>
<p>作者:何继昌</p>
<p>来源:宜信技术学院</p><br><br>
来源:https://www.cnblogs.com/yixinjishu/p/11132028.html
頁:
[1]