代码:
require 'tempfile'
require 'open3'
def valid_pgp_key?(unsafe_user_input)
tempfile = Tempfile.new('pgp_pubkey')
command = ['gpg',
'--no-default-keyring',
'--keyring',
tempfile.path,
'--import',
'-']
stdin, stderrout, thread = Open3.popen2e(command)
stdin.puts(unsafe_user_input)
stdin.close
exit_status = thread.value
tempfile.unlink
exit_status.success? ? true : false
end
unsafe_user_input
是一个完全未经过清理的字符串,我们希望它是一个有效的PGP公钥(但接受它可以有效地作为密钥)。
问题:
execve()
,因此无需担心shell注入 - 这是真的吗?答案 0 :(得分:1)
嗯..它似乎非常简单而且不够健壮,但让我们这样看待它:
-
结尾,因此IIRC GPG假设所有后续数据都作为数据,并且无法将其解释为其选项stdin
,而不是整个shell。如果注射成功,除了以奇怪的方式运行GPG之外几乎无法做任何其他事情。因此,即使攻击成功,如果GPG正确实现并且不会自行暴露任何攻击,那么只会失败GPG任务。 (我认为GPG的检查比Ruby的运行时和上面的脚本本身更好,所以看起来不太可能)command
和execve
部分在我看来是胡说八道。 Command包含一些在代码中明显可见的字符串,以及一个以标准方式自动生成的temppath。一切都是常数或根本不依赖于用户,因此command
与GPG的常量参数一样安全。unsafe_input
的{{1}}。它通过stdin
传递给标准输入,以字符串形式传递给标准输入。 IIRC,它将在puts
对象提供的to_s
中结束,但它仍将最终将字符串数据写入管道,管道已被GPG视为数据。同样,它和GPG以及Ruby运行时一样安全。所以,对我来说,这个剧本是“相对安全的” - “安全”,因为这是简单的代码而且我可以阅读它并且我没有看到任何问题 - 并且“相对”仅来自我不喜欢的事实认为自己是专家,无论是在Ruby中还是在安全方面。
我可以说我相信GPG的代码。如果我正在寻找一些漏洞,我可能会在Ruby运行时自己寻找问题,缓冲区溢出等。我敢打赌,它比GPG检查的要少。即如果用户提供的数据具有不正确的字符编码和不正确的长度怎么办? unsafe_input
puts
会发疯吗?此外,我看到了许多其他或多或少的邪恶可能性:让我们即时注入定制的stream/pipe
实施,并且安全性也随之而来。但除了这些之外,如果我们不允许“用户”加载他的任何代码,如果我使用Ruby来完成这项工作,并且如果我相信它的运行时 - 我发现这里没有问题。