九.安全

九.安全

深入了解安全相关书籍:《Hacking and Securing iOS Applications: Stealing Data, Hijacking Software, and How to Prevent It 》,《黑客攻防技术宝典:iOS实战篇》,《iOS Application Security: The Definitive Guide for Hackers and Developers》

9.1 应用访问

9.1.1 匿名访问

为设备创建唯一的标识符: 供应商的标识符(IDFV-identifierForVendor) 广告商的标识符(IDFA-identifierForldentifier)

//检索IDFV
-(NSString *)idfv{
	UIDevice *device = [UIDevice currentDevice];
	NSUUID *rv =device.identifierForVendor;
	while (!rv) {
		[NSThread sleepForTimeInterval:0.005];
		rv = device.identifierForVendor;
	}
	return rv.UUIDString;
}

//检索IDFA
-(NSString *)idfa{
	//#import <AdSupport/ASIdentifierManager.h>
	ASIdentifierManager *mgr = [ASIdentifierManager sharedManager];
	if (mgr.isAdvertisingTrackingEnabled){
		NSUUID *rv = mgr.advertisingIdentifier;
		while (!rv) {
			[NSThread sleepForTimeInterval:0.005];
			rv = mgr.advertisingIdentifier;
		}
		return rv.UUIDString;
	}
	return nil;
}

http://www.jianshu.com/p/0ba161cff01e http://www.cocoachina.com/industry/20130422/6040.html

9.1.2 认证访问

当需要识别用户时,需要认证访问。

  • 应用密码(应用PIN):存储在设备本地的密码。使用钥匙串在本地存储密码。
  • 游戏中心(仅使用游戏):用GameKit连接游戏中心,后者会负责使用凭证对用户进行验证。游戏中心可以访问用户资料,个人记录等,但仅共享唯一标识用户所需内容。
#include <GameKit/GameKit.h>//1.GameKit头文件,需加入GameKit.framework
-(void)authWithGameCenter{
	GKLocalPlayer __weak *player = [GKLocalPlayer localPlayer];//2.GKLocalPlayer表示运行游戏的已认证玩家。任何时刻,设备上只能有一个认证玩家
	if (!player.authenticated){//3.检查玩家是否通过认证
		player.authenticateHandler = ^(UIViewController * _Nullable viewController, NSError * _Nullable error) {//4.authenticateHandler触发授权
			if (error){
				//处理错误
			}else if (viewController){//5.如果用户以前没有授权与Gamekit连接,那么在回调中返回的 视图控制器必须显示出来
				[self presentViewController:viewController animated:YES completion:nil];
			}else{
				GKLocalPlayer *lp = player;
				if (lp){
					[self verifyLocalPlayer:lp];//6.正常流程获取用户详细信息
				}
			}
		};
	}else{
		[self verifyLocalPlayer:player];
	}
}

-(void)verifyLocalPlayer:(GKLocalPlayer *)player{
	[player generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL * _Nullable publicKeyUrl, NSData * _Nullable signature, NSData * _Nullable salt, uint64_t timestamp, NSError * _Nullable error) {//7.获取签名,从而验证本地玩家
		if (error){
			
		}else{
			//player id = player.playerID
			//使用数据核实  实际的验证应给服务器端
		}
	}];
}
  • 第三方认证
  • 自定义认证:
    1.强制要求使用强密码。
    2.提供会话列表,并允许用户将其他设备或位置上的现有会话设为无效。
    3.启用会话超时机制。
    4.对于永久登陆,确保访问令牌存储在本地的钥匙串中。

9.2 网络安全

讨论在于远程设备通信中与安全有关的最佳实践,该远程设备可以是服务器,也可以是点对点设备。

9.2.1 使用HTTPS

1.CRIME攻击 不要使用SSL/TLS压缩.使用TLS压缩,任何请求都会受到CRIME攻击(英语:Compression Ratio Info-leak Made Easy,意思为:压缩率使信息容易泄露)。要想缓解风险,可以关闭TLS压缩,并给每个响应发送反CRIME cookie,较为简单的方式是发送一个唯一的随机序列cookie。 https://zh.wikipedia.org/wiki/CRIME,http://www.freebuf.com/articles/web/5636.html

2.BREACH攻击 (全称:Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext的缩写,意为“通过自适应超文本压缩做浏览器侦听和渗透”)。 满足下列标准,就会存在风险:

  • 应用使用HTTP压缩
  • 响应反映了用户输入。
  • 响应反映了隐私。

