渗透测试与漏洞利用系列课程【第五课】

2018-04-1207:00:37 发表评论

渗透测试与漏洞利用系列课程【第五课】

软件安全开发

软件开发生命周期

软件编码人员进行软件开发过程中,一般都会遵循相应的软件开发生命周期模型用于指导编码的整个过程。计算机软件产品从需求分析、设计、编码、测试、发布到维护,一般称为软件开发生命周期。

一般的软件生命周期包含下面的六个阶段,问题定义、可行性分析、总体描述、系统设计、编码、调试和测试、验收与运行、维护升级到废弃等阶段

  1. 问题的定义与规划

    在软件开发的最初阶段,是软件开发团队与需求方共同讨论确定软件的开发目标,及其可行性分析,并指定相应的开发计划。

  2. 需求分析

    在完成软件开发目标和可行性分析后,接着要对软件需要的各个功能进行详细分析。需求分析阶段是一个很重要的阶段,需求挖掘和探讨的符合度和深度直接影响软件开发的效率。

  3. 软件设计

    在需求分析的基础上,要完成对整个软件的系统设计,如系统框架设计、各函数模块设计、数据库设计等。软件设计总体上分为概要设计和详细设计两部分。

  4. 程序编码

    完成软件设计后,下一步是编码人员根据详尽的软件设计文档完成直接编码,从而将软件设计的结果转换成计算机可运行的程序代码。程序代码为了保证可读性,易维护性,并提高程序的运行效率,一般要制定统一、符合标准的编写规范。

  5. 软件测试

    软件测试能发现软件设计或软件编码中存在的问题并进行修改,从而保证软件的质量。整个测试过程分单元测试、集成测试以及系统测试三个阶段进行。常用的软件测试方法包括白盒测试和黑盒测试两种,针对二进制代码的测试往往还有介于二者之间的灰盒测试法。

  6. 运行维护

    在软件产品完成开发并发布后,往往在功能、安全性、运行稳定性等方面不能满足用户要求或者暴露出问题,为此,需要对软件进行维护。一般的维护包括纠错性维护和改进性维护两个方面。

软件开发生命周期模型

为了指导软件开发工作,在划分软件开发生命周期的基础上,进一步提出了一些软件开发全部过程、活动和任务的结构性指导框架,称为软件开发生命周期模型。软件开发生命周期模型包括瀑布模型、螺旋模型、迭代模型、快速原型模型等。

  • 瀑布模型/改进的瀑布模型

    瀑布模型把软件开发的过程划分为需求->分析->设计->编码->测试等几个阶段进行,每一个阶段都明确定义了产出物和验证的准则。从而可以在每个阶段完成后组织相关的评审和验证,并且只有在前一个阶段的评审通过后才能够进入到下一个阶段。

    为了提高瀑布模型的开发效率,在系统的架构设计完成后,可将系统分为多个可并行开发的模块,每个模块的开发仍然遵循先设计后编码测试的瀑布模型思路,但可以实现部分模块的并行开发,这是瀑布模型的一种改进思路。另一种改进,就是适当的重叠各个阶段的过程,以达到效率的提升和资源的有效利用。

  • 螺旋模型

    螺旋模型总体上是遵从瀑布模型的,即总体上执行需求->架构->设计->开发->测试的路线,螺旋模型加强了软件开发各个阶段的项目管理和控制,它将瀑布模型的多个阶段转化到多个迭代过程中,以减少项目的风险。

    其中的每一次迭代都包含六个步骤

    • 确定目标和替代方案
    • 识别项目的风险
    • 对技术方案进行评估
    • 开发出本次迭代的交付物,并验证迭代产出的正确性
    • 计划下一次迭代过程
    • 提交下一次迭代的步骤和方案。

    螺旋模型实现了每个阶段过程的目标制定、风险分析、交付物的评估验证,并在修正后进行下一轮迭代,周而复始,采用了类似于一个螺旋的方式推进软件的开发,通过这种高级的项目管理方式,保证了软件具有较高的代码质量。

  • 迭代模型

    迭代式模型认为所有的软件开发阶段都可以包括多次迭代,每次迭代过程中要遵循需求->设计->开发的瀑布模型,每一次的迭代都会产生一个可以发布的产品,这个产品是最终产品的一个子集。

    迭代模型能够很好的控制开发风险并予以解决,迭代模型在每个阶段的开始就可以给出相对完善的框架或原型,并且后期的每次迭代都是针对上次迭代的逐步精化和修正,迭代模型能很好的满足用户的需求变化。

  • 快速原型模型

    快速原型模型也称为敏捷开发,它是根据客户的需要在很短的时间内完成一个可以演示的软件产品,这个软件产品可以是只实现部分功能或者是最重要的功能,但是可以让用户直接看到一个直观的原型系统。通过这种方法可以确定用户真正的需求。因为快速原型方法的开发速度很快,几乎没有进行软件设计的工作。所以在用户的需求确定后,后续的开发往往使用快速原型与其他模型相结合的方式进行。

