科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道安全管理动态变量的安全危机

动态变量的安全危机

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在这种情况下,处于谨慎的考虑应该采取简单的办法。如果不使用动态的变量名,你就不必处理所有这些问题,因此只要选择不使用动态变量名就可以了。这个问题真的就是这么简单。

作者:ZDNet安全频道 来源:ZDNet安全频道【原创】 2009年12月21日

关键字: 黑客 攻击 漏洞 网络安全 网络管理

  • 评论
  • 分享微博
  • 分享邮件

ZDNet安全频道原创翻译 转载请注明作者以及出处

在软件编程中,一个很常见的话题是如何对动态变量名进行处理。而且,实际上它也是一条制造安全问题的方便途径。
--------------------------------------------------------------------------------------------

  或许你已经看到过,至少,也应该在关于编程的网络讨论中注意到这一点。有时,在一些地方,有人会问,在一种特定的语言中,如何对变量进行动态命名。

  通常情况下,这意味着想这样做的人希望实现这样的功能,在用户输入信息后,利用该信息对变量进行命名。尽管到处都会出现这样的事情,但根据笔者的经验,在PHP圈子中,这样的情况出现的似乎更频繁。如果你选择的语言包含了eval函数的时间,它看上去通常是可行的。下面就是一个采用了Ruby语言非常危险的例子:

  var_name = gets.chomp # get input from STDIN

  var_value = gets.chomp # get more input from STDIN

  eval("#{var_name} = var_value")

  (请注意:在本文中,所有例子的代码都采用了Ruby语言。笔者之所以选择Ruby,是因为它方便阅读,可以让示例显得更有效;并且,笔者也很喜欢这种语言;还有,笔者知道Ruby非常有效,提供的例子非常简单易懂,不必花费大量的精力去思考。不过,这里的原则对于很多其它语言来说都是通用的。关于chomp模式要注意的是,它知识在输入行结束的时间丢弃了换行符。)

  如果你运行该程序,并在第一个提示符下输入foo,在第二个提示符下输入bar,就会得到一个包含了bar这个量的最终变量foo。看起来真的很简单,但是不要这么做。

  这真的是一件你永远都不应该做的事情。请千万不要这么做。它导致的最好结果就是危险代码很难获得通过,最终无法运行。笔者想,在邮件列表和其它网络讨论中提出这一问题的大多数人都不了解,在动态命名变量后,让包含未知变量名称的变量运行是一件多么困难的事情。

  程序员希望使用这项功能的常见原因是希望进一步挖掘用户提供的信息,增加含金量。举例来说,如果一个命名为foo的变量是用户在某个时间处于某种原因输入的,程序可以输出信息提示用户,让其再次输入foo。是这样子么?

  通常情况下,处理这种事情的正确做法是使用语言中的scoping规则,就是采用一些循环结构类型,这样的话,变量就可以存储需要的地方。通过这种方法,保存起来的“特殊位置”变量就不会是动态命名变量了;这样的话,程序与该变量在运行时都处在现有的范围中。在其他情况下,可能只需要在一些数据库或者数据表中创建一个新的条目,将变量保存在数据中而不是动态命名并保存变量。

  举例来说,考虑到数组群中的一个数组。为什么不创建一个数组,包含了任意数目的条目,在需要的时间就增加条目,这样每个数组元素本身就都是由两个元素组成的数组?

  ar = [

  [gets.chomp, gets.chomp],

  [gets.chomp, gets.chomp]

  ]

  如果用户根据输入框的提示输入foo、bar、baz和qux,在下面就可以得到:

  ar = [

  ['foo', 'bar'],

  ['baz', 'qux']

  ]

  你可以对数组进行迭代或递归操作,确保子数组的第一个元素是‘foo’,并且可以获得数组的第二个要素,具体步骤如下:

  user_call = gets.chomp

  ar.each do |pair|

  puts pair[1] if pair[0] == user_call

  end

  这样就可以输入文字了,看上去非常简单。并且,对于确认用户输入的信息,它的操作也更为容易。但是,如果你使用的是动态命名变量的话,就必须动态地确定如何调用这些变量了:

  user_call = gets.chomp

  puts eval("#{user_call}")

  这看起来非常简单,但是在执行的时间,效果却是令人难以置信的。为了保证开始代码的安全,你需要对输入进行安全处理,这就意味着更多的代码。事情就变得更加复杂了。

  越简单的概念在使用和维护的时间就会产生越复杂的问题。这样的问题越多,你的软件在安全方面出现漏洞的可能就越大。这不是一个仅仅让你的工作变得更困难的问题,它还会导致你的用户在安全性方面出现问题的可能增加。因此,不要选择这么做。不要试图动态命名变量。是时间摆脱它了,不要尝试玩火。与一些替代方案相比,它有时间甚至可能是一种更好的方法,但笔者可以保证你永远不会有机会遇到这种环境。如果你认为自己属于这种环境,根据手头问题选择解决方案的办法,很可能效果好得多。

  正如笔者在此前的文章中指出的:尽力避免这样做,选择其它人编写的代码,更重要的是,其它人的代码在你自己的进行测试前已经被测试过了,因此,对于尽量减少代码引入安全漏洞的可能性来说,这是一条非常有效的途径。从本质上讲,使用多维数组逼近动态命名变量是一些人(实现语言开发者)编写代码(数组处理代码)的一种情况,它可以替代自己编写动态变量执行(使用一个eval表达式):

  实际上,更简单的方法是采用一维数组。很多情况下,尽管人们感觉自己需要的是动态变量命名,但真正需要的其实是一个数组。你的数组可以任意命名,由于数组元素拥有编号,因此,你还可以利用数字对元素进行跟踪。如果需要的话,你还可以利用两个数组,通过其中的某种变量保持联系。举例来说:

  arkey[0] = gets.chomp

  arval[0] = gets.chomp

  这将为你提供两个数组,其中的一个包含了想要使用的变量名和其它打算赋予它的变量。你只要查询第一个数组(arkey),找出元素的编号和用户输入的信息,并赋予其变量名,就可以利用对应的元素编号得到相应的变量值:

  num = nil

  (0..(arkey.length - 1)).each do |n|

  num = n if arkey[n] == 'foo'

  end

  puts arval[num]

  如果相应的arval变量是你需要的,就可以进行简化操作了:

  (0..(arkey.length - 1)).each do |n|

  puts arval[n] if arkey[n] == 'foo'

  end

  如果你想获得真值的话,可能会认为也许可以使用哈希(如果语言支持的话),至少比使用一个eval表达式是一个更好的主意。例如:

  ha = Hash.new

  ha[gets.chomp] = gets.chomp

  如果你在第一栏输入foo,在第二栏输入bar,就可以获得一个名称为foo包含变量的哈希元素:

  puts ha['foo']

  这样的话,输出结果就是bar了。简单得很,没有动态变量命名的需求了,至少,表面上看起来是这样的。另一方面,经过深入研究,在处理用户输入信息的变量时,你会找出一些方法在动态的情况存储foo。再次提醒,你可以选择一个eval表达式。也许,你应该只使用数组。

  在这里的关键是,除了使用eval以外,摆脱动态命名的话还有多种令人满意的方法。如果不是非常非常小心的话,使用一个eval表达式是让你陷入麻烦中很有效的方法,特别是在用户可以随意输入的情况下!通过同样的方法,SQL注入漏洞可以让人们运行任意SQL查询命令,eval表达式中包含了用户输入的内容中可能会有执行代码,这就会导致安全出现问题。采用eval表达式处理用户输入信息,或者执行用户输入命令的时间,你都应该重新审视自己的做法。

  文章前面,笔者提到过之前的一篇文章。在那篇文章中,笔者第一次提出来,使用别人的代码来解决你的问题的重要性,因为其他代码可能已经经过充分测试,并且缺陷(包括潜在的安全漏洞)都出现了。关于这一编程经验,最重要的就是是验证输入代码。你也许已经读过文章了,但要记住,尽力避免这样做并不等于仅仅利用别人的代码来这么做。

  你可以对eval表达式中用户输入的信息进行净化处理,确保不存在直接的安全威胁,这样做是正确的。但问题的关键在于,怎么样知道所有用户可能输入的信息以实现“适当的净化”。这就是为什么要避免利用eval表达式处理任何涉及用户输入的信息的原因之一,简单的说,这是你避免来自未净化(或不正确净化)的用户输入导致的问题最好的方法就是避免净化所有的输入信息。任何其他动态命名变量的方法都可能遇到类似eval表达式解决方案面临的问题,创建一个需要净化输入的环境会导致为安全漏洞蔓延到代码中创造更多的机会。

  在这种情况下,处于谨慎的考虑应该采取简单的办法。如果不使用动态的变量名,你就不必处理所有这些问题,因此只要选择不使用动态变量名就可以了。这个问题真的就是这么简单。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章