“混沌”和“工程”这两个词一般不会放在一起;毕竟,好的工程师会把混沌拒之门外。但是,最近的软件开发者在给自己的环境里增加一些适量的“混沌”,来通过发现隐藏的漏洞加强他们的计算机系统。结果来看并不完美——任何混沌的东西都没法给出保障,但是使用的技术却非常有效,至少有些时候,使用他们是值得的。
这对安全分析师来说会非常有用,因为他们的工作就是去发现未被记录或者意料之外的后门。混沌测试无法识别所有安全问题,但是它能发现一些危险的、未修复的漏洞,并且往往都是开发者意想不到的。好的混沌工程能够同时帮助DevSecOps团队和DevOps团队,因为有时候可靠性和弹性的问题同样会成为安全隐患。这类代码错误通常会使系统崩溃,或者导致入侵。
何为混沌工程?
“混沌工程”是一个新词,意为将多种有一定成功结果的不同技术统一到一起。有些人会用“模糊”或者“故障”之类的词,来描述他们如何扭曲计算系统,甚至有时候使其无法自我平衡并崩溃。他们会注入一些可能会让软件失控的 随机行为,然后仔细观察失控的过程,或者出现的异常。这些错误模式如果在正常使用过程中,往往需要数年才可能出现。
电子自由基金会(Electronic Freedom Foundation, EFF)的创始人之一,以及数个关键开源项目的开发团队成员,John Gilmore表示,编程是一个持续改进的过程,而混沌测试是一种能加速搜索所有可能执行路径的方式:“使用时间长的代码的真正价值在于,大部分的漏洞在前1,000万个使用者、前20个进行编译的编译器、前5个运行的操作系统中,就会被发现了。那些通过模糊测试和渗透测试的代码,会比新代码少许多未被发现的代码路径。”
Gilmore喜欢讲一个在70年代他在Data General工作的故事。他发现按电源开关随机次数可能会导致操作系统状态混乱。“比起修复这个问题,操作系统工程师表示按开关并不是一个真正的测试。”Gilmore说到,同时还不忘加了一句,“所以,Data General倒闭了。”
这个概念对计算机制造或者其他工程领域而言并不陌生。比如汽车制造商,会在夏天的沙漠里或者在冬天的北方地区测试新的车型。建筑师会建造测试结构,并且通过过载测试发现问题。
计算机科学是一个相对偏向数学的领域。许多安全研究人员会对各种数学可能性构建逻辑证明。但是,现代软件的复杂性,远比我们现有的逻辑工具模型庞大得多。大部分计算安全领域还远远无法实现我们理解需要的精确性,这个时候随机行为就有了登场的机会。
这个名字避免了“科学”这个说法,以及所有通过仔细建立模型和测试来最终实现理解世界的传统模式。甚至使用“工程”这个词都不公平,因为工程一般都是经过严格计划和有法可循的,就像在科学实验室里一样。混沌工程更像是在一家瓷器店释放了一头公牛,或者在一个高中食堂释放了一头肥胖的猪。
混沌工程技术
混沌工程师使用的技术简单到发指,但是又同时需要高超的技巧。这些技术涉及扭曲、改变软件普通状态下的保护模式,会颠覆许多程序员认为理所当然的服务内容。比如在某个简单的测试中,只是单纯地删除互联网连接上一半的数据包;另一个例子可能会直接吞掉几乎所有的空闲内存,从而让软件不得不想办法抢夺资源存储数据。
这些测试也会在一些更高级别进行。DevSecOps团队可能会关闭一些下属服务器,看一下服务器集群弹性是否足够支撑错误的产生。其他测试可能会额外增加一些延迟,测试延迟是否会产生雪球效应,最终导致系统崩溃。
几乎所有像RAM、硬盘空间、或者数据库连接这类资源都是试验的好对象。有些测试会干脆将资源全部切断,其他的可能只是严格限制资源,看一下软件在被操作空间被挤压的时候如何表现。
安全问题总是间接地被发现。以缓冲区溢出问题为例,只要在一个通道(channel)里注入大量字节,就能很容易被混沌工具发现。工具本身可能未必会破坏软件,但是它们会显示其他人可能会从哪些地方通过缓冲区溢出注入恶意代码。
模糊测试也同样用于检测句法逻辑错误。一些程序员会忽视参数的各种不同配置情况,从而留下一些潜在的后门。对软件用各种随机和半结构化的输入进行“轰炸”能够在攻击者发现它们之前,触发这些错误模式。
这一领域还能变得更为复杂。一些研究人员不满足于完全随机的注入,就构建了复杂的模糊测试工具,能够通过对软件的了解用“白盒”分析的方式引导流程。一种称为语法模糊的技术从定义期望的数据结构开始,然后用这种语法生成测试数据,再修改定义,以发现句法错误。更深入的策略能够系统性地尝试识别代码中所有可能的执行路径。微软就自己创建了名为SAGE的工具,可以通过分析潜在的分支并创建输入对所有分支进行测试,来标记潜在的错误。
对于混沌工程师而言,挑战在于检测到的问题往往在极端情况下才会出现。尽管说中断情况的总数很容易就能发现,那种能引起细微安全问题的不起眼的错误往往更难察觉。许多被发现的问题可能不会引起失陷或者数据的泄露,但是他们依然显示了一些需要解决和修复的问题。
混沌工程工具
这一领域正在从聪明的DevSecOps团队悄悄进行的情况,快速地成为开发周期中普遍的一部分。工具开始成为工程师的一些小项目和研究手段,而现在已经成长为许多CI/CD管道中受信赖的一部分。许多这类工具都是由其他DevSecOps专家制造,并且开源化地公开分享。其他一些表格也开始受到商业的吸引。一些专注于提供相关工具的公司也在快速打开市场。
一些工具也是被设计用于软件堆栈的更深层。比如ChaosMachine,这个研究工具由瑞典皇家理工学院开发,将异常注入运行在Java虚拟机上的代码中,用于测试代码之中处理错误的机制。
一般每种语言或者每个平台都有十几种特定的优秀混沌工程工具。比如Pythonfuzz,就会反复用随机数据调用函数,同时观察是否存在内存泄露、死锁或者其他问题。谷歌的OSS-Fuzz会和多种语言与项目协同,被企业用于测试像Chrome扩展之类的开源生态系统。
其他工具会专注于特定平台。Netflix是这个领域的先锋,为自身的基础设施创建了一系列重度依赖AWS的测试工具。其中一个最早期的工具Chaos Monkey,会随机进入机器的节点,然后关闭一部分,观察某个实例的完全下线是否会引起问题。Netflix编写了一个类似的工具,称为Simian Army。它包括了Latency Monkey、Gorilla和Chaos Kong,可以降低网速,甚至直接关闭整个机群。
一些项目是用于跨多平台分享思路和代码的。一个名为Litmus的开源项目针对所有主流的云,以及本地部署的机器。Litmus平台支持能够以不同云为目标的“混沌试验”。它的ChaosEngine进行试验并追踪结果。
许多工具用于打破团队边界,将早期阶段测试代码的开发者和管理CI/CD管道的DevOps团队联结,观察生产运作中的软件的情况。比如ChaosToolkit,就是一个开源项目,能和各种已经建成的管道集成,为新代码加入更多复杂和混乱的挑战。它同时基于大量的驱动工具和插件,从而能够在许多不同的云环境和本地安装环境下运作。
软件开放工具供应商Cavisson有一种叫做“NetHavoc”的产品,能够注入名为“havocs”的错误,从而使包括安全漏洞在内的软件问题暴露。一种havoc可以破坏数据包,并且扭曲DNS结果;其他的havoc可以枯竭内存或者硬盘空间。
“你可以崩溃一个服务器、终结一个实例,还能移动到消息队列的任意位置并且改变消息。”Cavisson的产品经理Mrigank Mishra解释,“最终,它会精简到组织真正想要查找到的用例上。”
一些工具会更深入,因为代码中的问题在输入和预期远远不同时才发生。比如Cryptofuzz,就直接作用于负责SSL连接加密的密码库。它会寻找像崩溃、内存泄露、缓冲区溢出和未初始化变量之类的安全问题。
持续扩展的混沌工程
混沌工程领域依然在发展。许多开源资源的选项依然在扩展,每一个新版本都有提升。一些公司开始将混沌工具的选项集成到他们的开发工具、测试组合和安全审计中。这块领域并非是一个可以真正定义的领域——实际上,它只是一系列在错误的时间做错误的事情的技术。
从表面来看,混沌工程很容易,不过是反复开关和扭曲数据直到某些东西出问题。但是,真正展现技术的地方是准确找到需要捣鼓的地方,开始制造噪音。混沌工程师并不是那些恶毒的混蛋或者恶意的捣蛋者。他们一般都会被别人无视,或者出现在警察局的门口,但是他们发现阿喀琉斯之踵的能力,会需要他们那种厌世的态度,来削弱甚至消除开发者刚写代码时的一些预设条件。如果一些无伤大雅的坏行为可以在代码进入生产前就暴露出问题,那人人都是大赢家。
尽管说混沌工程在测试软件质量上已经有一定效果,但是从国内来看,混沌工程用于安全测试还很少。混沌测试需要依赖优秀的测试人员,能够通过意料不到的角度进行测试,诱发潜在的安全问题。虽然混沌工程存在着很大的随机性,但是不代表混沌工程完全就是毫无章法地摆弄测试对象,有目标地进行随机测试,才能够使混沌工程事半功倍。
参考阅读