软件安全开发

软件安全开发技术主要包括建立安全威胁模型、安全设计、安全编码和安全测试等几个方面,下面进行简要介绍。

  1. 建立安全威胁模型

    建立安全威胁模型的主要目标,是让开发者全面了解软件所受到的威胁,以及如何减少这些威胁和风险,才能在开发过程中把安全理念和安全技术应用于代码中。建立安全威胁模型,首先需要对软件安全环境进行分析,以确定可能出现的威胁,然后将模型中的威胁方式关联到软件产品的模块上,并在开发中采用消除或缓解威胁的技术。软件安全威胁模型可应用于软件开发的最初阶段,具体步骤如下:

    • 分析软件产品的安全环境,分析内容包括软件的功能作用,潜在攻击者的关注点与攻击力度等
    • 分析软件产品可能遭受的威胁,包括威胁的技术、危害、攻击面等
    • 将所有威胁进行评估分析,并按照风险值进行排序,对风险较大的威胁要重点关注
    • 考虑风险消减技术方案,应用于软件产品中,以缓解威胁
    • 实施解决方案

    安全威胁模型的建立,从通用的角度可以分为对机密性、可用性和完整性构成的威胁类别。从更细的角度划分威胁,可以考虑微软的STRIDE安全威胁模型,它将软件的安全威胁分为以下6种:身份欺骗(Spoofing identity)、篡改数据(Tampering with data)、否认(Repudiation)、信息泄漏(Information disclosure)、拒绝服务(Denial of service)、权限提升(Elevation of privilege)等。

  2. 安全设计

    在软件开发的设计阶段,通过应用安全设计原则,预先从设计和架构角度消除安全缺陷,将成为软件安全开发的关键。在软件设计初期,就需要按照以下安全设计的原则对软件的安全策略、安全环境、威胁解决方法进行全面考虑。

    • 最小权限原则,为软件授予其所需要的最少权限;
    • 开放设计原则,使用公开经过验证的方法而不是不公开的方法来保证软件的安全;
    • 全面防御原则,通过全面的采用防范技术可以避免因单个漏洞对系统造成的危害;
    • 权限分开原则,针对软件的不同使用用户、不同程序或函数,在不同的环境和时间给予不同的权限;
    • 最少公用原则,尽量只给软件开发最少的共享资源;
    • 心理接受性,考虑实施的软件安全技术,应该是用户愿意接受的而不是拒绝使用的;
    • 代码重用性,尽量使用以前经过测试的或已证明是安全的代码;
    • 充分考虑软件运行环境,这是软件设计的基础;
    • 选择安全的加密算法,在保证性能的条件下,应该考虑安全的加密算法;
    • 充分考虑不安全的条件,应该充分考虑软件各方面不安全的条件,要对其每个单元考虑进行安全检查;
    • 失效防护,当软件因安全缺陷出现问题时,应该考虑能给用户提供后备防护措施。
  3. 安全编程

    安全编程在实现软件功能的同时,保证软件代码的安全性。针对不同漏洞和不同攻击的安全编程技术,在前面章节中都有对应介绍,在此不再重复,而是主要介绍安全编程时需要考虑的原则。

    • 数据的机密性
      • 确保临时文件不包含原始信息,并且限制临时文件的访问用户
      • 使用公开验证过的加密算法
      • 不使用明文传送身份验证信息,使用非对称密码算法传递会话密钥,使用会话加密机制加密传输数据,使用强度较高的信息验证算法,并隐藏验证信息
      • 在需要的时候才提供给相应用户最低的权限,操作结束后及时收回权限
    • 数据的完整性
      • 全面检查访问对象的路径、调用的返回代码及关键的输入参数
      • 检查并过滤所有的输入参数,制定严格的过滤规则,防范非法或恶意的参数输入
      • 全面处理异常的输入或输出,防范程序资源被恶意占用或阻塞
      • 验证每个操作的前提条件,限制不触发非法的假设条件
      • 在代码相关位置使用完整的路径名
      • 在数据操作前后执行完整性检查
      • 检查竞争条件
    • 数据的有效性
      • 检查软件的环境参数,防止攻击者伪造参数作为默认环境参数传给程序
      • 软件运行时使用绝对路径
      • 网络环境下,对网络读写操作设置超时限制,并对用户的身份、权限和请求进行相对应的等级限制
      • 对网络操作的IP、端口进行多种验证
      • 采用安全的编译选项和新版本的开发环境,对内存中数据的访问进行严格的检查
    • 其他
      • 为了减少漏洞的产生,尽量用简洁的代码
      • 在遇到程序错误后不去试图恢复,直接中止程序,避免返回软件产品的相关信息造成信息泄露
      • 随机数应该选择用随机性更强的算法进行生成
  4. 安全测试
    • 构造畸形数据包做测试

      针对文件处理软件和网络数据处理软件,构造畸形的文件结构数据和网络数据包数据,开展测试,以发现程序中没有考虑到的畸形数据。

    • 对用户的输入进行全面检测

      攻击者往往构造异常的输入实施对web的注入攻击和脚本攻击,为此,需要对所有的用户输入都进行严格的检测,以发现web应用中对输入限制和过滤的不足。

    • 验证输入输出的文件

      攻击者经常伪造程序输入和输出的大量文件,以实施攻击。为此,需要对相关文件进行全面严格的检测,包括dll文件、配置文件、临时文件等。

    • 测试非正常的路径及其路径限制

      为了绕过程序中对某些资源访问路径的限制,攻击者往往采用不同的路径表示方式进行绕过,并利用路径限制的不足,通过路径回溯访问其他文件。因此,有关路径的测试需要包含多种多样的路径表达方式,并测试路径的访问控制机制。

    • 全面测试异常处理

      web应用中某些异常处理包含的错误信息将泄露敏感的信息,为攻击者提供更多的线索。为此,异常处理的测试应该做为重要的测试内容。

    • 采用反汇编方式检测敏感信息

      对于安全开发经验不足的编码人员,有时会对加密信息不采用有效的防护措施,造成软件的PE文件中包括明文的密码、序列号等。因此,可采用反汇编的方式检测PE文件中是否包含明文的敏感信息。

