首页 / 知识

关于安全性:如何在Ruby中进行防御性编程?

2023-04-13 11:54:00

关于安全性:如何在Ruby中进行防御性编程?

How can I program defensively in Ruby?

这是一个完美的例子:分类器gem破坏了Rails。

**原始问题:**

作为安全专家,我担心的一件事是Ruby没有Java的package-privacy的并行性。也就是说,这不是有效的Ruby:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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中是不可能的。 (请参阅乔什·布洛赫(Josh Bloch)的书,以获得一个不错的清单。)这真的有问题吗?我应该停止抱怨并且将Ruby用于轻量级产品,而不希望有"企业就绪"解决方案吗?

(不,默认情况下,Ruby中不冻结核心类。请参见下文:)

1
2
3
4
require 'md5'
# => true
MD5.frozen?
# => false

我不认为这是一个问题。

是的,神话般的"某人"可以用不安全的东西代替MD5的实现。但是为了做到这一点,神话般的人实际上必须能够将其代码带入Ruby进程。如果他能做到这一点,那么他大概也可以将其代码注入Java进程中,例如重写MD5操作的字节码。或者只是截获按键,而根本不用去理会加密代码。

一个典型的问题是:我正在编写这个很棒的库,应该这样使用:

1
2
require 'awesome'
# Do something awesome.

但是如果有人这样使用它,怎么办:

1
2
3
4
5
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中,您可以将密码设置为privatefinal,而不能。但是,仍然有人可以替换您的加密实现!实际上,实际上有人这样做:许多开源Java实现都使用OpenSSL来实现其加密例程。而且,您可能已经知道,Debian多年来发行了一个损坏的,不安全的OpenSSL版本。因此,过去几年在Debian上运行的所有Java程序实际上都使用不安全的密码运行!


Java provides lots of other tools for defensive programming

最初,我以为您是在谈论普通的防御性编程,
其中的想法是保护程序(或其子集或单个功能)免受无效数据输入的侵害。
那是一件很棒的事情,我鼓励大家阅读该文章。

但是,看来您实际上是在谈论"保护其他程序员的代码。"

我认为这是一个完全没有意义的目标,因为无论您做什么,恶意程序员始终可以在调试器下运行程序,或者使用dll注入或许多其他技术。

如果您只是想保护自己的代码免受不称职的同事的注意,这是荒谬的。教育您的同事,或获得更好的同事。

无论如何,如果您非常关心此类事情,那么ruby不是适合您的编程语言。 Monkeypatching是根据设计而存在的,并且不允许它与功能的整个要点相提并论。


Raganwald最近有关于此的帖子。最后,他构建了以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

这会将fubar公开为Acronym上的公共方法,但将内部胆量(fubar)保留为私有,并从外部视图隐藏帮助程序模块。


您可以看看"为什么幸运符"的"沙盒"项目,如果您担心潜在地运行不安全的代码,可以使用该项目。
http://code.whytheluckystiff.net/sandbox/

示例(在线TicTacToe):
http://www.elctech.com/blog/safely-exposed-your-app-to-a-ruby-sandbox


如果您喜欢猴子修补,则可以使用Immutable模块(或类似功能之一)。

不可变


查看Garry Dolley的不可变的作品。

您可以防止重新定义各个方法。


"教育您的同事,或者变得更好的同事"对于小型软件初创公司非常有用,对于Google和Amazon这样的大手笔也非常有用。认为每个低收入的开发人员都在一个小城市的医生办公室签约了一些小型医疗图表应用程序,这是荒谬的。

我并不是说我们应该为最低的公分制而开发,但是我们必须现实的是,那里有许多中等水平的程序员会引进任何可以完成工作的库,而不会关注安全性。他们如何注意安全性?也许上了算法和数据结构课。也许他们上了编译器课程。他们几乎可以肯定没有参加加密协议类。他们肯定还没有读过Schneier或其他任何人,他们几乎不得不恳求甚至非常优秀的程序员在构建软件时也要考虑安全性。

我对此并不担心:

1
2
require 'evil_cracker_lib_from_russian_pr0n_site'
require 'awesome'

我担心awesome要求foobarfazbot,并且foobar要求has_gumption,并且...最终,其中两个冲突以某种模糊的方式消除了重要的安全性方面。

一项重要的安全原则是"纵深防御"-添加这些额外的安全层可以帮助您避免意外地用脚砸自己。他们无法完全防止这种情况;没有办法。但是他们有帮助。


我想Ruby拥有一个功能-重视它是一个安全问题。小鸭也一样。
例如。我可以将自己的方法添加到Ruby String类中,而不是扩展或包装它。


如果有人用猴子修补了对象或模块,则需要查看2种情况:他添加了一个新方法。如果他是唯一添加此方法的人(很有可能),则不会出现任何问题。如果他不是唯一的一个,则需要查看两种方法是否都相同,并将这个严重的问题告诉库开发人员。

如果他们更改了方法,则应该开始研究更改方法的原因。他们是由于某些极端情况而改变了它,还是实际上修复了错误?特别是在后一种情况下,monkeypatch是一件很重要的事情,因为它在许多地方修复了一个错误。

此外,您正在使用一种非常动态的语言,并假定程序员以理智的方式使用此自由。消除此假设的唯一方法是不使用动态语言。


编程安全性分类器并行性

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