版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.08.17 |
前言
在这个信息爆炸的年代,特别是一些敏感的行业,比如金融业和银行卡相关等等,这都对
app
的安全机制有更高的需求,很多大公司都有安全 部门,用于检测自己产品的安全性,但是及时是这样,安全问题仍然被不断曝出,接下来几篇我们主要说一下app
的安全机制。
APP安全涉及方面
刚接触app安全大家可能会有一些疑问,app安全到底涉及到哪些方面,或者说app安全应该注意什么?
app安全主要应该注意下面几个方面:
ipa文件安全
我们在appleStore
下载的加壳后的ipa
文件,里面会有很多的资源包,不要在.plist
文件、项目中的静态文件中存储关键的信息,如要保存,需要加密处理。可以利用MAC上的PP软件助手,将ipa文件拷贝到电脑,直接就能获取ios的系统目录。如下图所示。
ipa文件的反编译工具IDA
前面已经说过了,从appleStore下载的都是加壳的ipa文件,想要去壳,可以使用clutch
、dumpdecrypted
、使用gdb
调试 等解密去壳工具,如果手机是越狱的,则可以从PP助手上下载ipa包,直接就是脱壳后的,还有就是xcode打包的ipa也是没有壳的。
建立新的项目加几句代码:
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 70, 200, 100)];
label.text = @"CeShiLabel007";
label.backgroundColor = [UIColor redColor];
[self.view addSubview:label];
}
接着就是将项目打包,获取的ipa文件解压后得到.app文件。
下面就下载好IDA,并安装打开如下所示。
利用IDA破解ipa文件,可以获取下面的图示。
由上面可见,字符串完全可以反编译出来。所以尽量不要在代码里放一些 关键的数据,可以通过接口来获取。或者把数据进行加密。
Hopper Disassembler反编译工具
具体方法还和IDA类似,就是下载软件和进行反编译,下面引用一个技术大牛反编译微信的图,如下所示。
这里可以很清楚的看到QQContactInfoViewController
里面的代码是如何写的。上面两种涉及到的都是代码的反编译,其实就是逆向工程。
沙盒安全
app的沙盒也是需要注意的地方,里面的文件比如sqlite、plist等等,不要保存敏感和关键信息,如要保存,同样需要加密。 这里需要注意:
-
.app
文件里面存放的使用程序本身的数据,打包时候的资源文件都在里面,这个目录不会被iTunes同步; -
Documents
:存储不可再生的关键性数据,不会被iTunes同步; -
Library
:保存配置文件和一些其他文件,NSUserDefault
会存储到Library
下的Preferences
中 的plist
文件中,所以不要在NSUserDefault
中存一些关键数据,或者存储的时候进行AES
加密,会被iTunes
同步; -
temp
:临时文件,不需要时候手动删除其内的文件,这个目录不会被iTunes同步。
下面重新回顾一下沙盒的文档结构。
源代码安全
通过file
、class-dump
、theos
、otool
等工具,黑客可以分析编译之后的二进制程序文件,不过相对于这些工具来说,IDA
的威胁最大。IDA是一个收费的反汇编工具,对于Objective-C代码,它常常可以反汇编到可以方便阅读的程度,这对于程序的安全性,也是一个很大的危害。因为通过阅读源码,黑客可以更加方便地分析出应用的通信协议和数据加密方式。
同样不要在代码中存储关键信息,比如通信接口的AES
加密的密钥,这是因为用脱壳工具可以对加壳的ipa文件进行处理,越狱手机就是这么越狱的,在利用IDA
、Hopper
进行反编译和分析,就可以得到很容易理解的伪代码。
- 关键数据不要保存在本地,尽量通过接口进行获取。
- 如果非要保存关键数据,那么一定要加密后保存,运行时候解密获取数据。
- 密钥要定期更换,如果密钥是才能够服务端获取,那么服务端进行更新处理等。
- 密钥如果写在代码里,app升级版本的时候,新版本app对应接口版本修改为新的秘钥,旧的接口版本和APP版本还有以前旧的秘钥。
对于IDA这类工具,我们的应对措施就比较少了。除了可以用一些宏来简单混淆类名外,也可以将关键的逻辑用纯C语言来实现。例如微信的iOS端的通信底层,就是用C语言实现的。这样的方式除了能保证通信协议的安全外,也可以在iOS和Android等多个平台使用同一套底层通信代码,达到复用的目的。
网络安全
网络安全很大一部分就是网络通信安全,在网络传输的过程中存在不安全的结点,所以我们应该对敏感数据进行加密,同于保证用户的信息安全,黑客可以设置网络代理服务器,截获所有的网络请求,即使是https加密通信,黑客仍然可以使用中间人攻击Man-In-The-Middle Attack
,指的是攻击者与通信的两端分别创建独立的联系,并交换其所收到的数据,使通信的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上,整个会话都被攻击者完全控制)来截取通信内容。
1. 通信协议安全相关
在成功破解了通信协议后,黑客可以模拟客户端登录,进而伪造一些用户行为,可能对用户数据造成危害。
下面我们就先了解下关于https方面的内容。
我们先了解下https ,HTTPS从最终的数据解析的角度,与HTTP没有任何的区别,HTTPS就是将HTTP协议数据包放到SSL/TSL
层加密后,在TCP/IP
层组成IP数据报去传输,以此保证传输数据的安全;而对于接收端,在SSL/TSL将接收的数据包解密之后,将数据传给HTTP协议层,就是普通的HTTP数据。HTTP和SSL/TSL都处于OSI模型的应用层
。从HTTP切换到HTTPS是一个非常简单的过程。
它虽然号称是安全的,但是也是可以抓包和解析的,所以网络通信一定要有自己的加密方式,接口返回的数据最好也加密。
下面我们就看一下charles
抓包。
http抓包
http抓包我们需要按照下面步骤配置charles
。
- 打开
Charles
程序。 - 查看Mac电脑的IP地址,如
192.168.1.7
。 - 打开iOS设置,进入当前wifi连接,设置HTTP代理Group,将服务器填为上一步中获得的IP,即
192.168.1.7
,端口填8888
。 - iOS设备打开你要抓包的app进行网络操作。
- Charles弹出确认框,点击Allow按钮即可。
https老版本抓包
- 下载Charles证书,解压后导入到iOS设备中(将
crt
文件作为邮件附件发给自己,再在iOS设备中点击附件即可安装;也可上传至dropbox
之类的网盘,通过safari下载安装)。 - 在Charles的工具栏上点击设置按钮,选择
Proxy Settings
,切换到SSL选项卡,选中Enable SSL Proxying
。 - 这一步跟
Fiddler
不同,Fiddler安装证书后就可以抓HTTPS网址的包了,Charles 还 需要在上一步的SSL选项卡的Locations表单填写要抓包的域名和端口,点击Add按钮,在弹出的表单中Host
填写域名,比如填api.instagram.com
,Port
填443
。
https新版本抓包
Charles新版本的 Proxy Settings 选项里是没有 SSL选项卡的。在左侧的域名上点右键
:Enable SSL Proxying
,就可以用了。
https相关代码书写
app中一般用的就是AFNetworking
这个框架,常见的问题包括:
- 信任任何证书
在AFNetworking
中定义allowInvalidCertificates = true
,就是表示忽略所有的证书。
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
这种情况的危险就是可以用charles破解https加密的数据,在一般测试环境不用CA发布的证书,而是自签名证书,访问的也不是域名,而是IP。可以使用#ifdef DEBUG
来进行设置。
#ifdef DEBUG
manager.securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy.validatesDomainName = NO;
#endif
- 信任证书管理机构(CA)颁发的证书
黑客可以买到这个证书,AFNetworking2.5.2
以及之前的版本都有漏洞,在不安全网路中黑客就可以使用CA证书对该app的https加密数据进行监听和篡改。
- 信任合法证书,采取服务器和客户端双向认证
虽然安全性提高了不少不过还是可以破解的,可以看这篇文章Bypassing OpenSSL Certificate Pinning in iOS Apps
所以,不要完全信任HTTPS的安全性,任何的协议、代码都是会有漏洞的,关键的数据一定要自己进行加密。
有关证书的配置在AFNetworking上的代码如下所示:
NSURL * url = [NSURL URLWithString:@"https://www.google.com"];
AFHTTPRequestOperationManager * requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
dispatch_queue_t requestQueue = dispatch_create_serial_queue_for_name("kRequestCompletionQueue");
requestOperationManager.completionQueue = requestQueue;
AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
//allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
//如果是需要验证自建证书,需要设置为YES
securityPolicy.allowInvalidCertificates = YES;
//validatesDomainName 是否需要验证域名,默认为YES;
//假如证书的域名与你请求的域名不一致,需把该项设置为NO
//主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
securityPolicy.validatesDomainName = NO;
//validatesCertificateChain 是否验证整个证书链,默认为YES
//设置为YES,会将服务器返回的Trust Object上的证书链与本地导入的证书进行对比,这就意味着,假如你的证书链是这样的:
//GeoTrust Global CA
// Google Internet Authority G2
// *.google.com
//那么,除了导入*.google.com之外,还需要导入证书链上所有的CA证书(GeoTrust Global CA, Google Internet Authority G2);
//如是自建证书的时候,可以设置为YES,增强安全性;假如是信任的CA所签发的证书,则建议关闭该验证;
securityPolicy.validatesCertificateChain = NO;
requestOperationManager.securityPolicy = securityPolicy;
2. 登录安全相关
很多app都是明码传递账号和密码的,那么黑客只要截获网络请求,就可以获得该app的账号和密码,由于现代人的习惯,很多的账号和密码都是一个,那么后果是不可以想象的。
关于登录的加密其实有很多方法,这里介绍一种:先生成一对加密的公私钥,客户端登录的时候,使用公钥将用户的密码加密并传输到服务器,服务器用私钥进行解密,然后加盐处理,再多次进行MD5处理,在和数据库里面存储的同样方法处理过的密码匹配,如果一致,匹配成功,则表示可以登录。
3. IAP安全相关
iOS应用内支付(IAP)是众多应用赢利的方式,通过先让用户免费试用或试玩,然后提供应用内支付来为愿意付费的用户提供更强大的功能,这种模式特别适合不习惯一开始就掏钱的中国用户。但由于国内越狱用户的比例比较大,所以我们也需要注意应用内支付环节中的安全问题。简单来说,越狱后的手机由于没有沙盒作为保护,黑客可以对系统进行任意地修改,所以在支付过程中,苹果返回的已付款成功的凭证可能是伪造的。客户端拿到付款凭证之后,还需要将凭证上传到自己的服务器上,进行二次验证,以保证凭证的真实性。
另外,我们发现越狱用户的手机上,很可能被黑客用中间人攻击技术来劫持支付凭证。这对于黑客有什么好处呢?因为苹果为了保护用户的隐私,支付凭证中并不包含任何用户的账号信息,所以我们的应用和服务器无法知道这个凭证是谁买的,而只能知道这个凭证是真的还是假的。所以在验证凭证时,哪个账号发起了验证请求,我们就默认这个凭证是该账号拥有的。如果黑客将凭证截获,就可以伪装成真实用户来验证凭证或者转手出售获利。打个比方,这就类似于很多商场的购物卡一样,由于是不记名的,黑客如果将你买的购物卡偷窃然后去刷卡购物,商场是无法简单地区分出来的。因此,对于应用内支付,开发者除了需要仔细地验证购买凭证外,也需要告知用户在越狱手机上进行支付的风险。
Reveal UI布局安全
Reveal
是一个很好的UI查看软件,大家调试的时候很多时候都使用过,但是这里我们知道如果手机不越狱,只能查看自己调试的APP,但是如果是越狱的手机,那么还可以查看别的app,如淘宝、去哪儿网等等。
代码调试安全
在release
环境下NSLog
不要打印日志 否则iOS系统日志里都可以查看到,在.pch
文件中加下面的几行代码就可以解决。
1 #ifdef DEBUG
2 #define NSLog(...) NSLog(__VA_ARGS__)
3 #define debugMethod() NSLog(@"%s", __func__)
4 #else
5 #define NSLog(...)
6 #define debugMethod()
7 #endif
现在很多app是用Swift
写的,在Swift 文件中是允许用 NSLog 的语法来打印,但是 不要这么做,因为这样就会导致这段代码在 release环境 中也可以正常输出。通过PP助手
、iTools
,可以直接 查看 iOS的系统日志。也可以直接通过Xcode-Window-Devices - 点最下面的向上的小箭头
,来看日志。所以Swift中打印还是用print
吧。
参考文章
1. 如何确保APP的安全性
2. [iOS]APP安全方面做的几个点总结
3. iOS应用安全开发,你不知道的那些事
4. iOS APP 如何做才安全
5. iOS APP安全杂谈之三
6. Jonathan Zdziarski《Hacking and Securing ios Application》 沙梓社,吴航《ios应用逆向工程》
后记
其实总的来说app安全,主要可以归纳为
网络安全
、本地文件和数据安全
、源代码
安全三个大的方面,每个方面都有很多措施可以保证安全性,也要注意细节,接下来会和大家细说这几个方面。未完,待续~~~