安全编程 -...

Preview:

Citation preview

软件安全与测试

安全编程

程绍银

sycheng@ustc.edu.cn

软件安全与测试 2

大纲

CERT十大安全编程原则

源代码审核

二进制代码审核

推荐书籍

软件安全与测试 3

大纲

CERT十大安全编程原则

源代码审核

二进制代码审核

推荐书籍

软件安全与测试

CERT安全编码建议

4

软件安全与测试

CERT安全编码建议验证输入。从不可信任的数据源中进行的输入需要验证。合适的输入验证能减少大量软件弱点。必须对大部分外部数据源持怀疑态度,包括命令行参数,网络接口,环境变量,以及用户文件

留言编译器警告。编译代码时使用编译器的最高警告级别,通过修改代码来减少警告

针对安全策略的架构和设计。构建软件架构和设计软件时采用安全策略。例如,如果系统在不同的时间需要不同的权限,则考虑将系统分成不同的互相通讯的子系统,每个系统拥有合适的权限

保持简单性。设计越简单越好。复杂的设计提高了实现时的错误的可能性

默认拒绝。默认的访问决策建立在允许的基础上。也就是说,默认的访问权限时拒绝,除非表明是允许的

5

软件安全与测试

CERT安全编码建议

最小权限原则。每个进程拥有完成工作所需的最小权限。任何权限的拥有时间要尽可能的短

清洁发送给其他系统的数据。清洁所有发送给复杂子系统的数据,例如shell、关系数据库、商用组件等。攻击者可能通过SQL、命令或者注入进行攻击

纵深防御。从多个防御策略中规避风险

使用有效的质量保证技术。渗透测试、Fuzz测试、源代码审计等

采用安全编码标准。为开发语言和平台指定安全编码标准,并应用这些标准

6

软件安全与测试

CERT 安全编码标准

7

软件安全与测试

CERT C语言安全编码标准

8

包括:预处理,声明,表达式,整数,浮点数,数组,字符串,内存管理,输入输出,环境设置,信号量处理,错误处理,应用编程接口等方面

使用该标准将有利于编写安全性高的健壮的软件系统

软件安全与测试

CERT C语言安全编码标准

CERT C语言安全编码标准提供了C语言安全编码的规程和建议,包括预处理,声明,表达式,整数,浮点数,数组,字符串,内存管理,输入输出,环境设置,信号量处理,错误处理,应用编程接口等方面

使用该标准将有利于编写安全性高的健壮的软件系统

9

软件安全与测试

CERT C语言安全编码标准

10

软件安全与测试

CERT C语言安全编码标准

11

软件安全与测试

安全编码避免缓冲区溢出

几个典型的不安全的字符串处理函数

strcpy函数:strcpy函数不安全,应该尽量少用,该函数只能在某些特定的场合能够安全地使用,如向缓冲区中拷贝一个固定长度的字符串,为另外一个字符串添加前缀

Strncpy函数:strncpy函数中有个参数限定了字符串复制的长度,比其他的同类型函数要安全得多,但是它也会带来一些问题:目的缓冲区可能不以空值结束,或者传递到函数中的用户输入内容比缓冲区允许值要长

12

软件安全与测试

安全编码避免缓冲区溢出

几个典型的不安全的字符串处理函数

sprintf函数:它可能导致故障。在调用sprintf函数之前,要检查缓冲区对于输入的数据来说是否足够长比较困难。如果目标缓冲区的结束不是Null

,则发生了溢出。类似的函数还有swprintf、_snprintf和_snwprintf

gets函数:gets函数将从stdio流中读取数据,直到遇到一个换行符或者回车符为止。没有方法能够查知它是否会导致缓冲区溢出,所以不要使用gets函数,用fgets函数代替

13

软件安全与测试

安全编码避免缓冲区溢出

几个典型的不安全的字符串处理函数

strcat函数:Strcat,wcscat,lstrcat这些函数不检查目标缓冲区的长度,也不检查null或其他无效的指针。如果源缓冲区不是以null结尾的,那么结果是无法判断的

Memcpy和CopyMemory:目标缓冲区必须足够大,以便能够存储在长度参数中指定的字节数,否则会发生缓冲区溢出。如果代码只拷贝指定的字符,请使用_memccpy

14

软件安全与测试

安全编码避免缓冲区溢出

几个典型的不安全的字符串处理函数

strlen和wcslen:这些函数都不能合适地处理非null结束的缓冲区。调用他们不会导致可利用的缓冲区溢出,但是如果函数试图读“无人区”,就有可能导致访问侵害。如果数据来源不受信任的话,请考虑在这样的代码周围使用异常处理

