这是一个很老的话题,但是仍然是最新的,并且如今令人惊讶地带来了更大的影响。正如乔恩(Jon)所述,这可能只是Java设计师一开始就犯的错误。但是我无法想象它会对安全产生影响。
许多编码人员都知道Apache Velocity,灵活而强大的模板引擎。它是如此强大,以至于它可以为模板提供一组命名对象-严格被认为是编程语言(最初是Java)中的对象。可以像使用编程语言一样从模板内访问这些对象,例如,Java的String实例可以与其所有公共字段,属性和方法一起使用。
$input.isEmpty()
其中input是String,直接通过JVM运行,并向Velocity解析器的输出返回true或false)。到现在为止还挺好。
但是在Java中,所有对象都继承自Object,因此我们的最终用户也可以将其放在模板中
$input.getClass()
获取String Class的实例。
并且使用此引用,他们还可以在此上调用静态方法forName(String)
$input.getClass().forName("java.io.FileDescriptor")
使用任何类名并将其用于Web服务器的帐户可以执行的任何操作(破坏,窃取数据库内容,检查配置文件等)
对此漏洞进行了某种描述(在特定上下文中):https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
如果禁止从对类实例的引用中调用静态方法,那将是不可能的。
我并不是说一个特定的编程框架要比另一个框架更好,但我只想进行比较。.NET有一个Apache Velocity端口。在C#中,仅从实例引用中就不可能调用静态方法,这使得像这样的利用毫无用处:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
String hello = null; hello.valueOf(123);
有效!