1、14.3 代码审查中的静态分析第1页,共38页。本节安排代码审查中的静态分析静态分析中的常见缺陷软件漏洞第2页,共38页。代码审查的主要任务代码审查的主要任务完整性检查:代码是否完全实现了设计文档中提出的功能需求正确性检查:代码符合制定的标准;变量都被正确定义和使用;注释都是准确的;程序调用都使用了正确的参数个数一致性检查:代码的逻辑是否符合设计文档;代码中使用的格式、符号、结构等风格是否保持一致。可预测性检查:代码所用的开发语言良好的语法和语义;避免了依赖于开发语言缺省提供的功能;没有死循环;避免无穷递归。健壮性检查:采取措施避免运行时错误(如数组边界溢出、被零除、值越界、堆栈溢出等)4.3
2、 代码审查中的静态分析第3页,共38页。代码审查的主要任务(续)代码审查的主要任务可追溯性检查:对每个程序进行了唯一标识;有一个交叉引用的框架可用来在代码和开发文档之间相互对应;包括修订历史记录,记录中对代码的修改和原因都有记录;所有的安全功能都有标识。可理解性检查:注释是否足够清晰的描述每个子程序等。可验证性检查:代码中的实现技术是否便于测试。可验证性检查:所有代码是可测试的。结构性检查:程序的每个功能是否都作为一个可辩识的代码块存在;循环是否只有一个入口。4.3 代码审查中的静态分析第4页,共38页。代码审查周期 一组定义完善的安全目标将有助于对应该被审查的代码以及应该用于审查这些代码的准
3、则进行优先级排序。建立目标 收集目标代码,去除无关项,添加自定义规则,手工代码审查运行静态分析工具 不要将自己局限于仅仅是分析结果。要让分析工具发现潜在的问题,但不要被它在其他问题上误导,而这些问题原本可以通过自己对代码的检查来发现。审查代码(使用静态分析工具的输出)当程序员解决了审查所识别出的问题时,相应的修复必须进行检验。所采取的验证形式取决于所做更改的性质。进行修补4.3.1 执行代码安全审查第5页,共38页。避开可利用陷阱代码的3中判定 明显是可利用的;不能确定是否安全;明显是安全的。4.3.1 执行代码安全审查陷阱可利用性的危险原因开发漏洞利用手段是一件消耗时间的工作开发漏洞利用手段
4、是一种与其他工作不大一样的独特技能第6页,共38页。静态分析工具将安全集成到软件开发过程中将安全集成到软件开发过程中,是程,是程序序员员应养成的一种习惯。应养成的一种习惯。评估和选择静态分析工评估和选择静态分析工具是具是软件安全的活动软件安全的活动中中必须必须的的部分部分。工工具可使得程序员能更高效地处理软件安全问具可使得程序员能更高效地处理软件安全问题题静静态分析应该作为安全的开发生命周期的一部分,而不是用其替代安全的开发生命周期。态分析应该作为安全的开发生命周期的一部分,而不是用其替代安全的开发生命周期。4.3.2 开发过程中的安全审查第7页,共38页。静态分析工具相关问题-WHO谁会运行
5、此工具?安全团队程序员 以上全体人员 4.3.2 开发过程中的安全审查第8页,共38页。静态分析工具相关问题-WHEN什么时候运行此工具?在代码编写期间在程序生成时 到达整个开发过程中的重要里程碑时4.3.2 开发过程中的安全审查第9页,共38页。静态分析工具相关问题-HOW分析结果会如何分析工具的输出阻塞软件发布 由中心权威机构少量发放个别结果由中心权威机构设置精确的关键问题4.3.2 开发过程中的安全审查第10页,共38页。作用源自静态分析结果的度量标准可用于排序补救工作的优先级、在多个项目之间调源自静态分析结果的度量标准可用于排序补救工作的优先级、在多个项目之间调配资源、从高效的安全过程
6、获得反馈。配资源、从高效的安全过程获得反馈。4.3.3 静态分析度量标准估量漏洞密度通过严重性比较项目通过类别来细分结果对趋势进行监测第11页,共38页。124.4 静态分析中的常见缺陷第12页,共38页。输入处理涉及的安全问题验证内容验证所有输入验证各种来源的输入验证方法强输入验证避免黑名单不要混淆可用性和安全性拒绝不良数据默认执行正确的输入验证检验输入的长度限制数值输入防止元字符攻击使用参数化请求路径操作命令注入日志欺骗4.4.1 输入的处理第13页,共38页。定义缓冲区溢出指的是一种常见且危害很大的系统攻击手段,通过向程序的缓冲区写入超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈
7、,使程序转而执行其他的指令,以达到攻击的目的。4.4.2 缓冲区溢出第14页,共38页。4.4.2 缓冲区溢出u跟踪缓冲区大小 无论采用哪种缓冲区分配策略,跟踪缓冲区大小都是程序分析时必须的工作。追踪缓冲区和其大小,最常见的方法是将它们存储在一个复合数据结构中。绝大多数与人工追踪缓冲区大小相关的错误都发生在当缓冲区的大小不能够正 确维护时。最好方法是,提供集中的库函数来维护常见数据结构的缓冲区大小。这样做可以仔细审 核用于更新这些缓冲大小值得代码,以避免错误。第15页,共38页。缓冲区分配策略缓冲区分配策略静态缓冲区分配:在静态缓冲区分配机制中,缓冲区中的内存是一次性分配的,并且这个缓冲区在存
8、储期间一直保持初始分配的大小。程序员必须为每个缓冲区选定最大长度,所以静态分配缓冲区的应用程序自然就缺少灵活性。在静态分配机制中,当缓冲区过小而不能满足输入数据的要求时,唯一的选择就是拒绝执行操作,或者截断数据并返回一个错误消息。动态缓冲区分配:动态缓冲区分配方法可根据应用程序运行时所需的值,动态分配缓冲区的大小。因为在应用程序编译时不需要确定缓冲区的大小,所以当应用程序所操作的数据在运行时变化很大时,动态解决方案给应用程序提供了更大的灵活性。动态方法是数据驱动的,意想不到的或者恶意的输入可能导致系统耗尽内存资源。4.4.2 缓冲区溢出第16页,共38页。缓冲区溢出分类字符字符串串-gets(
9、)、scanf()等字符串操纵函数等字符串操纵函数4.4.2 缓冲区溢出这里的gets函数不会检查输入的字符串是否超出分配空间的大小,因而导致缓冲区溢出第17页,共38页。有界字符串strcpy()溢出的例溢出的例子子:4.4.2 缓冲区溢出输出:abcdefg代码中将长字符串赋值给短字符串,会造成内存溢出。添加实例第18页,共38页。有界函数的常见缺陷1)因因为边界是根据源数据的大小为边界是根据源数据的大小(而不是目标缓冲区的大小而不是目标缓冲区的大小)来确定的,所以可能来确定的,所以可能导致目标缓冲区溢出导致目标缓冲区溢出。2)目标缓冲区中没有添加一个目标缓冲区中没有添加一个Null终止符
10、,这通常是因为终止符,这通常是因为off-by-one错误而导致错误而导致的的。3)因为边界指定为缓冲区的总容量而不是其剩余空间,所以导致目标缓冲区溢出因为边界指定为缓冲区的总容量而不是其剩余空间,所以导致目标缓冲区溢出。4)因为目标缓冲区没有设置一个因为目标缓冲区没有设置一个Null终止符,所以,函数在目标缓冲区的第一个终止符,所以,函数在目标缓冲区的第一个零字符所在位置后写入数据,从而导致应用程序在内存的任意位置写入数据。零字符所在位置后写入数据,从而导致应用程序在内存的任意位置写入数据。4.4.2 缓冲区溢出第19页,共38页。4.4.2 缓冲区溢出u不是每一次缓冲区溢出都是由字符串操作
11、错误引起的,当一个整数值大于或者小于其范围时,就会产生整数溢出错误。u许多情况下,缓冲区溢出都与数字有关,因为内存分配量、字符串操作长度都是用数字表示的,数字还常用于计算变址内存的偏移量。u 整数 回绕错误 截断和符号位扩展 有符号数和无符号数的转换u 运行时保护 使用类型安全、内存安全的编程语言来编写运行程序,如Java或C#第20页,共38页。4.4.2 缓冲区溢出整数溢出整数溢出回绕错误:是整数溢出的典型示例,在一个整数值回绕错误:是整数溢出的典型示例,在一个整数值超出其数据类型所限定范围的情况下,就会产生回超出其数据类型所限定范围的情况下,就会产生回绕错误。就像回绕错误会引起整数上溢。
12、绕错误。就像回绕错误会引起整数上溢。截断和符号位扩展:当一个整数类型的数据向一个截断和符号位扩展:当一个整数类型的数据向一个比自己位数少的数据类型转换时,就会产生整数截比自己位数少的数据类型转换时,就会产生整数截断错误。断错误。第21页,共38页。常见错误和异常处理方法所隐含的安全问题利用返回代码处理错误管理异常防止资源泄漏日志记录和调试4.4.3 错误和异常第22页,共38页。234.5 软件漏洞第23页,共38页。软件安全漏洞的分类两大分类设计漏洞:设计漏洞:如果程序设计不合理,程序如果程序设计不合理,程序则则不可能满足其需求和目标不可能满足其需求和目标。软件设计要解决的问题是,为满足软件
13、需求所需的任务,程序的各组件彼此间如何进行交互。它将规定系统构架,确定各组件可能的状态,并详细说明各组件之间的数据流。实现漏洞实现漏洞:是由软件实际编码中的安全缺陷造成的。微小的错误如果出现在不当位置又恰好被攻击者发现,那么它将变成一个十分危险的安全漏洞。优秀的安全软件设计人员会使用诸如分类法、最小权限、攻击面缩减、密码技术等安全技术,将实现缺陷的影响或严重程度控制到最低限度。4.5.1 软件漏洞的分类第24页,共38页。密码技术使用中的隐患常见隐患密码技术选用不当依赖隐藏式安全编写到程序中的密钥错误的处理私密信息4.5.2 常见的安全设计问题第25页,共38页。对用户及其许可权限进行跟踪权限
14、和身份认证问题权限和身份认证问题4.5.2 常见的安全设计问题会话管理薄弱或缺失身份鉴别薄弱或缺失授权薄弱或缺失第26页,共38页。有缺陷的输入验证验证例程不集中没有在安全的上下文环境中执行验证不安全的组件边界4.5.2 常见的安全设计问题第27页,共38页。薄弱的结构性安全攻击面就是攻击者可能与之进行交互的应用程序边界攻击面就是攻击者可能与之进行交互的应用程序边界。当一个漏洞被利用时,攻击者无论是执行任意代码或者是操作该系统的文件系统,其动作当一个漏洞被利用时,攻击者无论是执行任意代码或者是操作该系统的文件系统,其动作都是以那个存在漏洞的运行进程所具有的权限来执行的都是以那个存在漏洞的运行进
15、程所具有的权限来执行的。安全设计的基本内在法则之一就是不要依赖一种机制来实现安全性,因为那种机制可能会安全设计的基本内在法则之一就是不要依赖一种机制来实现安全性,因为那种机制可能会失效,应该并用多种相互独立的安全机制失效,应该并用多种相互独立的安全机制。软件应将错误细节记录到管理员可以读取的日志文件中,并只是简单地告诉用户发生了一软件应将错误细节记录到管理员可以读取的日志文件中,并只是简单地告诉用户发生了一个错误个错误4.5.2 常见的安全设计问题第28页,共38页。其他设计缺陷多层应用进程缺陷。应该将用户提供的数据和程序自己执行或传给其他系统执行的代码进行隔离。对外部输入数据做净化处理。跨服
16、务器时,应在每个服务器上做认证。应用程序应以安全的操作模式作为其默认值。有效的审计日志。4.5.2 常见的安全设计问题第29页,共38页。编译型语言-C/C+1)C语言没有安全的本地字符串类型,也没有安全而易用的字符串处理函数;2)缓冲区超限会覆盖栈中的函数返回地址;3)预防缓冲区溢出;4)printf类型的格式化函数;5)整数溢出。4.5.3 编程语言的实现问题第30页,共38页。解释型语言-Shell脚本和PHP脚本语言都是脚本语言都是“高级高级”语言语言。使用动态内存管理为变量分配内存空使用动态内存管理为变量分配内存空间间。最常见的缓冲区溢出源自最常见的缓冲区溢出源自C/C+代代码码。无
17、论使用何种语言或何种函数,永远要对输入长度进行检查无论使用何种语言或何种函数,永远要对输入长度进行检查4.5.3 编程语言的实现问题第31页,共38页。虚拟机语言-Java和C#编译为字节码并需要虚拟机来运行的语言,通常来讲比编译成本机代码的语言更安全一些。Java和C#强化了输入安全,这意味着它们不能访问任意的内存位置。如果一个Java程序试图超过数组边界来访问一个数组,就会抛出一个异常。4.5.3 编程语言的实现问题第32页,共38页。平台就是程序在其中运行的环境。平台包括程序与之交互的一些常用的组件。程序依赖操作系统来与用户、网络以及文件系统进行输入和输出的交互,还要依赖操作系统来产生新
18、的子进程以及与其他进程进行通信。一个设计完善的操作系统会清除默认行为,提供文档来说明安全访问操作系统的API或服务的方式,并且指导程序员编写安全程序4.5.4 平台的实现问题第33页,共38页。在 任 何 平 台 上 使 用 任 何 语 言 编 写 程 序,某 些 应 用 程 序 的 安 全 问题 都 会 出 现。其 中 某 些 问 题 是 由 应 用 程 序 的 某 个 组 件 接 受 的 恶意 数 据 引 起 的,这 种 数 据 在 应 用 程 序 的 另 一 个 组 件 被 当 做 了 合法 的 代 码。另 一 些 安 全 问 题 是 由 于 对 涉 密 信 息 的 不 当 处 理 造
19、成的,这 些 涉 密 信 息 必 须 保 持 其 作 为 秘 密 的 特 征,并 且 要 用 不 可预 测 的 密 码 系 统 来 履 行 加 密 的 使 命。4.5.5 常见的应用程序安全实现问题第34页,共38页。在开发过程中遇到的问题安全需求和前提条件的文档记录贫乏;交流和文档的匮乏;在开发过程中缺少安全过程4.5.6 开发过程中的问题及部署方面的薄弱性第35页,共38页。部署方面的薄弱性部署是指拿到软件,并将其在产品系统上进行安全和配置的过程。4.5.6 开发过程中的问题及部署方面的薄弱性假定软件所使用的文件和注册表键值只会由这个软件修改,而文件和注册表的访问控制机制需要恰当地进行设置,以保护配置文件和注册表不会被篡改。如何部署默认配置最高权限时,将被攻击者利用将软件安装为运行时具有不必要权限第36页,共38页。代码审查代码审查静静态分析工具态分析工具内内存分配方式存分配方式常常见缺陷见缺陷小 结第37页,共38页。内存分配方式内存分配方式代代码审查周期码审查周期编编程语言的分类程语言的分类缓冲缓冲区溢出分类区溢出分类作业第38页,共38页。
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。