Carnegie Mellon(卡内基梅隆)
软件工程学院
攻击性思想
综述
指南
• 多个期望从单个上学到有意义的东西的
多对一关系
学术讨论会
• 所有人都希望在为小组做贡献,同时也
希望从小组那里学习的多对多关系
本指南介于这两者之间
攻击的历史
1988年,美国电脑紧急应变团队(CERT)成立
1993年,美国电脑紧急应变团队(CERT)/合作中心攻击
响应组(1)
1995年,我加入了美国电脑紧急应变团队(CERT)
• 吉姆埃利斯和拉里罗杰斯带领我们进入了我们后来一
直在的轨道上。
2003年,总共有了10多个响应职员
2004年,有了两个新的攻击工作区
• 攻击分析
• 攻击发现和避免
软件的过程模型(现今)
Conception:概念
Requirements:需求
Architecture:体系结构
Design:设计
Implementation:执行
QA/Testing:质量评价/测试
Correct/Patch:纠正/补丁
Release:释放
Vulnerability:攻击发现
Publication:发布
美国电脑紧急应变团队(CERT)/合作中心哲学体系
白痴们会说他们是由经验获取知识的。而我更喜欢从别
人的经验上获取知识。
Otto von Bismark
德国首相 1871-1890
对于构建足够的理论基础或是实际应用,直接获得的经
验都具有先天的局限性。
B. H. Liddell Hart
大不列颠军事理论家
VDA的使命
美国电脑紧急应变团队(CERT)©合作中
心攻击发现和避免机构的作用是,显著的
减少众所周知的攻击。
VDA的目标
调查和研究现有的方法,技术和工具
与现有的VDA的组织合作
直接或者是间接的推进实践的状态
建立VDA的效率的测量方法
为特定的读者编写VDA知识
广泛的传播上述的VDA知识
• 信息保证社团
• 质量保证社团
• 软件工程社团
VDA反对的目标
我们自己不需要建立重大的发现机构,因为
• 其他人计划或者是已经在做着发现工作
• 无论如何我们自己都不能发现许多的攻击
- 许多更高的影响因素
• 我们希望其他的人从事到VDA的研究中
- 尤其是在软件工程社团
• 最终,我们希望美国电脑紧急应变团队(CERT)-如
VDA组织,需求减小。
-以常规的方式
• 我们不做软件工程
- 尽管我们的名字如此,但是我们不做软件工程。
软件的过程模型(未来)
Requirements:需求
Architecture:体系结构
Design:设计
Implementation:执行
QA/Testing:质量评价/测试
Correct/Patch:纠正/补丁
Release:释放
Vulnerability Discovery:攻击发现
Publication:发布
Vulnerability Discovery &Avoidance:
攻击发现&避免
VDA的过程模型(全世界的)
Publish/Patch:发布/补丁
Release:释放
Public Vulnerability Discovery Process(es):公众的攻击发现程序
Private Software Engineering Process(es):私人的软件工程程序
Case Inspection:个案检查
Infusion:灌输
VDA Codification Process:VDA的编写过程
个案的学习
识别所有的公众攻击发现组织,如下:
• 即使是那些看起来是有组织的,程序的定向是为了发
现的
• 具有可靠的发现攻击的历史
• 具有分担的意志,用抽象的术语来说,就是将这一知
识作为一个总体而和社团一起分担。
去观察他们的影响并且以一个新闻工作者的角度来采访
他们
出一本书来证明这些个案
• 这本书要包括这些组织以及他们的工作两个方面
个案研究
为成功者颁发大量的专门的荣耀
• 以组织或者是个人的名字来命名
• 将成功或者是很有希望成功的精确的归功于它们的创
造者
• 记述失败或者是不确定的实践时,不记录它们的归属
者
包括他们的工作的技术方面,程序方面和组织方面
每年重复这个过程一次
每年出版这本书的一个新的版本
包括我们知道的关于VDA的“所有的事情”
求助!
我们需要你的意见:
• 什么组织或者是个人需要进行个案研究
?为什么?
• 他们的特征是什么?成就又是什么?
应该包括什么专业的讨论会?
• 用来学习?
• 用来教授?
迄今为止我们鉴定的组织/个人
基本方法
如果我们真诚的希望在攻击出现以前就把
它们停止掉,那么我们就必须:
• 采用软件工程师们的观点
- 因为软件工程师们是唯一的可以使这种情况发生的
人
- 并且,我们必须从他们的观点来看这个问题,进而
以他们的语言来描述这个问题 和它的解决方法
观点的改变(1)
和我们以前在攻击上使用的观点相比,VDA中的A需要有
一个不同的观点
• VDA对“验证”攻击不感兴趣
• VDA对开发或者是攻击不感兴趣
• VDA对“验证”攻击的影响不感兴趣
• VDA对“验证”工作区不感兴趣
• VDA对“配置”不感兴趣
• VDA对“验证”最差的攻击不感兴趣
从根本上讲,VDA实际上是关于抢先减少所有潜在的工
程攻击
观点的改变(2)
然而,一种软件工程观点认为
• 所有可能被开发的缺陷都必须被消除掉
- “潜在的”和“事实上的”是同等重
要的
• 必须总是能够设想到全能的对手
- 所有的对手,包括现在的和未来的,
都必须得考虑到
计划
从一个“公众”攻击发现的观点来看
• 这个过程从第一个客户关系开始
• 主要在“公众”中传导
• 必须是“可以控制的”
从一个软件工程的观点来看
• 这个过程从观念的规划开始
• 两个非常清晰的发现的案例
- 先前发布的编码基数中的攻击
- 最新发布的编码基数中的攻击
攻击发现的问题
• 目标的选择
• 发现所使用的技术
• 发现所使用的工具
• 暴露的事实
• 工程上的纠正
• 各个评价之间的关系
• 潜在的合法的障碍
• 国内和国际关注的东西
• 长时间的影响
• 无意识的副作用
目标的选择(1)
互不相关的动机
• 当攻击研究的发起者和VDA组织的发起者具有
互不相关的动机时,会怎么样呢?
- 在技术选择上的争论可能会加速研究,从而
“证明”哪一个是更好一点的方向发展
隐藏的或者是敌对方的评估
• 在不与成果的创造者合作的情况下,评估这个
成果会有多少困难呢?
• 发起者会认为这种评估是客观的吗?
- 对成本而言,客观性是值得的吗?
目标选择(2)
附着于评估的串
• 抑制结果?
• 延迟结果?
• 顺从成果的所有者?
• 顺从发起者?
• 限制除了攻击以外的细节?
• 限制副作用结果的产生?
商业秘密
• 如果合作伙伴中的卖方提供商业秘密来帮助评价,那
怎么办呢?
• VDA组织中的哪个人可以接触到商业秘密呢?
发现所使用的技术(1)
攻击的可证明性
• 在评估(没有经过“处理”)中,为了列出攻
击的特征,而需要的证据的水平
- 必须把攻击的特征证明给卖主
在没有可证明性的情况下,完成的评估
• 这个“报告”真的还可以完成吗?
• 是否一个清晰的缺陷就够了,还是说它必须得
是可以被开发的呢?
• 在没有进行局部的“处理”的情况下,可以对
攻击下结论吗?
发现所使用的技术(2)
评估的成本/利益
• 什么样的评估投资是最有价值的呢?
- 体系结构上的和设计上的攻击是更有价值的,但是,也更难发
现。
– 因为在发布之后的修正可能是极端地,或者是无限的昂贵,所以它
要远远的有价值
- 执行攻击比发现攻击要简单多了,但是相对应的,也就具有较
少的价值
– 之所以具有更少的价值仅仅是因为它们容易被发现
– 在发布以后,保证书必须是可确定的
• 第三方评估通常是具有最差的成本/利益比
- 信息的数量最少
- 最小的价值,攻击最容易发现
发现所使用的工具(1)
增加的攻击发现
• 新的工具将如何影响社团呢?
- 伴随着工具的使用,更多的攻击将会被更多
的人发现(至少是增加的)
- 加重“处理”组织的负担
指南协助的要求
• 是否VDA组织能够负担得起发布这些工具呢?
- 需要其他人为这些工具的使用提供“支持
”
发现所使用的工具(2)
业余者用法
• 业余者能够使用这些工具吗?
- 对于业余者而言,工具不太容易被操
作。
- 工具用户界面需要把目标定位于专
家,而不是定位于普通的公众
暴露的事实(1)
VDA并不能够“处理”这些攻击
• VDA攻击是怎么处理的呢?
- 必须使用已经建立起来的“处理”程序,而且这些处理程序不
可
以复制
- 对于VDA的目的来说,这些已经存在的“处理”程序是否是充
足
的呢?
个人攻击公众暴露的事实
• 攻击与成果观点是相互冲突的吗?
- 即使VDA不关心个人攻击揭露的事实,风险承担者也会期望
他们将这个问题恰当的解决的。
- 在VDA和VH之间需要建立一种独立的而不是共生的关系
暴露的事实(2)
评估报告揭露的事实
• 在评估的最后,由哪个人根据结果决定发生什么?
- 发起者这样的关系将会希望得到切实的文件
- 他们能够自由的四处展示 - 作为成就的证据
评估报告的所有权
• 谁拥有这个报告的所有权呢?
- 从处理的观点来看
- 从知识产权的角度来看
暴露的事实(3)
报告的发表
• 发表的频率频繁到等于只揭露几个攻击
• 在发布报告前,报告中包括的所有的攻
击,是否都必须得“处理”了呢?
- 是?这样将会使VH在通往VDA的里
程碑的关键路径上工作
- 否?发布包含“新”攻击的报告的结构
会是什么呢?
暴露的事实(4)
不明确的攻击
• “潜在的”攻击的报告是否会引起问题呢?
• 在发表的报告中,从工程角度看的一个非常清晰的缺
陷,可能会在攻击分析社团引起相当大的争论
- 对于攻击的开端来说,从工程师的角度看要比从分
析家的角度看要低的多
评估的副作用
• 非常清晰的缺陷不是攻击吗?
- 对于发起者而言,它们显然是有价值的
• 缺陷和攻击的分界线在哪里呢?
- VDA与QA相比是多呢还是少呢?
揭露的事实(5)
成果内部
• 如果成果内部的揭露需要理解攻击呢?
- 许可是可能的吗?或者甚至它就是一个好主义呢?
• 如果评估是“不公开的”或者是“敌对的”呢?
竞争评估
• 对你的报告,其他的VDA组织将会做出什么样的反映呢?
- 其他的VDA组织可能会评估你的评估
这是同行审查过程中很正常的一步
其目标可能会是推进认识也可能会是诋毁其他人的名望
对可靠性有疑问的攻击,这样的竞争可能会产生明确的结构
工程纠正
• 如果评估是不公开的,那么,将会期望什么样
的处理,或者是什么样的处理是可能的呢?
• 如果发起者希望这个攻击继续,那又怎么办呢
?
发起者专用的纠正
• 如果工程纠正是专用于发起者组织的,那么又
怎么样呢?
- 报告的发布可能会危及到发起者组织
- 对于其他的组织来说,这份报告也许会是毫
不相关的,或者甚至可能会是错误的
各个评估之间的关系(1)
遗传性攻击
• 如果“发起者的”评估发现了“遗传性”攻击,那又
怎么办呢?
- 其他受到影响的“成果”又该如何处理呢?
• 如果不公开的评估中发生了遗传性攻击,那又该怎么
办呢?
- “其他的”攻击是否需要进行不公开的考虑呢?
争论
• 如果两个不同的发起者希望相同的目标评估,但是却
使用相互冲突的串,那么又该怎么办呢?
各个评估之间的关系(2)
工程的相互依赖性
• 什么样的依赖性呢?
- 共用的图书馆
- 静态的图书馆
- 资源的重复利用
• 公共界面条件
• 私人界面条件
- 随意的剪切和复制
• 我们怎么发现依赖的成果呢?
- 一些“依存性的博物馆”?
- 一些只有卖主才有的公告?
- 公众的公告和期望?
- 这难道不是“处理”吗?
潜在的合法的障碍
反向工程
• 什么“水平”的RE是被合法的允许的呢?
- 美国的DMCA?
- 欧洲,日本?
商业秘密
• 商业秘密,甚至是从来没有被揭露的商业秘密,
真的可以在UDA中“使用”吗?
- 那是否是违背产权的呢?
- 或者是违背专利权呢?
国内和国际的关注点
有吗?
长远的影响
质量下降
• 范围广大的VDA组织会使得软件的质量下
降是否是可能的呢?
• 生产者是否期望其他的人来发现攻击呢?
- 免费的?
- 在契约下?
无意识的副作用
卖方操作
• 是否卖方会故意的逼迫VDA社团,免费
的为他们发现他们的攻击呢?
• 是否“少量”的卖主甚至能够发现他们
自己的攻击呢?
- 他们支付得起吗?
• 时间对市场可能会是生或死的问题
- 甚至他们是否具有这个技术呢?
道德规范
过剩的卖主
• 对于一个特定的目标,如果它已经在为一个卖主评估时,又出现
了另一个卖主要评估这个目标,那么该怎么办呢?
- 如果他们中的一个,或者是两个都是不公开的进行的,又该怎
么办呢?
• 对于一个特定的目标,如果它已经在为一个卖主不公开的评估完
成了,又出现了另一个卖主要评估这个目标,那么该怎么办呢?
- 先前的结果是否可以被重新使用呢?
- 先前的评估的不公开性必须得到保护吗?
是否较低的评估价钱就揭示了,已经不公开的进行过这样的评估了呢?
软件工程问题
我们不知道
VDA词典
每个人以自己的方式来定义基本的术语
所以我也是以自己的方式来定义基本的术
语的
主要的术语(1)
所有者
• 一个或者是多个人[拥有]这个系统。他们为安
全策略的设置负责,其中安全策略管理系统的
行为。并不必须得是[用户]。
对手
• 一个或者是多个人可以攻击系统,并且很乐意
被[看到]他们正在攻击系统。
攻击
• 对手的每一个[动作]都试图开发系统的缺陷。
主要的术语(2)
缺陷
• 对于现在的系统,必须纠正某些工程[错误]防
止它被开发出来。
安全策略
• 这些策略用来管理什么样的代理商,可以在什
么[目标]上,用什么[资格],进行什么[操作]。
攻击
• 系统里的,可以被敌手开发出来,从而违反系
统的安全策略的缺陷。
主要的术语(3)
入侵
• 一个成功的攻击,它的结果是危机到系统的安全,常
常是[完整性],[隐私性],或者是[ 可用性]的损失。
系统
• 一个技术单元是由功能性机构组成的。
通道
• 系统和它的外部世界进行通讯的任何一个通道,或者
是它众多的功能机构之间相互通讯的任何一个通道。
一个和安全相关的通道可以和一个或者是多个安全边
界交叉
主要的术语(4)
协议
• 这些规则用来管理在通道中传输的数据的形式
和说明
安全范围
• 安全策略和权限设置。改变其中任何一个都会
建立一个安全边界。
安全边界
• 从任何一个机器指令的观点来看,就是暂时的
最近的联合,过去和将来,转变为其他的安全
范围。
主要的术语(5)
权限
• 在某些〔目标〕上进行某些〔操作〕的权利。
权限设置
• 对某一权限进行的设置。
功能性机构
• 机器指令的暂时性邻接设置在一个单独的安全
范围内执行。
代理商
• 功能性机构是被证明了的为人而工作的。同一
个调频可以被多个代理商多次进行并行动作。
VDA 语义网
Adversary:对手
Owner:所有者
Privilege:权限
Attack:攻击
System:系统
Defect:缺陷
Channel:通道
Protocol:协议
Agent:代理商
Privilege Set:权限设置
Security Boundary:安全边界
Security Domain:安全范围
Security Policy:安全策略
Functional Mechanism:功能性
机构
新类型(1)
可靠的VDA需要一个新的“基础”
我们需要把我们所知道的所有的有关攻击的东西进行再编
制,从而支持软件工程
观点
• 攻击分析的中心的观念就是“攻击”
• 软件工程的中心的观念必须是“缺陷”
- 缺陷是攻击的工程个性的某种类型
- 缺陷是攻击到工程的发射
这样,在VDA所有的事情都必须涉及到“缺陷”的修正
新类型(2)
我们已经(浪费我们的时间?)建造了(建造失
败?)“攻击分类法?”
现在VDA需要的是“缺陷类型”
• 如果我们可以学到如何建造它们
我们正在试图通过设计一个所有涉及到工程缺陷
的全面的类型“族”来完成之一任务。
使用有效的XML进行描述
• 包括系谱相关的DTD
• 将会在这本“书”中论证
新类型(3)
美国电脑紧急应变团队(CERT)VDA类型族,包括以下
这些类型(迄今为止):
• 缺陷
• 缺陷-属性
• 缺陷-指示器
• 发现-技术
• 通道
• 工程-习惯用语
• 工程-样式
• 攻击(外部的与CVE相关)
• 设计 - 原则(或者是设计-妨碍)
缺陷
它描述每一个缺陷
与攻击相比,它具有很大的详细水平
• 一些缺陷可能会产生相同的攻击
它有13个外在的属性
它有1个内在的属性
• 它是一个真正的“缺陷-属性”的无序设置
• 它一起描述了缺陷的精确的本质
• 它是作为一个大的逻辑与(AND)的
- ORS是不允许的
- ORS是单独的缺陷
缺陷-属性
缺陷属性的例子:
•
- store(存储)
- (stack)堆栈-列-目标
- 多单元-列-操作
- 未经检查的-操作
- 输入-来源
- 对手-输入
- 清晰的-范围
逻辑与(AND)
• 它用于根据缺陷分类法动态的计算类似处
缺陷-指示器
缺陷指示器的例子:
•
- 分割-错误
- 总线-故障
- 变量-错误
- 不稳定的-行为
- 无限的-循环
逻辑或(OR)
• 这样,就不能被用作固有的属性了
发现-技术
缺陷发现技术的例子
•
-
-
-
-
-
-
通道
通道的例子
• 命令行
• 环境
• 继承的进程关联
- 文件/目录创建
默认通道控制
- 信号设置
- 程序优先权
- 资源限制
- 鉴定证书
- 当前工作目录
- 打开文件描述符
- 系统调用结果
- 插槽
- 管道
- 共享内存
- 信号
- 永久存储器
• 比如寄存器
- 文件存在
- 文件信息
• 系统I/O
工程-习惯用语
工程习惯用语的例子
• ANSI C没有原型
• ANSI C/ C++ 指针算法
• ANSI C/ C++ 在{堆栈,堆积,静态}存储器中的字符串
• ANSI C 有正负号/无正负号混合算法
• Java 并发没有保护的对象
• 土生的密码算法
• 公众可写的对象属性
• 对象存取器到专用属性的返回指针
• 除非管理者泄露整体资源分配
• C++对象使用专用成员指针和非默认的构造器
工程样式的例子
• 不完全的授权
攻击
例子:
• 缓冲区溢出
• 格式行
• cross-sight脚本
• SQL 注入
• 共享的可写目录TOCTOU race
设计-原则
我们将单独地讲述所有的设计原则
IA是艺术,而不是科学
请习惯于这一点
攻击分析社团已经非常清楚了这一点,
但是,软件工程社团还没有清楚这一点
明确的管理风险
风险是如下列出的某种功能:
• 事件的可能性
• 事件的结果(代价)
- 如果可能性约等于0,那么风险是可以的(OK)
- 如果结果(代价)约等于0,那么风险是可以的(OK)
- 其它情况下,就必须把风险降低
现实的敌手模型对下述列出的情况是必要的
• 要确定特定的风险
• 要模拟可能性和结果
首先要消除最高的风险
先前的经验的逻辑结果
• 一旦确定并且量化了风险后,只有当把
它们从最高到最低的风险处理时,才是
敏感的
这就是“最薄弱的链接”思想
深入的实行防御
当设计系统特征时,而又必须包含一个攻
击特征时
• 包括潜在的多余的特征,它们会减少攻击特征
的范围,性能,持续时间等其它方面
• 这是一般的攻击分析和系统管理思想
• 它并不是一般的软件工程思想
- 只有容错社团曾经这样想过
审计所有的通道
在你的系统上,通道是攻击唯一的通路
• 完全的保护这些通道,那样你的系统将会
受到完全的保护
假设你的敌手可以协调的操作你所有的通道
将你的系统的通道最小化,从而将攻击
的通路也降到最低
保证完全
你的系统必须总是处在一种安全的状态下
每一个潜在的不安全的转变都必须检测其安全性
任何一个安全丧失的证据都意味着系统的完
全性的丧失
如果安全不能够得到保证或者是不能够被完
全的恢复,那么,系统必须自行终止
甚至以可用性为代价
• 由定义,一个可用的危及安全的系统比一个不可用的
系统更糟糕
攻击/侵扰的工程师
当设计系统时,一定要包括可以对假
定的攻击和侵扰进行断定的真实的仪器
仪器应该
• 安全的记录潜在的攻击和侵扰信息
• 不将自己暴露给敌手
• 不向系统添加攻击
使用最小的权限
为你的系统授予它可以进行操作所能使用
的最小的权限
在任何一个给定点处获得和丢弃权限,系统
只具有完成它正忙于的任务的权限
用户权限的分离
如果你的系统需要在不同的时间具有不
同的权限,那么,就可以考虑将系统分割
成几个清楚的互相联系的子系统,每个子
系统具有一个适当的最小权限设置
请记得通道将会增加攻击的新的通路
在最小通道和权限分割上需要一个适
当的平衡
使用最小功能性
使你的系统包括它所需要的最小的功能性
附加功能,甚至是睡眠状态,都代表着附加的攻击
• 可能是由于代码的增加的行数
• 可能是由于里面包含的攻击
• 可能是由于无意识代码的路径
• 可能是由于激活无意识功能的方式
主动的限制一个过度的功能性子系统的功能,可
能会非常的昂贵并且还可能会导致错误的发生
调停所有的操作
调停(提出)在所有的对象上的所有的操作
即使是没有明显的敏感数据的操作
潜在的将来的再次使用需要它
对于透明的调停可以使用“把柄”
一定不要为对象内部的返回实指针
一定不要相信回叫功能或者是对象
使用行人愉快的界面
用户具有足够的创造性来规避令人讨
厌的界面
如果界面必须是限制性的,那么,它
们必须得是完美的限制,而不是只是令人
气馁的限制
穿过界面的自动化的攻击可能会战胜许
多明显的限制
使用多重正交鉴定证书
使你的系统需要双因素鉴定
• 有些是你有的
• 有些是你知道的
两个相互独立的鉴定因素两个相互独立的鉴定因素
应该按照重要度来排序,而回避这些会更加困难。
使用实际的鉴定时一定要非常小心
• 生物测定学(Biometric)
• GPS
• 直接的实际地址
只从安全得到保证的通道输入
使得系统只从已经进行过完全的鉴定的通道
输入
许多通道是可以信任的,并且它的鉴定是不
可能的,所以小心以下几点
• 信号
• 被装载器映射的共享的库
• 系统的调用
如果你的系统真的是敏感的,那么,需要重
新鉴定而不是为了鉴定而接受环境的命令
只从安全得到保证的通道输出
使得系统只从已经进行过完全的鉴定
的通道输出
让系统从没有经过鉴定的通道输出,
不管输出是什么,实际上,就是一种对保
密性的侵害
保证微观操作
当一系列的操作不能被中断时,就确保它们不会被中断
使用任何的需要的“设备”来确保这一点
• 操作的不同的顺序
• 用具有相同的结果但是却没有(或者是较少的)次序要求的操
作来代替
• 互斥体,旗语,以及其它的同时控制设备
• 分布式的事物处理服务程序
当没有其它的可能时,就减少序列
将秘密安全的存储
将秘密安全的存储几乎是不可能的
如果根本不可能,那么就要避免存储它们
如果你必须存储它们,为了这个目的,可
以使用“设备”设计和检验
• 密钥环 (keyring)
• 智能卡 (smartcard)
• 强大的编密码
使用默认的拒绝
将你的系统设计成,可以根据所知道的什么
是安全和正确的,来有选择性的允许{操作,输
入}
否认所有其它的
一定不要试图将坏的东西“过滤”掉
• 今天是坏的东西明天就不一定还是坏的
仅仅重新使用保证代码
请一定要非常小心地重新使用代码
你可以重新使用下述的代码:
• 你为相同安全水平所编写的代码
• 你已经为相同的安全水平进行了完全的
再检查的代码
• 你所信任的人所写的代码,其中,这个
代码和你需要的代码具有相同的安全水
平
跨边界委托要非常小心
如果你的系统必须得将某些操作委托给其它的系统,那么请留意
以下几点:
• 用较高的权限委托其它的系统
• 用更严格的安全策略委托其它的系统
- 它们比你的系统具有更高的敏感度,所以它们很可
能会自我保护的非常好
• 避免使用较低的权限或者是松的安全策略委托系统
- 它们将不太可能会以你所希望的你的数据的处理方式,来处理
任何输入/输出
- 如果你必须得委托给这样一个系统,那么,一定要确保以合适
的方式处理好通往/来自那个系统的通道
- 尤其适用于没有安全边界的系统
只使用私人存储区
对于那些其他人也可以从中读取数据的持久的存储
区,永远都不要写入任何东西
• 这就减少了敏感数据泄露的可能性
对于那些其他人也可以从中写入数据的持久的存储
区,永远都不要读取任何东西
• 这就减少了你的系统的“内部的”持久的存储数据的
破
坏的可能性
这些工作并不适用
• 其它系统的许多攻击可能会允许你的持久存储是坏的,
这样,你仍旧需要假定你自己的先前的存储数据可能
是坏的
使用密码系统
对于所有的敏感数据,只将它们以加
密的形式永久的存储
不管你认为存储箱多么的安全,在某
些情况下,它都不是有那么安全的
你只能通过存储箱的自我保护来保护
存储箱中的数据;存储箱是不可靠的
正确的使用密码系统
如果你的系统需要密码包括,那么,请正确的使用它:
• 在任何时候,永远都不要发明你自己的算法
- 即使你是一个数学家,你都不知道你在作什么
– 但是它们更知道
• 在任何时候,永远都不要执行一个已知的算法
-即使你是一个熟练的程序员,你都不知道你在作什么
– 不幸的是,它们也并不知道
• 永远都要使用公认的,被广泛使用的代码
- 它可能已经被彻底的检验过
- 如果还没有,那么它将会被彻底的检验
并且,你将从中受益匪浅
检验变量约束
始终检验标量变量约束
始终使用标量变量约束
• 如果你的系统需要约束,使用它们如下
- 列的脚注为最大的有益的原因
- 指针的算法基本上是相同的情形
使用“标准的”机构
使用那些可以用于解决标准问题的标准的机构
• 使用“标准的”语言的机构
• 使用“标准的”操作系统机构
• 让内核完成它的工作;而不要扮演内核的角色
通常,这些机构都写的很好
总之,最终你的系统取决于它们
• 即使你规避它们,你依赖的东西还是使用它们的
• 你不能够自己写所有的东西
构造“契约性的”界面
虔诚的使用Meyer型的契约界面
始终使用预处理
• 并且永远都不要使它们无效
在不变式有意义的地方,就尝试使用不变式
在可以以合适的成本执行后处理的地方,就
尝试使用后处理
• 只有当进行后处理的成本真的成为一个被批评
的对象时,才可以不进行后处理
初始化所有的变量
一定要保证所有的变量都被明确的初始化,这样
• 你的系统的动作是可预测的(正确的或者是错误的)
• 你的系统不会泄露未被初始化的数据
除非语言规范保证初始化,而不是系统,那么初始化以下内容:
• 局部自动(堆栈)变量
• 全局静态变量
• 动态(堆或存储池)变量
• “初始化”并不意味着隐式构造程序的调用
至少要把他们赋值为0,但是最好把它们初始化为一个有意义的值
清除不相关的内存
当内存不再使用时,经常应该清除它们
• 尤其是当它包含敏感信息的时候
这一点并不容易做到,因为大部分的语言没有完全支持这一功能
• C++类的语言能够大大的帮助清除内存
- 在内存释放之前清除它们
- 一定要非常确定,什么时候它们是分配给你运行的
• 隐式内存语言会将这一点变得十分困难
- “解决问题”通常已经被认为足够好了
– 内存在解决问题之前,将不会被再次使用
– 但是仍旧可能被其它的缺陷泄露
• 密切注意
--Away
选择适当的语言
了解许多关于不同语言的知识
请一定不要让学习曲线限制住
• 对于一个好的程序员而言,学习语言是一件微
不足道的事情
- 我在两个星期内就学会了PL/1;在四个星
期内学会了Ada95
根据语言能够做什么来选择它,而不是根据
谁了解它们或者是谁喜欢(讨厌)它们确保这个
语言最理想的满足你的需求
确保所有的代码可再入
实现所有的代码都是可再入的代码
因为
• 这样通常会产生更安全的代码
• - 使用静态内存的代码趋向于以一种非直观的方式表
现
• 它们通常在有线程的环境里工作的更好
• 保证线程安全肯定会容易一点
• - 甚至是热线程
当在线程环境里使用了不可再入的代码,会发生很奇
怪的事情
正确进行整数运算
在算术表达式中不要混合使用有符号和无符号的变量
• 如果你这样做了,不要抑制符号的溢出/下溢
- 宁愿引起一个错误,也不要一个错误的结果
更一般的讲,一定要正确的进行所有的整数运算
• 同样,一定不要抑制符号的溢出/下溢条件
使用知道怎么可以探测到这样的错误的语言
• 所知道的更高类型的语言,如Ada95
• 所知道的更适度的语言,如C++
使执行环境生效
是所有你需要的东西在你使用之前生效
越早生效就越好
• 文件描述符的数量
• RAM的数量
• 其它的“处理限制”
• Umask(为掩码)
• 环境变量
• 硬盘空间
• 静态的对动态的资源
在TOCTOU race中频繁的结果
• 当时,这总比什么也没有要好
抑制调试援助
尤其是抑制任何的调试“输入”
• 调试输入是许多的攻击的原因
同样也要抑制调试输出
• 经常泄露敏感信息
非常高质量的工程需要与高质量相关的仪器
• 普通的质量评估仪器同样必须被禁止
• 如果你必须得留下质量评估仪器,一定要仔细
的再检查每一个有效的仪器
使用安全相关的语言功能
一旦你选择了合适的语言,那么就恰当的使用它
一些例子:
• 除非能够免费得到处理器
• 在c++对象中没有私有指针
• 永远不要在c++中使用转型(cast)运算符
• 在非序列化的类别上抑制序列号
• 在java中使用暂时的关键字来保护变量
• 使用ANSI C 原型
• 在Ada95中使用极大限度变量
• 在PERL中使用strict(严格)和warnings(警告)
• 一定不要在Java中使用内部类(至少为了安全)
完全的假定同时发生的敌手
假定你的敌手具有精确的,可以预测环境的
所有的方面的控制
从统计学上讲,这一点将是正确的;所有它
们需要作的知识重复的试
即使为了一个指令也永远都不要接受界面缺陷
• 界面缺陷是最难被发现的执行缺陷
• 指令检测测试几乎永远都不能检测到它们
结束
联系信息