软件安全开发生命周期

介绍微软的软件安全开发生命周期SDL(Security Development Lifecycle)模型,微软的软件安全开发生命周期模型共包括13个阶段。

  1. 第0阶段:准备阶段

    第0阶段,就是通过教育培训,培养开发团队员工的安全意识。这种通过教育提升安全意识的措施,在公司获得了管理层的明确支持,因而得以贯彻。微软公司通过定期举办安全培训来提升员工的安全意识,并且对产品团队的员工提出了保证100%参加培训的要求。为了确保每个产品团队的人员都积极参加培训并加入到安全技术交流中,微软也考虑了一些办法,例如积分制度,约束员工通过参与培训或其他安全交流而去获得足够的积分,而积分的获得对员工是一个核心的度量指标。培训时的授课人员是从安全团队中来,而不是专门的授课讲师,这将使提问的安全问题回答的更专业。微软公司将这种有效的培训和教育已经形成制度长久保存下来。

  2. 第1阶段:项目启动阶段

    在项目启动时,需要将项目涉及的安全问题都分析到位,以使软件产品更加安全可靠。为此,需要考虑软件安全开发生命周期是否能够覆盖应用软件的每个方面。此外,在项目启动阶段建立bug跟踪管理数据库,确定软件安全开发生命周期中哪些类型的bug需要修复,以实现对安全与隐私泄露bug的精确跟踪。这些工作的开展,需要任命一个安全顾问,由他来担任开发团队和安全团队沟通的桥梁,召集开发团队举办SDL启动会议,对开发团队的设计与威胁模型进行评审,分析程序bug等。安全顾问的最终目标是帮助产品团队在安全方面做得更加完美。安全顾问的人选往往来自于公司的安全团队。除了安全顾问之外,微软公司还为项目组组建安全领导团队。这个团队负责在更高的安全策略层面进行沟通。建立的安全顾问、安全管理团队能够使安全问题的沟通更顺畅。建立bug跟踪管理数据库并设定bug标准将实现对整个SDL过程中的bug有统一的认识和连续的管理。

  3. 第2阶段:定义需要遵守的安全设计原则

    在编码阶段开始之前,需要在设计阶段对软件的安全特性进行较多考虑,并定义出安全设计的原则。设计阶段另一个需要考虑的内容,就是考虑降低软件产品的被攻击面。 安全设计的原则包括:

    • 简化原则,代码尽可能的简短精炼
    • 默认失效保护,对任何不符合条件的请求默认都拒绝
    • 完全检查,对每一个访问受保护对象的行为都要进行检查
    • 公开原则,选取加密机制时尽可能选择经过公开验证过的密码算法
    • 权限分离,不允许只经过单一条件就能通过验证的操作
    • 最小特权,只给操作授予最小执行权限

    软件产品的被攻击面包括一个软件可能遭受外来攻击的所有攻击点,包括代码、网络接口、服务和协议。为了降低被攻击面,需要从下面的几个方面来进行考虑:

    • 软件产品的哪些功能是可以不用的。这个问题考虑的目的是对于不重要的功能尽可能的删减,从而减少被攻击的代码。
    • 攻击者可以从哪里对软件产品的哪些功能进行攻击。考虑这个问题的目的是,让开发者对于攻击者重点攻击的软件模块要着重关注。
    • 降低代码的权限。尽可能降低代码运行时的权限,可以保证存在漏洞时,如果出现漏洞被利用的情况,攻击者获得的控制权限也是最低的权限。

    在设计阶段对被攻击面的分析是非常重要的工作,它可以尽可能预测到未来的攻击,并在设计阶段就以降低被攻击面为目标。

  4. 第3阶段:产品风险评估

    在此阶段对所开发的产品进行风险评估,以确定开发的软件是否采用了有潜在风险的技术,或者是否有较大的隐私泄露危险性。一旦通过本阶段确定了存在较大的风险和隐私泄露的可能性,就应该对后续的软件产品开发投入更多的安全与隐私审查活动。

    本阶段仍然是在软件设计和开发之前,用于理解软件安全开发需要投入的成本大小。如果通过评估发现存在较高的风险,意味着需要投入更高的开发与支持成本。风险评估一般通过调查表来进行,需要调查要开发的软件产品在安装时的详细细节,软件产品的被攻击面问题,软件产品中有关使用脚本代码的问题,以及安全特性和常规问题。通过风险评估,可以在此阶段提前识别,在软件发布之前软件需要进行威胁建模的部分,需要进行安全设计审计的部分,需要进行渗透测试的部分,需要进行fuzzing的部分等等。

    产品风险评估的第二部分是调查软件产品涉及到使用者多少隐私,并依据对使用者隐私涉及的多少进行隐私影响分级,对于包含了使用者最高隐私等级的内容,往往软件后续开发过程中要由专家进行专门的分析,以确保不会发生隐私泄露,甚至触发法律法规。

  5. 第4阶段:风险分析

    对于存在高风险的软件产品,有必要通过威胁建模开展深入的风险分析。威胁建模的目的是帮助软件开发团队在进入编码阶段之前发现系统的威胁,理解软件中潜在的安全威胁,以明确风险并建立相应的威胁消减机制。开发团队通过威胁建模可以重新验证架构和设计,并从安全和隐私保护的角度再次审计整个设计,以理解最具风险的功能模块。

    威胁建模和风险分析的过程虽然繁琐但是并不需要太多安全技能,需要按部就班开展下列建模和分析工作。具体的过程包括,定义软件应用的场景,收集外部依赖的软件环境并列表,定义出软件模块所依赖的系统环境所能提供的安全保证,明确确保功能正常运转的外部安全信息,绘制并分析待建模软件的数据流图,最高层次的数据流图就是场景图,可以展现开发中的系统及与系统发生交互的外部实体间的关系,有助于理解与代码发生交互的对象。接下来是确定威胁类型,识别系统的威胁,从中判断风险,并针对高风险部分规划消减的措施。完善威胁建模和风险分析过程,可以有助于代码评审和测试。

  6. 第5阶段:创建安全文档、安全配置工具

    在此阶段主要考虑的是为用户提供可操作的安全指南和安全配置工具。 为用户提供详尽的安全指南非常重要,它可以帮助用户更安全地部署产品,并深入理解安全配置的各项要求以及配置所带来的安全隐患与问题。这些安全文档包括详尽的安装文档、软件产品的使用文档、帮助文档,如果为用户提供开发接口,还应该包括为开发人员提供的开发手册,并配上相关的编程语言安全开发规范指南等。这些文档中,应该包含对系统进行加固、安全升级和安全隐患的说明。除了安全文档之外,为了实现更好的安全配置,可以为用户提供安全配置的相关工具,例如安全配置向导类工具,使安全配置更加方便。

  7. 第6阶段:安全编码策略

    软件安全编程的策略已经非常多,SDL给出了以下几个方面的指定建议。

    • 第一,使用最新版本编译器与支持工具,在编译时使用内置的安全选项,包括缓冲区栈保护选项/GS,安全异常处理选项/SAFESEH,数据执行保护兼容性/NXCOMPAT。
    • 第二,编码完成后,使用源代码分析工具进行代码的审核分析,源代码分析工具有助于将代码的审核过程快速批量完成,也有助于强制落实安全编码策略。
    • 第三,避免使用危险的函数,减少不安全且容易被利用的编码结构和设计。一般情况可以建立一个包括危险函数和不安全编码结构的安全编码检查列表,这个检查列表可以随时提醒开发人员要注意避免的不安全编码。
  8. 第7阶段:安全测试策略

    安全测试不同于功能性测试,它可以协助开发团队发现可以被利用的高危漏洞。安全测试可以简单的理解为以攻击者的角度开展的测试,具体包括模糊测试(Fuzzing)、渗透测试、运行时验证测试、重新审核威胁模型、重新评估被攻击面。

    • 模糊测试的主要目标是针对文件处理操作、网络协议,以及API函数等,测试过程是先解析测试目标的结构和格式,然后收集尽可能多的有效的输入样本库,然后依据输入样本进行畸形化变异操作,最后拿畸形化后的非正常样本进行测试,并检测是否发生异常。
    • 渗透测试往往是在产品部署后开展的用于发现信息系统脆弱性的测试,然而为了提高软件产品的安全性,在产品的测试阶段就应该开始计划开展渗透工作。由于渗透测试不是开发人员的专长,可以考虑由第三方的公司进行渗透测试。
    • 最后一种测试方式就是运行时的验证测试,以检验软件运行时是否存在某些已知的特定类型的漏洞,以弥补前两种测试中没有对全部已知特定类型漏洞测试的不足。

    在安全测试阶段如果发现软件的设计、功能和实现存在问题,这时就有必要重新审核更新威胁模型,并重新评估被攻击面,以把同类的问题在设计和规划阶段能加以解决。

  9. 第8阶段:开发团队自身进行的全面安全分析检测

    这个阶段是在软件产品进入验证阶段且已经完成所有代码与功能开发后的一个阶段。它给了开发团队一个专门关注软件代码安全问题的机会,它的主要目标就是发现bug,为此需要开展针对此阶段相关工作的安全培训,之后进行代码的评审。

    代码的评审工作首先要建立包含了每个源代码文件的所有者、相关文件信息的数据库,原则上代码的开发者不参与自己代码的评审,可以两人进行交叉评审。之后明确评审的优先级,通过威胁模型识别出的最高风险模块就是待评审的最高优先级代码模块。然后是具体的评审过程,评审过程应该覆盖每段代码。

    评审后要进行威胁模型的更新,以及被攻击面和所有文档的更新,并重新进行安全测试,发现的bug应该被记录下来,并组织修复。

  10. 第9阶段:最终安全评审

    在产品解决完成时,需要做一次最终的安全评审,以检查是否做好了提交给客户的准备。软件开发团队成员不能对自己的产品进行最终安全评审,只有安全团队可以对软件产品进行最终评审。安全评审要对软件产品在安全开发周期中的相关要求逐一验证,包括威胁模型的评审、未修复安全bug的评审,对工具有效性的验证。最终安全评审完成后,安全团队要针对软件产品是否可以发布给用户提出意见,并给出进一步修改的问题。

  11. 第10阶段:组建安全响应团队制定安全响应计划

    之所以要针对软件中的安全漏洞做好响应准备,是由于大规模的软件产品不可避免会存在缺陷,因此要专门组建一个安全响应部门或团队,负责对软件产品中出现的漏洞做出及时的响应,以证明软件产品具有强大的自我更新能力。

    安全响应的过程,首先是接收上报的漏洞,安全机构的研究人员、安全产品厂商、独立的安全顾问、高校的安全研究课题组,以及各种恶意组织攻击数据中提取的漏洞都可以做为漏洞的来源。所有接收到的漏洞都要分工合作处理,由安全团队根据漏洞的严重性进行分析提交报告,产品团队应承担起漏洞的修复工作。漏洞修复后还要进行安全测试,测试要从回归测试开始,要包括应用测试,也要包括部署测试。

    安全响应过程最终的输出成果,包括提供一个有关漏洞影响及修复问题的指南,即微软的安全公告。同时,微软还建立了一个在没有安全更新的情况下发布安全建议的机制,以使用户及时了解微软产品遇到的安全威胁。在完成漏洞更新、编写完成安全报告之后,就可以发布更新后的补丁了。安全响应过程虽然到此就结束了,但是还要从中吸取教训,安全团队中要有一位成员专门负责把安全补丁所修复漏洞的根本原因进行分析并记录存档,并把相关内容提供给安全培训课程做为案例。

  12. 第11阶段:产品发布

    如果上述各个阶段都成功完成,就可以发布软件产品了。如果在整个软件开发过程中,软件产品团队尽职尽责的贯彻了SDL的过程要求,那么产品发布后几乎不会或者很少会出现意料之外的问题,这也是SDL的魅力所在。

  13. 第12阶段:安全响应执行

    在产品发布之后,如果贯彻执行了第10阶段的内容,则软件出现漏洞也能按部就班的进行响应了。安全响应执行中最关键的问题就是制定一个合理的响应计划并执行,另外,就是合理安排开发、测试、打包更新的人员,这时执行安全响应最基本的资源。

CE安全网
CE安全网广告位招租

发表评论

您必须登录才能发表评论!