scanf(“%s”,....),_tscanf,wscanf:像gets

一样,由于%s是没有边界的,因此scanf,_tscanf,和wscanf都很难正确的使用。虽然可以用像%32s这样的结构来限制字符串的大小,但是最好还是用fgets

15

软件安全与测试

安全编码避免缓冲区溢出

几个典型的不安全的字符串处理函数

标准模板库中的流操作符(>>):C++标准模板库的流操作符(>>)从输入源拷贝数据到一个变量。如果输入的长度不加检查,可能会导致缓冲区溢出。这一点上和gets类似,不要使用该函数,或者用cin.width来限制输入数据的长度。例如,下面的代码从stdin(cin)中读取输入,然后传给szTemp,若用户的输入超过32字节,就会产生缓冲区溢出

16

软件安全与测试

安全编码避免缓冲区溢出

另外,有几个关于进程创建和代码执行的较危险的API函数需要注意

CreateProcess(NULL,...)、CreateProcessAsUser、CreatePrecessWithLogon函数,这些函数的第一个参数是应用程序的路径,第二个参数是命令行。若第一个参数是NULL,第二个参数的应用程序路径中包含有空格,则会执行错误的应用程序

LoadLibrary和LoadLibraryEx函数,若库的完整路径没有指定,这些函数试图从当前工作路径中调用一个DLL。若当前工作路径中存在恶意程序,则可能执行该程序。因此,建议将库的完整路径在调用函数时给出。搜索策略决定了会调用哪一个DLL。搜索策略可以通过SearchPath函数指定

17

软件安全与测试

安全编码避免缓冲区溢出

C/C++常见缓冲区溢出危险函数

18

软件安全与测试

安全编码避免缓冲区溢出

C/C++常见缓冲区溢出危险函数

19

软件安全与测试 20

大纲

CERT十大安全编程原则

源代码审核

二进制代码审核

推荐书籍

软件安全与测试

源代码审核

源代码审核关注编码中的实现缺陷,通常通过静态分析工具进行,它们扫描源代码中,能够发现大约50%的代码中的安全问题

源代码分析工具就是检查源代码,检测并报告代码中的可能导致安全弱点的薄弱之处

人工审核 vs. 静态分析

21

软件安全与测试

源代码审核

基本的静态分析方法有

一个最简单的方法是使用文本查找功能,查找源文件中的有安全隐患的函数

Grep –nE ‘ printf |fprintf |sprintf |snprintf ’ *.c

词法分析方法

基于语法树语义分析

直接发现源程序中的逻辑错误的方法有很多,如数据流分析、类型验证系统、边界检验系统、状态机系统等

22

软件安全与测试

代码审核工具

BOON:来自UCBerkerly。将整数范围分析用于确定C语言程序是否会出现超出数组范围的索引。这个工具虽然能够找出词汇分析工具不能发现的许多错误,它仍然是不完善的:它忽略了语句的次序,它不能建立过程之间互相依赖的模型,并且它忽略了指针混淆

Cqual:来自马里兰大学。受Perl的污点模式的启发,CQual使用类型限定符来进行污点分析,以检测C

程序中的格式化字符串弱点。CQual要求程序员将一些变量标记为被污染或者未被污染的,然后使用类型推论规则来传播限定符。一旦传播了限定符,系统就能通过类型检查来检测格式化字符串弱点

23

软件安全与测试

代码审核工具

xg++:使用模版驱动的编译器扩展来查找Linux和OpenBSD中的内核弱点。xg++工具会检查在哪些位置,内核使用过来自于事先没有检查的不可信来源的数据、用户使用过可能导致内核分配内存且没有释放内存的方法,以及用户可能导致内核死锁

Eau Claire:使用定理证明法来为C程序创建一种通用的规范检查框架。它有助于查找缓冲区溢出、文件访问竞争条件和格式化字符串之类的一般的安全问题。开发人员能够使用规范来保证函数实现的行为与预期一致

24

软件安全与测试

代码审核工具

MOPS:采用模型检查的方法来查找违例的临时安全属性。开发人员可以为自己的安全建模,有的人已经利用该工具来检查特权管理错误、chroot监牢的不正确构造、文件访问竞争条件,以及构想拙劣的临时文件模型。

Splint:将lint的概念扩展到安全领域。通过增加标注,开发人员就可以使用splint来查找抽象违例、未经申明的全局变量的修改,以及可能的使用未初始化变量的错误。如果给函数提供了前、后条件,Splint还可以推测数组范围的最小值和最大值

25

软件安全与测试

代码审核工具

IBM研究院研发的BEAM:采用数据流的方法,分析源代码的所有可执行的路径,以检测代码中潜在的错误

