我知道目前正在为美国军方项目工作的人(安全级别低,非战斗人力资源类型数据)。
已提交了项目代码的初始状态交给军方进行审查,然后他们通过某种安全分析器工具运行该程序。它返回了代码中已知安全问题的报告,并要求进行了最终产品交付之前需要实施的更改。
需要解决的项目之一是删除项目的一部分是用Ruby编写的,因为它是一种动态语言。
不允许在安全设置中使用动态语言的背景/原因是什么?这是政府采用新技术的速度缓慢吗?还是与静态语言(ala C ++或Java)相比,动态语言会带来额外的安全风险?
#1 楼
在动态语言中可以完成许多“整洁”的事情,这些事情可以隐藏在代码的某些部分中,这些部分对于另一个程序员或审计人员而言,对于给定代码段的功能而言,并不是立即显而易见的。 />在irb(交互式红宝石外壳程序)中考虑此序列:这失败了。然后,我打开String类并定义方法foo
或return foo
,然后调用它。 这被称为开放类,每当我想到用红宝石编写具有任何安全性或完整性的代码时,都会感到恶心。当然,它可以使您快速地完成一些整洁的事情……但是我可以做到,这样每当有人存储一个字符串时,它就会将其存储到文件中,或者通过网络发送。重新定义String的这一点可以放在代码中的任何地方。
许多其他动态语言也可以完成类似的工作。 Perl具有Tie :: Scalar,可以在幕后改变给定标量的工作方式(这更加明显,并且需要您可以看到的特定命令,但是从其他地方传入的标量可能是一个问题)。如果您可以访问Perl Cookbook,请查阅13.15节-使用领带创建魔术变量。
由于这些因素(以及其他一些经常是动态语言的一部分),许多静态分析安全性的方法代码不起作用。 Perl和Undecidability证明了这种情况,甚至指出了语法高亮这样的琐碎问题(
"foobar!"
带来了挑战,因为whatever / 25 ; # / ; die "this dies!";
可以定义为在运行时接受参数或不接受参数,从而完全击败了语法高亮器或静态分析器)。Ruby可以访问定义了闭包的环境,这在Ruby中变得更加有趣(请参阅Joshua Ballanco的YouTube:RubyConf 2011中的Ruby合理化)。我从MouseTheLuckyDog的Ars Technica评论中获悉了此视频。
考虑以下代码:
whatever
此代码是完全可见的,但是
def mal(&block)
puts ">:)"
block.call
t = block.binding.eval('(self.methods - Object.methods).sample')
block.binding.eval <<-END
def #{t.to_s}
raise 'MWHWAHAW!'
end
END
end
class Foo
def bar
puts "bar"
end
def qux
mal do
puts "qux"
end
end
end
f = Foo.new
f.bar
f.qux
f.bar
f.qux
方法可以在其他位置...并且对于开放类,当然可以在其他位置重新定义。运行此代码:
irb(main):001:0> "bar".foo
NoMethodError: undefined method `foo' for "bar":String
from (irb):1
from /usr/bin/irb:12:in `<main>'
irb(main):002:0> class String
irb(main):003:1> def foo
irb(main):004:2> "foobar!"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> "bar".foo
=> "foobar!"
在此代码中,闭包能够访问该范围内该类中定义的所有方法和其他绑定。它选择了一个随机方法并重新定义它以引发异常。 (请参阅Ruby中的Binding类以了解此对象可以访问的内容)。
变量,方法,self的值以及可能在其中访问的迭代器块
表示该变量的重新定义的简短版本:
mal
运行时会产生以下情况:
~/$ ruby foo.rb bar >:) qux bar b.rb:20:in `qux': MWHWAHAW! (RuntimeError) from b.rb:30:in `' ~/$ ruby foo.rb bar >:) qux b.rb:20:in `bar': MWHWAHAW! (RuntimeError) from b.rb:29:in `'
这不仅仅是我上面提到的使静态的开放类分析不可能。上面展示的是,一个传递给其他地方的闭包带有它在其中定义的完整环境。这被称为一流环境(就像您可以传递函数一样,它们是一流函数,这是环境以及当时所有可用的绑定)。可以重新定义在闭包范围内定义的任何变量。
是好是坏,抱怨或不抱怨红宝石(在某些情况下人们希望能够获得一种方法的环境(请参阅Perl中的Safe)),“为什么将红宝石限制在政府项目中? “确实在上面链接的视频中得到了回答。
鉴于:
Ruby允许人们从任何闭包中提取环境
Ruby捕获了所有内容闭包范围内的绑定
Ruby将所有绑定保持为活动且可变的
Ruby有了新的绑定,从而对旧绑定进行了阴影(而不是克隆环境或禁止重新绑定)这四个设计选择的含义,就不可能知道任何代码的用途。
有关此内容的更多信息,请参见Abstract Heresies博客。特别的帖子是关于Scheme的辩论。 (与SO相关:Scheme为什么不支持一流的环境?)
随着时间的流逝,我逐渐意识到,一流的环境存在更多的困难和更少的功能比我原先想的要多在这一点上,我相信一流的环境充其量是无用的,而最坏的情况则是危险的。
我希望本节介绍一流环境的危险方面以及为什么会提出这个问题从提供的解决方案中删除Ruby。不仅Ruby是一种动态语言(如其他提及,答案,其他项目中允许使用其他动态语言),而且还有一些特定的问题使某些动态语言更加难以推理。
评论
我不明白这一点。您提到了一个Perl类,该类允许更改标量的行为。但是,Perl被广泛使用,包括在安全环境中。仅在语言中具有这些功能并不意味着该语言无法使用。在特定的Ruby情况下,目标环境可能不支持Ruby。就个人而言,我从来没有见过可以在任何系统上使用Ruby,并且甚至不确定它是否在任何认可的软件列表中。
–托马斯·欧文斯♦
13年7月30日在17:28
@ThomasOwens-我对这个答案的理解是,关键是“许多对代码中的安全性进行静态分析的方法都行不通”,因此被拒绝了,因为无法对其进行分析(至少是该小组)。我不知道是对的是正确的解释,还是拒绝它的正当理由,我不知道。
–鲍勃森
13年7月30日在17:33
由于缺少批准的软件列表上的信息,我只能猜测动态语言存在的困难。但是,我已经看到金融软件存在类似问题,并且支付卡行业检查失败,因为该语言无法针对安全性问题进行静态分析。我用动态语言演示了两个示例,其中语言的性质使它可以颠覆静态分析。我还指出了为什么即使从理论上讲也永远不可能是准确的。也许在某些地方允许使用perl,而在其他地方则不允许,我只能猜测原因。
–user40980
13年7月30日在17:35
您还可以使用许多其他语言(例如Obj-C,C,C ++)重新定义标准库函数。
–马丁·威克曼(Martin Wickman)
13年7月31日在10:23
嗯,.NET扩展方法与上述Ruby不同。它们只是创建一种简单的方式来键入静态类。他们实际上并没有向类添加方法。
–格雷厄姆
13年7月31日在12:04
#2 楼
假设评估仅是安全性,而不仅仅是接受扫描(也就是说,他们不接受Ruby是因为他们不希望支持Ruby),那么:安全性分析工具通常存在问题时间与动态行为。
例如:
通过诸如Veracode的程序运行任何用ASP.NET MVC和Entity Framework等现代功能编写的.NET项目,并查看什么样的误报清单您会在报告中收到。
Veracode甚至将.NET 4核心库中的许多基本技术列为“不受支持的框架”,称为“不受支持的框架”或beta版,即使它们中的大多数已经使用了几年。 br />
如果您要与非常依赖这种工具的实体打交道,那么如果他们没有技术专长和资源,他们几乎会被迫考虑那些不安全的人,以手动评估项目并看看它是否被正确编写并且安全。
在民用行动中,计算机系统通常无法控制任何危险或极其昂贵的事情,缓解措施是,您讨论误报,并且在以下情况中通常被接受。批量。
在银行业务中,您仍然有机会错误的缓解措施,但是您将花费更多的时间讨论每个项目的细节。这很快就变得成本过高,您开始使用更多传统方法。
在军事,航空,重工业等领域,系统可以控制那些具有可怕故障模式的系统,因此它们可能非常严格。关于语言,编译器等的规则。
组织通常还会针对他们所知的最坏情况编写其安全策略,因此,即使您编写的内容微不足道,如果您是为拥有以下知识的组织编写的,非平凡的系统,除非有人要求特定的例外,否则默认情况通常是将其保持在更高的标准。
评论
那只是误报。真正令人担忧的是潜在的假阴性。
– Stephen C
13年8月1日在6:21
老实说,我对这些工具的经验通常很糟糕。大概是从1/200到1/1000的比率找到真正值得讨论的事物。同样,当我得到一个误报时,我知道在代码库或框架的成千上万的地方都使用了某种东西,并且它只在少数情况下才发现它,我对此并不充满信心。问题在于,除非您以诸如spec#之类的正式语言开始,否则在构建这些工具之一时,您将有效地实施否定证明。
– Bill
2013年8月1日14:32
#3 楼
动态语言可用于国防和军事应用。我亲自在DoD应用程序中使用和交付了Perl和Python。我还看到了PHP和JavaScript的使用和部署。根据我的经验,我看到的大多数非编译代码都是shell脚本和Perl,因为所需的环境已被批准并安装在各种可能的目标系统上。语言是动态的,这很可能不是问题。这些语言的口译员必须经过批准才能在目标系统上使用。如果解释器未被批准使用(或者可能被批准,但是未部署在目标系统上),则该语言将无法使用。在安全系统上使用给定的解释器(或任何应用程序)需要任何数量的安全障碍:源代码分析,针对目标环境从源代码编译的能力,二进制文件的附加分析,确保与现有基础结构不发生冲突等。
#4 楼
我花了一些时间在国防部(DOD)面试,为F-16的MMU编写代码。不违反任何保密规定:MMU是控制几乎所有F-16功能的计算机单元。 (很明显)至关重要的是,在飞行过程中不会发生任何错误,例如运行时错误。同样重要的是,系统必须执行实时计算操作。由于这个原因和其他历史原因,该系统的所有代码都是用静态对象导向的编程语言ADA编写或编译的。 br />
由于Ada的安全性至关重要的支持功能,现在它不仅用于军事应用,而且还用于商业项目,在这些商业项目中,软件错误可能具有严重的缺陷。结果,例如航空电子和空中交通管制,商用火箭(例如Ariane 4和5),卫星
和其他空间系统,铁路运输和银行业务。对于
示例,波音777中的电传操纵系统软件是在Ada中编写的。
我讨厌引用过多,但这确实很好地解释了为什么将完全静态语言(如ADA)用于这样的项目:
支持大量的编译时检查,以帮助避免在某些其他语言下运行时无法检测到的错误,或者需要将显式检查添加到源代码中的错误。对于
示例,语法要求显式命名的块关闭以
防止由于结束令牌不匹配而导致错误。坚持强类型
可以在编译期间或在运行期间检测许多常见的软件错误(错误的
参数,范围违反,无效的引用,类型不匹配,
等)。 -时间。由于
并发是语言规范的一部分,因此在某些情况下,编译器可以检测到潜在的死锁。编译器通常还会检查
用于拼写错误的标识符,包的可见性,冗余的
声明等,并且可以针对如何解决错误提供警告和有用的建议。
Ada还支持运行时检查,以保护
防止访问未分配的内存,缓冲区溢出错误,范围
违规,一次性错误,数组访问错误和其他
可检测的错误。可以出于运行时效率的考虑禁用这些检查,但是通常可以有效地进行编译。它还
包括有助于程序验证的工具。由于这些原因,
Ada广泛用于关键系统中,在该系统中任何异常都可能导致非常严重的后果,例如意外死亡,受伤或严重的经济损失。使用Ada的系统示例包括航空电子,铁路,银行,军事和太空技术。
Ada的动态内存管理是高级且类型安全的。 Ada没有
没有通用的(模糊的)“指针”;也不会隐式
声明任何指针类型。相反,所有动态内存分配和
重新分配必须通过显式声明的访问类型进行。
每种访问类型都有一个关联的存储池,用于处理内存管理的低级详细信息。程序员可以使用默认存储池,也可以定义新的存储池(与非统一内存访问特别相关)。甚至可以声明几种不同的访问类型,它们都指定相同的类型,但使用不同的存储池。此外,该语言还提供了
在编译时和运行时的可访问性检查,以确保
确保访问值不会超过它所指向的对象的类型。
>
评论
“由于Ada的安全性至关重要的支持功能,现在已在[商业]火箭中使用(例如Ariane 4和5)。”当然,第一个Ariane 5由于软件错误而爆炸,因此没有灵丹妙药。
–安德鲁·马歇尔(Andrew Marshall)
2014年1月26日20:16
@AndrewMarshall:“尽管该报告将软件错误确定为直接原因,但其他调查人员将这些原因视为系统设计失败和管理问题”-我严重怀疑使用其他语言(例如Java或C ++)编写的代码是否会火箭进入轨道。
–马丁·施罗德(MartinSchröder)
2014年1月27日10:39
@MartinSchröder噢,我并不怀疑Ada在此应用程序方面仍然可能优于其他应用程序,只是指出它不是万无一失的。另一种语言可能会通过Ada不可能的无数错误。
–安德鲁·马歇尔(Andrew Marshall)
2014年1月29日,下午2:29
#5 楼
国防部和美国国家航空航天局都有悠久的历史,编程失败使他们损失了数十亿美元。两家机构都接受了应该保护它们避免重复相同错误的过程。Is this the government being slow to adopting new technologies?
这是一个误解-动态语言不是新技术,它们已经很老了。问题是,如果您曾经遇到过由动态语言引起的问题(例如,弱类型/动态键入),并且该问题使您付出了很多钱,那么您可以接受一项政策,以防止再次犯同样的错误-例如禁止在敏感系统中使用动态语言。
动态语言通常会“吞噬”错误,并最终导致某些意外行为。这在敏感系统中非常危险。如果发生错误,您希望尽快知道。
如果考虑到安全性,则有必要查看实际用例。例如,我认为Ruby on Rails网页不会自动地比Java网页安全。
评论
恕我直言,未被检测到的缓冲区溢出“吞噬”了更多的错误,这比大多数其他错误更确切地说,这恰恰是大多数动态语言不允许的……
– miraculixx
2014年1月26日在1:09
@miraculixx是的,确实有一个原因使得Java / C#和类似语言的使用量比Ruby多得多。他们是防御性的-他们检查一切。在C / C ++中,可以通过使用良好的编码标准来增强防御性。您还可以对所有内容执行检查。但是您能想象用ruby或javascript编写敏感的应用程序吗?隐藏错误的可能性很大。
–苏丹
2015年3月10日9:35
的确可以。我们可能同意,软件需要进行独立于编程语言的彻底测试。为了避免回归,最好使用例如单元测试,BDD等。假设采用专业方法(敏感的应用程序,对吗?),实现足够的测试覆盖范围是一个托管过程,并非偶然。因此,我怀疑C / C ++,Java在隐藏错误方面是否比ruby或javascript有优势。程序员技能? C ++可能更具技术性,而Java则令人怀疑,但几乎没有语言问题。技术含量更高!=产品质量。
– miraculixx
2015年3月12日9:03
#6 楼
我想通过描述Drupal的SA-CORE-2014-005来增加现有的答案,这是一个非常关键的漏洞,可以启用SQL注入并最终执行任意代码。这是由PHP的动态类型输入和宽松的运行时类型输入规则引起的。此问题的修补程序的整体是:是SQL抽象层的一部分,旨在防止SQL注入。它需要一个带有命名参数的SQL查询,以及一个为每个命名参数提供值的关联数组。对于类似
WHERE x IN (val1, val2, val3)
的情况,该值允许为数组,其中所有三个值都可以作为单个命名参数的单个数组值传递。之所以会出现此漏洞,是因为代码假定
$i
$i => $value
中的值必须是该值的整数索引。它继续并将该“索引”作为参数名称的一部分直接连接到SQL查询中,因为整数不需要任何转义,对吗?不幸的是,对于Drupal,PHP没有提供这样的保证。可以传入另一个键为字符串的关联数组,并且此循环将按原样愉快地将字符串键连接到查询中(请记住代码认为它只能是整数)。
虽然有多种方法可以在静态类型的语言中产生类似的错误,但可能性不大。一个好的开发人员在将
$i
连接到查询中之前会考虑可能的情况。使用静态类型的语言,可以很容易地强制$i
必须为整数,并且在像这样的安全敏感代码中,肯定可以做到这一点。此外,代码实际上在迭代项目之前检查该值是否为数组。这是导致该漏洞的失败的第二部分:关联数组和“正常”数组均对
is_array
返回true。虽然在C#中也确实如此,字典和数组都是IEnumerable
,但很难构造将字典键与这样的数组索引相混淆的代码,即使是有意的,更不用说偶然了。#7 楼
据我所知,国防部的官方政策通常不禁止使用动态语言。国防部开发或采购的软件标准由国防信息系统局(DISA)颁布)。他们的应用程序安全性-应用程序安全性和开发安全性技术实施指南(STIG)不禁止任何特定语言。它没有提到Ruby,但是提到了类似的动态Perl和Python。它在各种主题的上下文中提到了它们(遵循既定的编码标准,避免了命令注入漏洞等)。
您可能看到的是一个过于严格的扫描工具(提到了几种不同的工具)在STIG中,每个人可能都有自己对规则的解释)和/或对其输出的解释过于严格。
#8 楼
代码库是否安全取决于代码的编写方式,测试方式以及验证和监视开发与部署过程的方式。语言既不安全也不安全,这就是您编码的方式。大多数安全事件是由于恶意输入(SQL注入,缓冲区溢出),病毒,Rootkit和特洛伊木马引起的。没有语言可以保护您不受此威胁的影响。
因此,禁止使用“不安全”的语言类别是没有道理的。
我怀疑有人出于某种原因-知情还是不-决定禁止这些语言。一段时间后,它变成了组织真理。对于某些项目,那时可能确实如此,但是控制文化并不热衷于更改决策(承认他们错了),而是更喜欢简单的规则。它们在规则和法规上蓬勃发展,无论它们是否有意义,都至关重要,重要的是可感知的安全性。
在控制文化中,这种情况一直存在。我每天或多或少看到它。这没有任何意义,但事实就是如此。如果您想阅读有关此高度相关主题的更多信息,我建议使用Schneider的书“ The Reengineering Alternative”。这是Michael Sahoto / Agilitrix根据Schneider的书制作的文化图表:
评论
-1对于安全关键型系统,有很多有效的技术原因会选择一种语言而不是另一种语言(实时,静态键入,运行时检查)。您暗示其原因是100%的文化,我们与他们的文化和武断的,在这种情况下,IMO完全不正确。
–迈克尔·贾斯珀(Michael Jasper)
13年8月1日下午5:21
“语言既不安全也不安全” -请参阅stackoverflow.com/a/14313277/602554。某些语言肯定比其他语言“更安全”。
–迈克尔·贾斯珀(Michael Jasper)
13年8月1日在5:25
更新了我的答案,也许根据您的喜好。我仍然相信,系统的安全性取决于所编写的代码而不是所使用的语言,尽管某些语言可以帮助避免某些问题(而可能会引入其他问题)。
–马丁·威克曼(Martin Wickman)
13年8月1日在8:46
@MartinWickman:a)SQL / HTML注入和缓冲区溢出由某些类型系统解决-逸出和未逸出的输入具有不同的类型,因此您知道应该以哪种方式处理。 b)并非“安全项目”中的所有安全问题都必然意味着妥协。我不希望运行飞机的软件出现任何错误,即使这不是“安全性”问题(即不能用来接管系统)也是如此。
– Maciej Piechotka
13年8月2日在10:48
-1为事实准确性问题。缓冲区溢出漏洞利用是高度针对C语言的问题。您从未听说过用不允许您在堆栈上分配字符串缓冲区的语言。而且,不难想象一个假设的SQL方言,其中不仅仅允许使用参数,而且要求使用参数。用这种语言不可能进行SQL注入。因此,是的,一种经过适当设计的语言可以保护您免受几种常见类型的攻击。
–梅森·惠勒
2014年1月26日在1:46
评论
唯一可以确定的方法是您的熟人是否向其雇主询问原因。但我可以冒险:静态类型检查是另一层有助于关键任务软件正确性的层。当然,它不会消除错误,但这是朝着正确方向迈出的一步:计算机正在为您完成一些工作。 (是的,我知道这是圣战领土)。可能相关:williamedwardscoder.tumblr.com/post/42912076785/…
您不希望用PHP + JavaScript编写导弹控制软件。
HR数据不是“低安全级别”。我希望一家公司尽可能确保我的工作和个人数据安全。
@gbjbaanb我猜想OP意味着失去生命并不是这里最坏的情况。