使用Scala解释器API时保护系统

时间:2019-05-23 07:11:17

标签: linux scala security scala-reflect scala-repl

我为REPL创建了一个简单的scala机器人。

它在linux环境中运行,并在对话框中处理scala编写的代码,并给出结果:

例如

user| 1+1
bot | res0: Int = 2
user| res0 + 3
bot | res1: Int = 5
...

我为此目的使用了scala interpreter API

将给定string作为scala代码处理的代码:

private val settings = new Settings
settings.processArgumentString(
    """
      |-deprecation
      |-feature
      |-Xfatal-warnings
      |-Xlint
      |-usejavacp
      |""".stripMargin)

def run(code: String, id: Long): (Result, String) = {
    stream.reset()
    try {
        val intp = intpMap.getOrElseUpdate(id, new IMain(settings, new PrintWriter(stream, true)))
        timedRun(maxWorkTime)(intp.interpret(code)) -> stream.toString
    } catch {
        case e: TimeoutException => (Error, s"Долго считать - иди в пень")
    }
}

但是在以下情况下会出现问题:如果用户尝试访问系统文件怎么办?例如将写入字符串:

scala.sys.process.stringToProcess("ls /").!!

bot将提供对系统文件的访问权限。 我还在https://scastie.scala-lang.org/中尝试了此代码段,并可以访问系统文件。但是我认为他们在docker容器中运行REPL,并且没有问题。

是否有任何方法可以限制运行我的机器人的jvm实例访问系统文件,或者可以限制REPL API配置中的文件访问?

这时,我正在对'scala.sys'或'java.io'子字符串的给定字符串进行分析,但我认为它不可靠。

还有其他安全漏洞吗?

1 个答案:

答案 0 :(得分:1)

据我所知,内置于JVM的解决方案是SecurityManager

您可以使用它来限制对JVM各种功能的访问,例如限制对文件,请求,反射等的访问。尽管我尚未对其进行测试(尤其是在REPL的情况下),并且可能会发生限制事物的方式完全不会阻止REPL起作用。

我认为更安全的替代方法是将REPL作为单独的进程运行,而没有在系统级别进行访问-基本上创建一个非常受限制的用户,在该进程中运行第二个JVM并通过某些RPC进行通信-这种方式操作系统本身将停止所有邪恶用户的尝试。

为了更加安全,我将两者结合起来:在系统级别和SecurityManager受限访问的单独进程中运行REPL。

您已经注意到Scastie只需使用Docker即可解决此问题-如果您配置Docker以限制每个映像的CPU,内存和磁盘空间量,并且不对主机和映像公开任何内容。

然后,您的“唯一”麻烦是诸如崩溃/幽灵之类的漏洞。但是在这一点上,您应该咨询一些安全专家,因为这样可能太笼统了。