http://www.breachattack.com 网站按有效性列出一下方法降低风险:

  • 禁用HTTP压缩。这种方法增加了传输的数据量,一般不作为实际的解决方案。
  • 从用户输入分离出隐私。将授权码放在远离请求正文的地方。
  • 对每个请求进行随机化的加密。但是,由于每个请求的加密是随机的,因此,多个并行请求可能无法实现了。
  • 修饰隐私。不要以原始格式发送隐私。
  • 使用CSRF保护易受攻击的HTML页面。在移动原生应用上,除非使用移动Web,否则不需要CSRF。https://zh.wikipedia.org/wiki/跨站请求伪造
  • 隐藏长度。一个较好的方法是在HTTP响应中使用分块传输编码。
  • 对请求限速。

9.2.2 使用证书锁定

HTTPS的基础是对公钥的信任,该公钥用于加密初始信息(在SSL握手期间)。中间人(man-in-the-middle,MITM)攻击会捕获用于加密消息的密钥。

输入图片说明

这个问题的解决方案就是所谓的证书锁定。这种方案的工作原理是,通过只信任一个或几个能够作为应用根证书的证书,应用创建一个自定义的信任级别。这允许应用仅信任来自白名单的证书,确保设备上用不安装那些允许网络见识的未知证书。

参考文章:http://www.jianshu.com/p/f732749ce786,https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#iOS

9.3 本地存储

保护本地存储空间遵循的最佳实践:

  • 本地存储不安全:在越狱的设备上非常容易访问本地存储。服务器应实现额外的安全性,使用速率限制技术和增强的DDoS保护措施来进行防卫。
  • 加密本地存储:在Xcode中启用数据保护。 输入图片说明

默认情况下,启用数据保护后,应用使用的所有本地存储都将使用设备密码进行加密。这意味着在设备解锁前无法访问数据。 在Apple Developer门户上配置安全级别。

数据保护的安全级别共享和权限选项:(sharing and permissions)

  • 安全保护:在任何时候访问文件进行读取或写入时,设备都需要是解锁状态的。
  • 打开前保护:这需要在创建文件句柄时解锁设备,一旦句柄可用,则设备锁定时也可以写入内容。这一选项在设备已经锁定,但还需要对文件进行写入时比较有用。
  • 第一个用户认证前保护:这需要设备在重新启动后进行一次解锁。第一次解锁后,应用可以访问所有文件,并且没有任何限制。
  • NSUserDefaults 不安全。plist文件是与其他应用文件一起保存的。
  • NSBundle值也不安全。包含值的.plist文件实际上是可以被篡改的。
  • 不要完全依靠钥匙串:可以对存储在密钥库中的数据进行加密,并只存储最少的数据。还可以针对每个设备生成密钥,并在本地存储。最好的做法是让攻击者更加那一定位和解密数据。如果攻击者可以物理访问设备,能做的也只有这些。
  • 小心记录的东西:不要在非调试版本中使用NSLog,会在View Device Log看到所有日志。(CocoaLumberjack库)

9.4 数据共享

共享数据和处理传入数据时遵循的简单基本规则是:不要信任对方。 当接受数据时,总是进行验证。应用对数据的唯一假设应该是,它可能是无效且错误的。为了提高安全性,要求数据进行签名。

9.5 清单

静态代码分析
是否使用了NSLog,如果是,仅在调式模式中使用
所有的URL都是HTTPS
本地文件的路径不是硬编码的
检查最新版本和补丁程序的依赖关系
没有使用私有API
代码中没有嵌入私钥或隐私
资源中没有嵌入私钥或隐私
没有运行不到的代码或无用代码
权利是正确的(没有丢失,没有附加)
应用使用了IDFV
应用使用了IDFA
为应用签名设置正确的配置文件/证书
检查SQL注入

运行时分析--日志
仅对文件执行日志记录
定期删除日志文件
执行日志循环
日志中没有隐私或敏感信息
打印栈跟踪时不会记录敏感信息

运行时分析--网络
只使用HTTPS URL
服务器有针对CRIME攻击的实现
服务器和客户端应用有针对BREACH攻击的实现
客户端使用证书锁定
设置正确的缓存策略

运行时分析--认证
应用使用第三方身份验证
应用使用自定义身份验证
第三方验证SDK按照此清单的其余部分进行严格的审核
登陆UI隐藏了密码
密码不可复制
应用实现密码
密码存储在钥匙串中
可以通过服务器的配置更改身份验证工作流

运行时分析--本地存储
应用使用本地存储
加密所有的敏感信息
周期性清理存储

运行时分析--数据共享
应用使用共享秘钥库保存常见设置
验证深层链接URL
验证任何传入的数据
不向未知应用共享任何敏感数据
使用应用扩展时,设置正确的群组ID

猜你喜欢

转载自my.oschina.net/u/2319073/blog/1593288