安全地评估R中的算术表达式吗? [英] Safely evaluating arithmetic expressions in R?

查看:45
本文介绍了安全地评估R中的算术表达式吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,由于似乎存在很多混乱,我将简化一下这个问题。您可以尝试回答下面的原始问题,也可以改用这个版本,而忽略该行下方的所有内容。

Ok, since there seems to be a lot of confusion, I'm going to simplify the question a little. You can try to answer the original question below, or you can tackle this version instead and ignore everything below the line.

我的目标是采用任意表达式并对其求值在极端受限的环境中。此环境将仅包含具有以下值类型的变量:

My goal is to take an arbitrary expression and evaluate it in an extremely restricted environment. This environment will contain only variables with the following types of values:


  • 数值向量

  • 纯函数取一个或多个数值向量并返回数值向量(即算术运算符)

另外,表达式必须能够使用任何文字,例如数字和字符串常量(但不包括数字或字符串向量,因为它们需要 c )。我想在此环境中评估该表达式,并确保该表达式无法访问该环境以外的任何内容,以便可以确保评估该表达式不会带来安全风险。因此,在下面的代码中,您是否可以用一个字符串填充空白,该字符串在求值时会变得很顽皮? 有些顽皮的定义是在屏幕上打印一些东西,访问变量 secret 的值,执行任何shell命令(最好是产生输出的shell命令)或任何其他

In addition, the expression would necessarily be able to use any literals, such as numeric and string constants (but not numeric or string vectors, since those would require c). I would like to evaluate the expression in this environment and ensure that there is no way for the expression to access anything outside the environment, so that I can be sure that evaluating the expression would not be a security risk. So, in the below code, can you fill in the blank with a string that will do something naughty when evaluated? "Something naughty" is defined as printing something to the screen, accessing the value of the variable secret, executing any shell command (preferably one that produces output), or anything else that seems naughty to you (justify your choice).

a <- 1
b <- 2
x <- 5
y <- 1:10
z <- -1

## Give secret a random value so that you can't just compute it from
## the above variables
secret <- rnorm(5)

allowed.variables <- c(
    ## Numeric variables
    "a", "b", "x", "y", "z",
    ## Arithmetic operators
    "(", "+", "-", "/", "*", "^", "sqrt", "log", "log10", "log2", "exp", "log1p")

restricted.environment <- Map(get, allowed.variables)

## Example naughty expressions that my method successfully guards
## against
expr1 <- "secret"
expr2 <- "cat('Printing something with cat\n')"
expr3 <- "system('echo Printing something via shell command')"

arbitrary.expression <- "?????????" # Your naughty string constant here

eval(parse(text=arbitrary.expression), envir=restricted.environment, enclos=emptyenv())






原始问题



我正在编写一些代码,将算术表达式用作用户输入并对其进行求值。我有一组可以使用的指定变量,以及一个算术函数白名单( + - * / ^ 等)。有什么方法可以对表达式求值,以便仅这些变量和运算符在范围内,从而避免任意代码注入的可能性?我有一些我认为可行的东西,但是除非可以肯定它确实是防弹的,否则我不希望实际使用它:


Original question

I am writing some code to take an arithmetic expression as user input and evaluate it. I have a specified set of variables that can be used, and a whitelist of arithmetic functions (+, -, *, /, ^, etc.). Is there any way that I can evaluate an expression so that only these variables and operators are in scope, in order to avoid any possibility of arbitrary code injection? I have something that I think works, but I don't want to actually use it unless I have some certainty that it is really bulletproof:

## Shortcut for parse-then-eval pattern
evalparse <- function(expr, ...) eval(parse(text=expr), ...)

# I control these
arithmetic.operators <- Map(get, c("(", "+", "-", "/", "*", "^", "sqrt", "log", "log10", "log2", "exp", "log1p"))
vars <- list(a=1, b=2)
safe.envir <- c(vars, arithmetic.operators)

# Assume that these expressions are user input, e.g. from a web form.
nice.expr <- "a + b"
naughty.expr <- paste("cat('ARBITRARY R CODE INJECTION\n'); system('echo ARBITRARY SHELL COMMAND INJECTION');", nice.expr)

## NOT SAFE! Lookups outside env still possible.
evalparse(nice.expr, envir=safe.envir)
evalparse(naughty.expr, envir=safe.envir)

## Is this safe?
evalparse(nice.expr, envir=safe.envir, enclos=emptyenv())
evalparse(naughty.expr, envir=safe.envir, enclos=emptyenv())

如果运行在R中的上述代码中,您会看到我们第一次评估 naughty.expr 时,它成功执行了其有效负载。但是,第二次使用 enclose = emptyenv(),评估只能访问变量 a b 以及指定的算术运算符,因此有效负载无法执行。

If you run the above code in R, you'll see that the first time we eval naughty.expr, it successfully executes its payload. However, the second time, with enclose=emptyenv(), the evaluation only has access to the variables a, b, and the specified arithmetic operators, so the payload fails to execute.

因此,此方法是(即 eval(...,envir = safeenv,enclos = emptyenv()))实际上可以在生产中使用来接受实际的用户输入,还是我错过了一些偷偷摸摸的方式来执行在受限制的环境中使用任意代码?

So, is this method (i.e. eval(..., envir=safeenv, enclos=emptyenv()) ) actually OK to use in production accepting actual user input, or am I missing some sneaky way to still execute arbitrary code in the resticted environment?

推荐答案

我会采用略有不同的方法来定义安全功能和环境您可以评估任意代码,但实际上只是一些样式更改。只要 safe_f 中的所有函数都是安全的,即不允许您执行任意代码执行,则该技术是安全的。我非常有信心列表中的功能是安全的,但是您需要检查各个源代码以确保安全。

I'd take a slightly different approach to defining the safe functions and the environment in which you evaluate arbitrary code, but it's really just some style changes. This technique is provably safe, provided all of the functions in safe_f are safe, i.e. they don't allow you to perform arbitrary code execution. I'd be pretty confident the functions in list are safe, but you'd need to inspect the individual source code to be sure.

safe_f <- c(
  getGroupMembers("Math"),
  getGroupMembers("Arith"),
  getGroupMembers("Compare"),
  "<-", "{", "("
)

safe_env <- new.env(parent = emptyenv())

for (f in safe_f) {
  safe_env[[f]] <- get(f, "package:base")
}

safe_eval <- function(x) {
  eval(substitute(x), env = safe_env)
}

# Can't access variables outside of that environment
a <- 1
safe_eval(a)    

# But you can create in that environment
safe_eval(a <- 2)
# And retrieve later
safe_eval(a)
# a in the global environment is not affected
a

# You can't access dangerous functions
safe_eval(cat("Hi!"))

# And because function isn't included in the safe list
# you can't even create functions
safe_eval({
  log <- function() {
    stop("Danger!")
  }
  log()
})

这是一个比 rapporter沙箱简单得多的问题,因为您不是要创建有用的R环境,只是一个有用的计算器环境,而要检查的函数集要小得多。

This is a much simpler problem than the rapporter sandbox because you're not trying to create an useful R environment, just a useful calculator environment, and the set of functions to check is much much smaller.

这篇关于安全地评估R中的算术表达式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