Coordinated Disclosure Timeline
- 03/23/2020: Sent report to security@apache.com
- 03/24/2020: Received acknowledgement
- 07/4/2020: Reported Uberspector bypass to Velocity security team
- 07/15/2020: Received acknowledgement
- 08/05/2020: Public PR containing the fix is submitted
- 02/26/2021: Fix gets merged
Summary
- Velocity Uberspector fails to prevent access to
java.lang.ClassLoader
methods. - When Velocity templates are used in the context of a VelocityView an attacker that is able to modify Template contents may execute arbitrary Java code or run arbitrary system commands with the same privileges as the account running the Servlet container.
Product
Apache Velocity
Tested Version
Apache Velocity 2.2
Details
Improper BlockList verification
Velocity SecureUberspector prevents access to dangerous classes and packages by checking if any methods are invoked on the blocked classes. However Velocity fails to inspect the complete class hierarchy of the object where the method is invoked. This effectively means that if a method is called on an object of a given type that extends a class or implements an interface present in the BlockList, the invocation will not be blocked. As an example, the java.lang.ClassLoader
abstract class is present in the Secure Uberspector default BlockList, however, as an abstract class, it cannot be instantiated, so any calls on a ClassLoader instance will happen to be in a class extending java.lang.ClassLoader
which is not present in the BlockList.
For example, given the following template, the ScriptEngineManager
class will be successfully loaded:
${request.servletContext.classLoader.loadClass("javax.script.ScriptEngineManager")}
Insufficient Sandbox Protection
Even though Velocity offers a great sandbox that prevents dangerous methods from being invoked, exposing Servlet related objects (such as the Servlet context) may introduce a variaty of objects which can be used to bypass the Velocity sandbox. Deep inspection of the exposed objects’ object graph allows an attacker to get access to objects that allow them to instantiate arbitrary Java objects. According to the documentation:
The HttpServletRequest, HttpSession, ServletContext, and their attributes are automatically available in your templates.
There are different ways to access the Servlet context including:
$request.servletContext
$application
But if the application also exposes the context tool (which is the default), the Servlet context can also be accessed through:
$context.application
$context.servletContext
$context.request.servletContext
On a Tomcat server the Servlet context will contain the org.apache.tomcat.InstanceManager
which enables an attacker to instantiate arbitrary objects. Note that the same class (regardless of its name) is available on other servlet containers such as Jetty and similar classes are available in other servers. For example JBoss/WildFly exposes org.wildfly.extension.undertow.deployment.UndertowJSPInstanceManage
.
We can then try to run arbitrary Java code using a ScriptEngine
:
${req.getServletContext().getAttribute('org.apache.tomcat.InstanceManager').newInstance('javax.script.ScriptEngineManager').getEngineByName('js').eval("java.lang.Runtime.getRuntime().exec('touch /tmp/pwned')")}
In addition, on Spring applications a number of other Servlet context attributes may lead to remote code execution such as:
- org.springframework.web.context.WebApplicationContext.ROOT
- org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcherServlet
- org.springframework.web.context.support.ServletContextScope
Impact
This issue may lead to Remote Code Execution
.
CVE
CVE-2020-13936
Credit
This issue was discovered and reported by GHSL team member @pwntester (Alvaro Munoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include the GHSL-2020-048
in any communication regarding this issue.