Airac5:一个来自韩国的静态分析自动检查C

语言程序中缓冲区错误的工具

26

软件安全与测试

代码审核工具

27

软件安全与测试

代码审核工具

28

软件安全与测试 29

软件安全与测试 30

软件安全与测试 31

软件安全与测试 32

软件安全与测试 33

软件安全与测试 34

大纲

CERT十大安全编程原则

源代码审核

二进制代码审核

推荐书籍

软件安全与测试

二进制代码审核

源代码审核是对开发团队自己编写的代码进行审核,以消除软件中的安全错误和安全缺陷等潜在漏洞

没有源代码的情况下对第三方程序进行审核方法

一个基本的方法是采用逆向工程的方法:首先分析第三方程序中若干使用较为频繁的库程序,对程序中的涉及到数据输入,字符串处理等逻辑功能的若干代码片断实施逆向工程,然后采取安全漏洞分析的方法和安全编码原则来评价这些代码

还可以采用安全测试的方法:对第三方软件库的可执行代码部分,可以采用软件安全测试的方法,测试其是否存在漏洞,如果发现了漏洞,则判定漏洞的可利用性,并对漏洞进行风险评级

35

软件安全与测试

二进制代码审核

NIST的SAMATE项目给出了二进制代码分析工具的一个列表,同时还给出一个Java字节码分析工具的列表

这里列举二进制代码审核的工具。这些工具既有商业软件,也有自由软件,它们或者是IDA Pro的插件或者是单独开发的应用程序。表8.5列举了它们中的一小部分

36

软件安全与测试 37

二进制代码审核

软件安全与测试 38

软件安全与测试 39

大纲

CERT十大安全编程原则

源代码审核

二进制代码审核

推荐书籍

软件安全与测试

编写安全的代码

http://product.china-pub.com/22278

40

原书名: Writing Secure Code,

Second Edition

原出版社: Microsoft Press

作者:(美)Michael Howard,

David LeBlanc

译者:程永敬 翁海燕 朱涛江

出版社:机械工业出版社

出版日期:2005 年1月

软件安全与测试

编写安全的代码

第一部分 现代安全

第1章 对安全系统的需求

第2章 主动的安全开发过程

第3章 赖以生存的安全法则

第4章 威胁建模

41

软件安全与测试

编写安全的代码

第二部分 安全的编码技术

第5章 头号公敌:缓冲区溢出

第6章 确定确当的访问控制

第7章 以最小特权运行

第8章 加密的特点

第9章 保护机密数据

第10章 一切输入都是有害的

第11章 规范表示的问题

第12章 数据库输入问题

第13章 Web特有的输入问题

第14章 国际化问题

42

软件安全与测试

编写安全的代码

第三部分 更安全的编码技术

第15章 Socket安全

第16章 RPC、ActiveX控件和DCOM安全

第17章 拒绝服务攻击的防范

第18章 编写安全的NET代码

43

软件安全与测试

编写安全的代码

第四部分 特殊的安全问题

第19章 安全性测试

第20章 审查安全代码

第21章 在应有加入隐私策略

第22章 安全的软件安装

第23章 常用的好做法

第24章 编写安全文档和错误消息

44

软件安全与测试

编写安全的代码

附录B 安全误区没有人会做那种事情!

为什么会有人做那种事情?

我们从来没有受到过攻击。

我们是安全的,我们使用了密码。

我们是安全的,我们使用了ACL。

我们是安全的,我们使用了防火墙。

我们已经检查了代码,没有安全bug。

我们知道默认情况下这项功能是启动状态,但是管理员能够将它关闭。

如果我们不以管理员的身份运行,就会有东西不能运行。

但是我们要更改时间表。

它不可利用。

我们总是那么做。

只要我们有更好的工具……

45

软件安全与测试

软件安全实现--安全编程技术

http://product.china-pub.com/51834

作者:郭克华

出版社:清华大学出版社

出版日期:2010 年6月

46

软件安全与测试

软件安全实现--安全编程技术

第1章 安全编程概述

第2章 内存安全

第3章 线程/进程安全

第4章 异常/错误处理中的安全

第5章 输入安全

第6章 国际化安全

第7章 面向对象中的编程安全

第8章 Web编程安全

47

软件安全与测试

软件安全实现--安全编程技术

第9章 权限控制

第10章 远程调用和组件安全

第11章 避免拒绝服务攻击

第12章 数据的加密保护

第13章 数据的其他保护

第14章 数字签名

第15章 软件安全测试

第16章 程序性能调优

48

软件安全与测试

小结

避免犯常见的编程错误

49

Recommended