昨天傍晚盘古实验室负责任的披露了针对 iOS 应用的 ZipperDown 漏洞,并提供了检索、查询受影响应用的平台: zipperdown.com。基于目前公开的信息,该漏洞的影响面比较大,15000 多个应用可能受此漏洞影响。 并且,结合应用中的其它安全缺陷,可以在某些应用上获得远程任意代码执行能力,即:远程控制目标应用,危害也较大。由于目前官方没有公开 ZipperDown 的详细信息,所以这里会跟大家分享、探讨一下针对 iOS 应用的防守策略以及针对具体功能点的防守方法。
我们谈的主要是防守,谈防守就要基于一定的信任基础,如果什么都不可信,那也就没法做防守了。再具体一点,我们现在谈的是 iOS App 的防守,我们信任的基础是 iOS,即:iOS 系统及服务是可信的,他们的安全性是完整的,没有被破坏的。 对于 iOS 应用而言,操作系统提供的最基本、最重要的安全特性是:代码签名、沙盒。代码签名是指:iOS 上只能运行由苹果签名的代码。沙盒是一种限制程序行为的安全特性,其中包括对程序可以访问的文件的限制,如:App1 无法访问 App2 存储的数据文件。 除了代码签名与沙盒,iOS 上还有其它的一些安全特性或者安全功能,比如:Keychain、用户数据加密等。我们做防守时一定要充分利用现有的安全功能与安全特性,换句话说就是:充分利用苹果提供的资源,这样可以大大降低我们的防守成本,这就是第一条防守策略:尽量基于现有的防御阵地来搭建我们自己的防线。 防守的第二条策略是:要搭建防线。搭建防线,换句话说就是:没有银弹,没有什么单一的防御点可以从整体上保证我们的 App 的安全。以本地存储为例,从 iOS 8.4 之后,没法导出单个应用的存储在设备上的文件,那我们还用不用对 App 存储到本地的数据进行加密?对于我们公司的产品,我们是要求加密的,原因是:如果不加密,我们就依赖于 Bundle 不可导出这个安全特性,但是 Bundle 真的不可导出吗?!有没有办法绕过?实际上是有办法绕过的,我们还可以通过备份手机进而获得应用的数据。所以,如果做了本地数据加密,可以将这个理解为增加了一条防线,那应用就可以抵御后一种攻击方式。 防守的第三条策略是:要持续的、牢牢的抓住主要“矛盾”。对于 iOS 应用而言,我们认为主要矛盾是:远程代码执行。远程代码执行的前提是攻击者可以远程的将攻击 Payload 投放到 iOS 应用中。对于投递恶意 Payload,首先想到的方式是中间人攻击(MitM)。为了避免 MitM,我们要求 App 与服务器的通信使用 HTTPS,并且需要正确的校验证书,这问题我们一直在抓,因为控制住了 HTTPS 就可以大大的降低程序的远程攻击面。在 HTTPS 之后,我们会重点关注用户可以产生内容的 App,这样又可以将攻击面降低。 防守的第四条策略是:尽量避免因为业务功能而将安全降维。这里的典型例子就是脚本能力(或者说热补能力),前面我们提过 iOS 平台的一个重要安全特性就是代码签名,由于代码签名特性、地址随机化特性、iOS App 通信特点(由 App 通过 HTTP 的方式请求 Server 上的数据),远程的在 iOS App 上获得稳定的任意代码执行是非常困难的。而脚本能力恰恰破坏了系统中基本的、重要的代码签名安全特性,可以帮助攻击者获得稳定的远程代码执行能力,从而将 App 的防御能力降维。 前面有点零散的谈了我们对 iOS App 防守的理解以及防守的一些基本策略,下面我们以具体功能点为维度谈谈如何做防守。
移动应用程序中通常会使用 SQLite 数据库来存储应用数据,而数据库本身一般存储在沙盒文件中。尽管在 iOS 8.4 之后,已经无法访问沙盒里面的用户数据,但是在 8.4 以前的设备或者是越狱设备上,数据库文件可以轻易地通过助手类工具导出。 如果数据库里面存储的数据没有进行复杂的加密处理,会是应用程序有敏感信息泄漏的风险,同时也有助于攻击者进行逆向分析。
使用较复杂的加密加盐算法对敏感数据加密后存储。
保存用户信息和属性的一个非常普通方法就是使用 NSUserDefaults。保存在 NSUserDefaults 中的信息在应用关闭后再次打开依然存在。加之 NSUserDefaults 的使用接口非常方便,导致开发人员有可能不加以区别的把数据存放到 NSUserDefautls 中。 事实上保存到 NSUserDefautls 中的数据是没有加密的,可以很轻易地从沙盒中找到。NSUserDefautls 被存储在一个以应用 Bundle ID 为名称的 Plist 文件中。
重要的敏感数据存储在 Keychain 中。
iOS 设备中的 Keychain 是一个安全的存储容器,可以用来为不同的应用保存敏感信息比如用户名、密码、网络密码、认证令牌。苹果用 Keychain 来保存 Wi-Fi 网络密码、V** 凭证等等。它是一个 SQLite 数据库,位于 /private/var/Keychains/keychain-2.db,其保存的所有数据都是加密过的。Keychain 在沙盒之外 App 会将部分重要数据存放在 Keychain 中使用进行读取,但若写入后未清楚就卸载 App 而下一位用户安全 App 时未清除数据,则可能到导致下次安全的时候直接从 Keychain 中读取密码登陆或手势密码无法解除等问题。
首次安装应用程序启动后,进行删除 Keychain 数据操作。
iOS 系统在程序退出的时候,会保存程序当前的快照到/Library/Caches/snapshots 中,如果退出的时候页面含有密码等关键信息未进行处理则会导致安全隐患。
UIApplication 的委托方法 applicationDidEnterBackground: 可用于响应 App 进入后台并且修改敏感数据显示。例如,在进入后台的时候,把特殊字符用“hidder”属性隐藏。
Cookie 是 App 或者网站为了辨别用户身份,进行 Session 跟踪而存储在用户本地终端上的数据。如果 Cookie 以明文的形式存储,那是非常危险的。iOS 上的 Cookie 数据会被保存在 /Library/Cookies/Cookies.binarycookies 中。在越狱设备或者iOS 8.4版本之前的设备上,这个数据是可以被导出并且通过工具 Dump 数据出来的。
1、Cookie 存放前进行较复杂的加密运算。 2、将一部分 Cookie 加密存放在 Keychain 中,增加逆向难度。
在 iOS 应用程序中,使用 HTTPS 进行通信是一种更为安全的做法,也是官方所推荐的做法。但是即使使用了 HTTPS,也有可能因为没有校验服务器证书的原因导致被中间人劫持。如果交互请求数据处理不当,攻击者可以解密得到明文通信数据;甚至进一步伪造 App 的请求,这是极大的安全隐患。
1、App 内要对 HTTPS 证书做校验。 2、避免使用有漏洞的第三网网络库(如 AFNetworking < 2.5.3 版本)。 3、关键数据(如登录密码、卡号、交易密码等)单独加密。
在 iOS 应用程序中,WebView 是经常使用到的一个控件,用来加载网页显示在终端上,因跨平台、动态等特性被广泛使用。但是与此同时,很多桌面浏览器前端漏洞在 iOS 终端上仍然存在。 同时因为 iOS 终端上, WebView 可以注册一些敏感信息数据,比如发短信、付款、定位信息等等,也带来了一些新的安全风险。
1、对输入进行过滤和编码。 2、服务端对 App 发送的数据进行过滤和编码。 3、尽量减少敏感接口的注册、尽量不要加载第三方内容;如果加载,则必须在 WebView 的 Delegate 方法中,通过白名单机制实现对调用者的检验。
在 iOS 应用程序中,经常存在敏感数据需要加密存储的场景。例如登陆密码、通讯录数据等,其加密算法被破解是相当危险的。一旦重要的算法被攻击者逆向,应用的一切数据就相当于毫无保留的展现在攻击者面前。
1、对称加密算法要使用 AES、DES 或 3DES,避免使用 RC4 等目前可能被爆破的算法。 2、对于数据安全性要求较高的场景并且条件允许的情况下,使用非对称加密算法如 RSA 等。 3、对称加密算法的 KEY 和 IV,应避免硬编码。若加密数据仅是本地存储,可基于设备相关的信息来生成 KEY 和 IV。
开发人员可能会从非官方渠道下载开发环境或者开发工具。被修改过的恶意开发工具可能会在打包 IPA 文件时,插入恶意代码。 另外,由于配置不当,打包 IPA 文件时,可能会把源码或者开发文档打包进入 IPA。
1、从官方下载开发工具 Xcode。 2、打包 IPA 文件时,管理好 Xcode 的 Build Phases、Copy Bundle Resources。
开发过程中通常会使用 NSLog 来输出日志,用于调试 Bug 和测试功能。因此在打印出来的 Log 中很容易会泄漏程序的关键逻辑和用户敏感数据,降低了逆向破解的难度,增加了敏感信息泄漏的风险。 如果 Release 包里面没有关闭系统日志,通过 Xcode Device 等工具,可以很容易地看到应用程序 Log 的打印。
1、使用宏来控制测试版和发布版本的日志输出。 2、安全测试和对外发布时使用 Release 版本,关闭日志输出。