我为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'子字符串的给定字符串进行分析,但我认为它不可靠。
还有其他安全漏洞吗?
答案 0 :(得分:1)
据我所知,内置于JVM的解决方案是SecurityManager
。
您可以使用它来限制对JVM各种功能的访问,例如限制对文件,请求,反射等的访问。尽管我尚未对其进行测试(尤其是在REPL的情况下),并且可能会发生限制事物的方式完全不会阻止REPL起作用。
我认为更安全的替代方法是将REPL作为单独的进程运行,而没有在系统级别进行访问-基本上创建一个非常受限制的用户,在该进程中运行第二个JVM并通过某些RPC进行通信-这种方式操作系统本身将停止所有邪恶用户的尝试。
为了更加安全,我将两者结合起来:在系统级别和SecurityManager
受限访问的单独进程中运行REPL。
您已经注意到Scastie只需使用Docker即可解决此问题-如果您配置Docker以限制每个映像的CPU,内存和磁盘空间量,并且不对主机和映像公开任何内容。
然后,您的“唯一”麻烦是诸如崩溃/幽灵之类的漏洞。但是在这一点上,您应该咨询一些安全专家,因为这样可能太笼统了。