无论你是编写银行应用还是游戏,如果应用使用了网络,它就应该是安全的。除了最不重要的数据之外,软件不可能确定用户的数据是否是机密的、尴尬的、还是危险的。看似无关紧要的信息,其实很可能泄密。
由于这些原因,要始终假设应用遇到的每个数据,都可能包含银行账号或密码,需要得到保护。
应用可能遭遇到的攻击包括:
- 窥探——第三方嗅探到传输中的应用数据的攻击。
- 中间人攻击——第三方将自己的计算机插入到应用和服务器之间。中间人攻击包括:
- 窥探和网络诱骗——创建伪装成合法服务器的假服务器。
- 篡改——修改服务器和应用之间的数据。
- 会话劫持——捕获认证信息,将其作用于用户。
- 注射攻击——该攻击使用特定的骗术数据,它能导致客户端或服务器端软件执行未被检查的命令。这通常发生在程序与脚本交互的时候,例如shell或者SQL数据库服务器。
- 缓存溢出以及数字溢出——该攻击使用特定的欺骗数据,能导致应用在它的地址空间的某些部分读或写;而这些部分,是不应该随意执行代码,或泄露隐私信息,或两者都不允许的。
本章解释的是如何防范窥探和中间人攻击。想要了解更多关于注射攻击、缓存溢出,以及其他软件安全方面的内容,请阅读Secure Coding Guide。
启用TLS或SSL
传输层安全(Transport Layer Security, TLS)协议为基于socket通信提供数据加密,以及服务器和客户端的认证,来防范窥探攻击。
OS X和iOS也提供对安全socket层(Secure Socket Layer,SSL)的支持。因为TLS是SSL的继任者。如果两个协议都支持,OS X和iOS在默认情况下会使用TLS。
注意:TLS和SSL的设计主要针对于客户-服务器模式。所以在点对点环境下使用这些协议很难确保安全通信。
安全连接到URL
通过TLS连接到URL很轻松。当你创建NSURLRequest对象以提供给initWithRequest:delegate:方法时,指定的https而不是http作为URL的方案。在没有额外配置的情况下,这个连接自动使用了TLS。
使用流数据的安全连接
你可以通过调用NSStream对象的setProperty:forKey:方法来使用TLS。指定NSStreamSocketSecurityLevelNegotiatedSSL 作为property参数,指定NSStreamSocketSecurityLevelKey作为key参数。如果你需要解决兼容性错误,你还可以指定更多特定的协议,例如NSStreamSocketSecurityLevelTLSv1。
使用BSD Socket的安全连接
当进行安全连接时,如有可能,你应该使用NSStream(如上一节所述)而不是直接使用socket。但是,如果你必须使用直接BSD socket,你必须实现SSL或TLS来自己进行加密和解密。基于你平台,有两种方式可以做到这一点:
- 在OS X中,或在iOS 5及更高版本中,你可以使用Security框架中的安全传输(Secure Transport)API来处理你的SSL和TLS握手交换、加密、以及解密。更多详情参见Secure Transport Reference。
- 在iOS或OS X中,你可以下载开源的SSL或TLS实现,例如OpenSSL,并把该库(或者一部分)的变异副本包含到你的应用程序束中(或者和你的非绑定程序在一起)。确保遵守你可能使用的第三方库的许可条款。
注意:虽然OpenSSL库的一个版本已经作为OS X的一部分被包含,但OpenSSL库不保证不同版本的OpenSSL二进制兼容。因此,在OS X v 10.7开始,不在支持连接到OpenSSL的内置副本。如果你想使用OpenSSL,提供库的你自己的副本,以便你精确地控制程序连接的OpenSSL版本。
在OS X中使用其他安全协议
除了默认的TLS安全传输实现,下面的网络安全协议在OS X中也是可用的:
- Kerberos协议可以通过Kerberos框架使用。这个协议提供通过网络单点登录认证的支持。更多信息,阅读read Security Overview 和 Authentication, Authorization, and Permissions Guide.
- 安全外壳(Secure Shell,SSH)协议。这个协议通常使用于终端应用登录远程主机。更多信息参见ssh。
- TLS的OpenSSL实现,但是由于二进制兼容性原因,OS X v10.7之预装的OpenSSL库被弃用。如果你需要OpenSSL,则提供该库的你自己的副本,并将其静态连接到你的应用。
常见错误
在编写安全网络代码的时候,有一些开发者常犯的错误。本部分提供为避免其中几个错误的建议。
谨慎对待你相信的服务器
如果应用和服务器传输有潜在机密的数据,要确保它对服务器的认证,以保证它没有被欺骗。确认你的服务器认证当前的客户端,来避免把数据提供给错误的用户。此外,确保连接使用合适的加密方式进行了加密。
同样的,请确保仅在必要的时候存储数据,并以执行任务所需的最小量来提供数据。例如,为了最大限度的提高用户个人信息的隐私性,你可以将网络服务器的数据库放在独立的服务器上,配置为仅从你的网络服务器上接收SQL请求,显示它和整个网络的连接。换句话所,使用了适当的权限分离。
更多信息,请阅读Secure Coding Guide中的Designing Secure Helpers and Daemons。
谨慎对待你相信的数据
每个应用到处在被恶意内容攻击的危险之中。尤其是在应用从不受信任的服务器获取数据,或从信任的服务器获取不信任数据的时候(例如论坛帖子)。
为了防止这样的攻击,应用应该小心的检查所有来自网络或磁盘(因为用户或许已经下载了数据)的数据。如果数据以某种方式表现出了恶意,不要像处理正常数据那样处理它。
更多信息,参见Secure Coding Guide中的Validating Input and Interprocess Communication
要知道千里之堤溃于蚁穴
始终采取措施确保应用在网络中的内容保持私有。虽然某些信息本身看上去是无用的,但是一个老练的攻击者可以把该信息和其他信息进行结合,从而可能发现比单条信息本身有用的多的隐私事件——该过程就是数据挖掘。
例如,如果某人想要进入你的房间,在周六晚上在图书馆发一个帖子可能是无用的,但是连续几个周六在相同的时间在图书馆发帖子就可能不是无用的了,因为它们表明了你的习惯。
数据甚至不需要都是针对同一件事也可以造成伤害。知道某人喜欢看特定的电视节目可能无害,但是一个人的喜好、购买的物品、以及交往的朋友组成的完整侧写,可能可以和一个人的隐私有强关联性,例如宗教和性取向。一个令人印象深刻的例子(也可能不是事实),说连锁零售企业承认,它们通过一个女孩的购买决定断定她已经怀孕,而女孩的父亲此时还尚不知情。
身份信息泄露特别成问题。如果你的应用泄露了手机号,其他应用可能泄露邮政地址等等。当攻击者搜集到受害者足够信息的时候,他就可以使用社交工程技术来说服第三方给他更多信息,从而导致信息收集的反馈循环,造成毁灭性后果。
因此,应用在任何时候进行加密通信是非常重要的,针对所有连接,除非这样做不可行。你永远不知道此时看起来无害的信息,在和别的看似无害的信息结合之后,就有可能发酵为危险或伤害。
正确的安装证书
当使用TLS或SSL连接服务器的时候,如果应用得到一个错误,表示签发了你的证书的认证机构是未知的,假设你从有信誉的认证机构获取的证书,那么者几乎就是意味着你的证书链丢失或不完整。
当你的服务器接收到一个通过TLS或SSL加密的连接,它会提供两样东西:你的服务器的SSL证书,以及完整的SSL证书链,从服务器的证书开始,到一个被信任的锚证书签名的证书止,这个锚证书是被操作系统识别的。如果证书链中有证书丢失,你将得到一个错误,因为链中的较早的证书无法被后面的证书验证。
想要查看你的服务器到底发送了什么,在终端中输入以下命令(将www.example.com替换成你的真实域名)并按下回车键:
openssl s_client -showcerts -connect www.example.com:443
当你输入这个命令时,你应该可以看到你的服务器证书,然后时一系列中间证书。如果你没有得到,检查你的服务器配置。想要获取正确的证书以便放置到你的服务器证书链中,请与提供服务器SSL证书的认证机构联系。
永远不要禁用证书链验证(除非你自己验证)
禁止链验证消除了你使用安全连接可能得到的任何好处。所得到的连接不比使用没有加密的HTTP发送请求更安全,因为它没有提供防止假服务器欺骗的保护。
如果你使用受信任的认证机构的服务器证书,确保你的证书正确的被安装(查看上一部分)。
如果你临时使用自签名的证书,你应该把它们添加到你的测试机器的可信任锚列表中。在OS X中,你可以使用Keychain Access(钥匙串访问)实用工具应用做到这一点。在iOS中,你可以在程序中使用SecTrustCopyAnchorCertificates, SecTrustCreateWithCertificates, 和 SecTrustSetAnchorCertificates函数。
如果你需要特别允许的单独的自签名证书,或为不同(特定)主机的签名证书,你可以通过阅读Overriding TLS Chain Validation Correctly来了解这样做的安全方式。
网友评论