如何在Ruby中进行防御性编程?
下面是一个完美的问题示例: **原始问题:** 作为一名安全专业人士,我关心的一件事是Ruby没有Java的包隐私。也就是说,这不是有效的Ruby:如何在Ruby中进行防御性编程?,ruby,security,defensive-programming,Ruby,Security,Defensive Programming,下面是一个完美的问题示例: **原始问题:** 作为一名安全专业人士,我关心的一件事是Ruby没有Java的包隐私。也就是说,这不是有效的Ruby: public module Foo public module Bar # factory method for new Bar implementations def self.new(...) SimpleBarImplementation.new(...) end def baz r
public module Foo
public module Bar
# factory method for new Bar implementations
def self.new(...)
SimpleBarImplementation.new(...)
end
def baz
raise NotImplementedError.new('Implementing Classes MUST redefine #baz')
end
end
private class SimpleBarImplementation
include Bar
def baz
...
end
end
end
能够防止Foo::BarImpl的猴子补丁真是太好了。这样,依赖图书馆的人就知道没有人把它弄糟了。想象一下,如果有人在你身上改变了MD5或SHA1的实现!我可以对这些类调用freeze
,但我必须逐个类地调用,如果我对加载顺序不太谨慎,其他脚本可能会在我完成应用程序安全保护之前修改它们
Java为防御性编程提供了许多其他工具,其中许多在Ruby中是不可能的。(见乔什·布洛赫的书中的一个好的列表)这真的是一个问题吗?我是否应该停止抱怨,用Ruby做轻量级的东西,而不要指望“企业级”的解决方案
(不,Ruby中的核心类在默认情况下不会冻结。请参见下面的:)
我想Ruby有一个更重要的特性,这是一个安全问题。也要打字。
例如,我可以将自己的方法添加到Ruby String类中,而不是扩展或包装它。我不认为这是一个问题 是的,虚构的“某人”可以用不安全的东西取代MD5的实现。但是为了做到这一点,虚构的某人必须能够将他的代码放入Ruby进程中。如果他能做到这一点,那么他可能还可以将代码注入Java进程,例如重写MD5操作的字节码。或者只是截取按键,而根本不去摆弄密码 其中一个典型的担忧是:我正在编写这个很棒的库,它应该这样使用:
require 'awesome'
# Do something awesome.
但是如果有人这样使用它呢:
require 'evil_cracker_lib_from_russian_pr0n_site'
# Overrides crypto functions and sends all data to mafia
require 'awesome'
# Now everything is insecure because awesome lib uses
# cracker lib instead of builtin
简单的解决办法是:不要这样做!教育您的用户不要在其安全关键型应用程序中运行从不明来源下载的不受信任代码。如果他们这样做了,他们可能就活该
回到您的Java示例:的确,在Java中,您可以将加密代码设置为私有的
和最终的
等等。但是,仍有人可以替换您的加密实现!事实上,确实有人这样做了:许多开源Java实现都使用OpenSSL来实现其加密例程。而且,正如您可能知道的,Debian多年来一直附带着一个破损的、不安全的OpenSSL版本。所以,在过去的几年里,所有在Debian上运行的Java程序实际上都使用了不安全的加密
Java为防御性编程提供了许多其他工具
起初我以为你说的是,
其中的思想是保护程序(或其子集,或单个函数)不受无效数据输入的影响。这是一件很棒的事情,我鼓励大家去读那篇文章 然而,看起来您实际上是在谈论“从其他程序员那里保护您的代码” 在我看来,这是一个完全没有意义的目标,因为无论你做什么,恶意程序员总是可以在调试器下运行你的程序,或者使用或任何其他技术 如果你只是想保护你的代码免受不称职的同事的攻击,这是荒谬的教育你的同事,或者让他们成为更好的同事。 无论如何,如果您非常关心这些事情,那么ruby不是适合您的编程语言。Monkeypatching是有设计的,不允许它违背了该功能的全部要点。“教育你的同事,或者让更好的同事”对一家小型软件初创公司非常有效,对谷歌和亚马逊这样的巨头也非常有效。想到每一个卑微的开发者都签约在一个小城市的医生办公室里开发一些小型的医疗图表应用程序,真是可笑 我并不是说我们应该为最小的公分母构建,但我们必须现实一点,有很多平庸的程序员,他们会利用任何完成任务的库,而不考虑安全性。他们怎么会注意安全呢?也许他们学习了算法和数据结构课程。也许他们上了编译器课程。他们几乎肯定没有上加密协议课。他们肯定没有读过Schneier或其他任何人,他们实际上不得不恳求甚至恳求非常优秀的程序员在构建软件时考虑安全性。 我不担心这个:
require 'evil_cracker_lib_from_russian_pr0n_site'
require 'awesome'
我担心awesome
需要foobar
和fazbot
,而且foobar
需要有魄力,而且。。。最终,其中两个冲突以某种模糊的方式破坏了一个重要的安全方面
一个重要的安全原则是“纵深防御”——增加这些额外的安全层可以帮助你避免意外地射中自己的脚。他们不能完全阻止它;什么都不能。但是他们很有帮助。请看加里·多利的报道
您可以阻止对单个方法的重新定义。如果您关心猴子补丁,您可以使用不可变模块(或类似功能之一)
您可以看看Lucky Stiff的“沙盒”项目的原因,如果您担心可能会运行不安全的代码,可以使用该项目。
例如(在线TictaToe):
如果有人对某个对象或模块进行了修补,那么您需要看两种情况:他添加了一种新方法。如果他是唯一一个添加这个meyhod的人(很可能),那么就不会出现问题。如果他不是唯一的一个,那么您需要查看这两种方法是否相同,并告诉库开发人员这个严重的问题
如果他们改变了一种方法,你应该开始研究改变方法的原因。是吗
require 'evil_cracker_lib_from_russian_pr0n_site'
require 'awesome'
class Module
def anonymous_module(&block)
self.send :include, Module.new(&block)
end
end
class Acronym
anonymous_module do
fu = lambda { 'fu' }
bar = lambda { 'bar' }
define_method :fubar do
fu.call + bar.call
end
end
end