1 Vulnerability Description
Recently, the Jira vendor released a security advisory on a template injection vulnerability in Jira Server and Jira Data Center, which could cause remote code execution when either of the following conditions is met:
- An SMTP server has been configured in Jira and the Contact Administrators Form is enabled.
- An SMTP server has been configured in Jira and an attacker has “Jira Administrators” access.
Jira is a project and issue tracking tool developed by Atlassian. It is widely used in such areas as bug tracking, customer service, requirement collection, process review, task tracking, project tracking, and agile management. The full-featured Jira is characterized by flexible configuration, ease of deployment, and diverse extensions. Considering its wide scope of application, users are advised to immediately check their installations for this vulnerability to nip the security risk in the bud.
2 Scope of Impact
- Jira 4.4.0 < 7.6.14
- Jira 7.7.0 < 7.13.5
- Jira 8.0.0 < 8.0.3
- Jira 8.1.0 < 8.1.2
- Jira 8.2.0 < 8.2.3
- Jira 7.6.14
- Jira 7.13.5
- Jira 8.0.3
- Jira 8.1.2
- Jira 8.2.3
3.1 Official Fix
The Jira vendor has released the latest versions to fix this vulnerability, which can be found at the links listed below.
Users who cannot immediately upgrade Jira can use the following temporary workaround:
- Disable the Contact Administrators Form:
- Click and select System.
- Select General Configuration.
- Click Edit Settings.
- Scroll down to the Contact Administrators Form and set it to OFF.
- Block access to the /secure/admin/SendBulkMail!default.jspa endpoint.
4 Technical Analysis
First, a payload is crafted to generate an email.
The posted data reaches the setActionProperty() method of the JiraSafeActionParameterSetter class.
The ContactAdministrators.setSubject() method is reflectively invoked to set the subject attribute of the ContactAdministrators object to the passed-in content. Then the send() method is invoked via ContactAdministrators.doExecute() to find activated administrators in the system before sending the email to such an administrator via this.sendTo(administrator).
In the sendTo() process, Jira needs to create an email queue object with the EmailBuilder() method and then put the object in the email sending queue. Owing to the queue wait time, we have to wait a while for the payload to be triggered. If the email fails to be sent, the system will attempt to send it again. Therefore, the payload can be triggered multiple times.
The method for creating a queue takes some time to explain. Simply put, it works like this: MailQueueItem item = (new EmailBuilder()).withSubject(this.subject).withBodyFromFile().addParameters().renderLater();
The withSubject() method of EmailBuilder is used to create a TemplateSources$fragment object. The parameter is the payload previously passed in. Then the renderLater() method is invoked to create an EmailBuilder object, which, as a parameter, is then passed to the RenderingMailQueueItem class (its inheritance relationship is shown in the following figure). Finally, a MailQueueItem object is created and put in the email sending queue.
After we inject the payload into a template, the email enters the to-be-sent queue. In Jira, the process of handling email queues is as follows:
Use the templating engine (getTemplatingEngine) to generate a Velocity template and use the applying() method to generate a RenderRequest object. For different source (member variable) types of objects, different methods are invoked to parse the template. The vulnerability in question stems from this difference. Following is a detailed analysis of this process.
First, use the RenderingMailQueueItem().send() method to invoke the this.emailRenderer.render() method, and then invoke this.getTemplatingEngine().render(this.subjectTemplate).applying(contextParams).asPlainText();.
In this process, the first steps are for obtaining the templating engine (VelocityTemplatingEngine) and passing the subject template (here it is the payload data), and then using the applying() method to create a VelocityContext object and populating the payload to the member variable source.
Subsequently, the with() method of the abstract class StringRepresentation is rewritten, in which the asPlainText method is invoked:
The function of asPlainText() is to parse templates using the Velocity templating engine. The invocation chain is as follows:
In the evaluate() method, an AST structure is generated. Then the passed-in payload is reflectively invoked to complete code execution.
The invocation stack after asPlainText() is as follows:
After the Object template is processed, the send() method of the parent class SingleMailQueueItem is invoked to send the email via smtpMailServer.sendWithMessageId(). Because of improper configuration, the SMTP server will throw an exception. However, the vulnerability has already been triggered before connection to the SMTP server. The MailQueue execution process is also visible to the console.
The complete vulnerability exploitation process is as such. However, a critical problem is still unclear: Why is the email subject parsed into an AST structure and finally executed? According to the normal feedback sending logic, the subject (string) of an email does not need to be parsed into AST. What caused this variance?
Let’s walk through the process again by sending a normal “contact administrators” email.
When normal feedback is sent, this.getVe().mergeTemplate is invoked in writeEncodedBody(). The template file (templates/email/html/contactadministrator.vm) is loaded via the getResourceStream() method of the ClasspathResourceLoader() class of the Velocity engine. Subsequently, the header and footer are loaded as expected. Finally, the entire page is rendered. In contrast, when the payload is sent, the TemplateSource$Fragment object is created via asPlainText(), and this Fragment object is populated to source via the DefaultRenderRequest method. Now comes the first divergence, where this.getVe().evaluate() is invoked and finally ASTMethod.execute() is invoked. This is a different processing logic caused by the variance we mentioned before.
Let’s look back on the general Velocity rendering process: The Velocity rendering engine first loads a template file to memory, then parses this file into the AST structure and initializes each node in the AST. When the same template file needs to be loaded later, if the cache is enabled, the template will directly be returned. This way of utilizing cached resources reduces the overhead for loading files from disks and parsing them into AST again.
The ASTMethod.execute() method is originally designed to complete normal template rendering actions, such as obtaining the background color, text content, and page code, via reflective invocation in the process of Velocity parsing templates. However, via carefully crafted data, an attacker ingeniously exploits this vulnerability to have java.lang.Runtime.getRuntime executed via reflective invocation, leading to command execution.
This advisory is only used to describe a potential risk. NSFOCUS does not provide any commitment or promise on this advisory. NSFOCUS and the author will not bear any liability for any direct and/or indirect consequences and losses caused by transmitting and/or using this advisory. NSFOCUS reserves all the rights to modify and interpret this advisory. Please include this statement paragraph when reproducing or transferring this advisory. Do not modify this advisory, add/delete any information to/from it, or use this advisory for commercial purposes without permission from NSFOCUS.
NSFOCUS, Inc., a global network and cyber security leader, protects enterprises and carriers from advanced cyber attacks. The company’s Intelligent Hybrid Security strategy utilizes both cloud and on-premises security platforms, built on a foundation of real-time global threat intelligence, to provide multi-layered, unified and dynamic protection against advanced cyber attacks.
NSFOCUS works with Fortune Global 500 companies, including four of the world’s five largest financial institutions, organizations in insurance, retail, healthcare, critical infrastructure industries as well as government agencies. NSFOCUS has technology and channel partners in more than 60 countries, is a member of both the Microsoft Active Protections Program (MAPP), and the Cloud Security Alliance (CSA).
A wholly owned subsidiary of NSFOCUS Information Technology Co. Ltd., the company has operations in the Americas, Europe, the Middle East and Asia Pacific.