-
Notifications
You must be signed in to change notification settings - Fork 14.4k
SMBv3 integration with Framework #13417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@msjenkins-r7 test this please. |
1 similar comment
@msjenkins-r7 test this please. |
73e1408
to
6bff45c
Compare
@cdelafuente-r7 would you be able to please rebase / retarget this for merging into the |
Sure! I retargeted the PR. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good, I'll move on to testing as many of the modules as I can.
@@ -144,17 +165,23 @@ def smb_login(simple_client = self.simple) | |||
datastore['SMB::Native_LM'], | |||
{:use_spn => datastore['NTLM::SendSPN'], :name => self.rhost} | |||
) | |||
# XXX: Any reason to connect to the IPC$ share in this method? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing it has to do with:
When the named pipe is being created, the process specifies the security that is associated with the pipe, and then makes sure that access is only granted to the specified users or groups.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, $IPC
is just a special share that enables named pipe connections to the server. It should only be necessary when a named pipe is needed (e.g. DCERPC requests). Security is set on the named pipe and not on the $IPC
share.
I noticed that when a module needs to connect to a named pipe, it usually connects to the $IPC
share right after smb_login
, which creates a duplicate connection to $IPC
. This first connection to $IPC
is never closed.
After think about it, it might be some kind of "keep-alive" trick. Having an active connection to the $IPC
share maybe help to avoid a server timeout if the SMB session is not used. I will need to run some tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested against different Windows version (2008R2, 2012, 2016 and 2019) and the behavior remains the same regarding this connection to $IPC
share is established or not: after the session is setup, the server sends a TCP keepalive packets every 2 minutes and RST after 7 attempts.
I would be inclined to remove it.
- multiple protocol version negotiation - SMB 1, 2 and 3 by default - add SMB::ProtocolVersion option to SMB Client mixin
- Add SMB::AlwaysEncrypt option - Force SMB1 for SMB fingerprint - Update smb_netshareenumall
- smb_ms17_010.rb - psexec_ms17_010.rb - psexec_psh.rb - smb_enumshares.rb
- modules/auxiliary/scanner/smb/smb_enumshares.rb - modules/exploits/linux/samba/setinfopolicy_heap.rb - modules/exploits/linux/samba/trans2open.rb - modules/exploits/multi/samba/usermap_script.rb - modules/exploits/windows/smb/ipass_pipe_exec.rb
- ms17_010_command and ms17_010_psexec: deregister SMB::ProtocolVersion option - client: update error handling - is_known_pipename: force SMB1 only for #enumerate_directories and update error handling
That error on Windows 8.1x86 is consistent.....
|
When I drop the SMB version to [1,2], I get a response from the Windows 8.1 x86 machines:
Logs:
|
I could successfully reproduce this with an out-of-the-box Windows 8.1 (x86). My first assumption was that SMB3 dialects < 3.1.1 don't support session encryption and only per-share encryption as described here. However, after updating the OS (Windows Update), it appears to work properly. I read the protocol again and found out my assumption was wrong, 3.0.0 and 3.0.2 dialects also support session and per-share encryptions, like 3.1.1. So, out-of-the-box Windows 8 does not comply with the protocol. Actually, without updating the OS, SMB3 does not work properly in the first place. Do you mind trying again with an updated Windows 8, if possible? |
Yup..... after update, all targets respond
Log
|
Awesome! Thank you for testing @bwatters-r7 . Can we reasonably say that no change is needed since the updated version works fine? |
I really dislike the error, even if it might not be on us. Is there any moderately easy way we could be more descriptive or recognize this particular error as a subclass of a reset? |
I've tested some SMB aux scanner modules. OSX doesn't work for me. Windows works better, but some of the modules don't work as expected for me. OSX TestingTargetI set up a local share for this and a new test account for smb sharing
This originally gave me:
With the latest
Logs:
Note that impacket works fine in this scenario. WindowsTargetTested on some HTB the boxes. The below reports are from HTB monteverde -
scanner/smb/smb_enumsharesWorks as expected:
scanner/smb/smb_enumusersWorks as exepcted:
scanner/smb/smb_login
scanner/smb/smb_versionDoesn't appear to work:
Log:
smb_checks.rcCurrently broken due to smb login above:
|
@adfoster-r7, thanks for testing again, really appreciated. It looks like it is also broken on MSF master branch. I tracked down the issue and had to update this:
However, it appears that Mac OS X cares about it and fails with
However, Windows just ignores it, but Mac OS X follows the specs and fails with So, I will update these two things, unless someone is against it. Regarding
When no domain is used (local user), it is substituted by Regarding |
- Update the SimpleClient#create_pipe permission from 'c' (FILE_OPEN_IF disposition: Open the file if it already exists; otherwise, create the file) to 'o' (FILE_OPEN disposition: If the file already exists, return success; otherwise, fail the operation). - Remove the random offset in Rex::Proto::DCERPC::Client#write (evasion). This is strictly prohibited by the protocol and break on MAC OS X
@@ -136,7 +136,7 @@ Gem::Specification.new do |spec| | |||
spec.add_runtime_dependency 'net-ssh' | |||
spec.add_runtime_dependency 'ed25519' # Adds ed25519 keys for net-ssh | |||
spec.add_runtime_dependency 'bcrypt_pbkdf' | |||
spec.add_runtime_dependency 'ruby_smb', '~> 1.1' | |||
spec.add_runtime_dependency 'ruby_smb', '~> 2.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Gemfile.lock
need updated too? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, absolutely. When this PR gets merged, we will release a new version of ruby_smb
and I will update the gemspec
file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! ruby_smb
version 2.0.1
has been released and incorporates the referenced changes.
@bwatters-r7, @adfoster-r7, I pushed some Thanks again for all the testing you've done! |
OSX share enumeration works for me now 🎉 Just testing some additional SMB module, everything seems pretty good to me WIndows testingadmin/smb/check_dir_fileWorks as expected
Log:
admin/smb/download_fileWith a folder
Correctly handling error scenario:
Correctly handled error logs:
With a fileSetting a real file:
Log:
modules/auxiliary/admin/smb/list_directoryThis module seems to fail due to needing smb 1 support?
|
@@ -55,7 +56,7 @@ def as_size( s ) | |||
def run | |||
print_status("Connecting to the server...") | |||
begin | |||
connect() | |||
connect(versions: [1]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for context; Why do we need to change this to version 1 here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This module uses a method that is only implemented in the Rex SMB client (find_first
). It also extracts information from the raw Rex response. Forcing to version 1 will ensure it will use Rex SMB client and not RubySMB client.
This module will need to be redesigned to be able to use RubySMB by default (like many others). This will be taken care of, in the next iteration of this project.
I don't think it's a concern for this PR, but just as visibility I also tested this out with impacket's smb server and I wasn't able to connect successfully.
After spinning up the server:
I confirmed connecting with impacket’s client just fine:
But msfconsole’s enum shares doesn’t work:
I can’t immediately tell if that’s a problem with msfconsole or impacket server - I didn't look any further, but just posting for visibility 👍 |
I was trying to download a file from a share with a Options:
Result:
Backtrace
|
Windows 7 testingTesting SMB v1 + v2 on windows 7 target
From tryhackme's blue box
Passexploit/windows/smb/ms17_010_eternalblueAfter a couple of fails, eventually a win:
scanner/smb/smb_enumusers
scanner/smb/smb_enumshares
scanner/smb/smb_ms17_010Success
auxiliary/scanner/smb/smb_login
Failscanner/smb/smb_enumusers_domainFailed
scanner/smb/smb_enum_gppFailed
|
I ran some tests and found out that the However, this is not enough to have it working with impacket. This time, it looks like an impacket issue: it does not add the We can still update RubySMB to accept this and parse the response even if extended information is missing. But, I'm wondering if it is worth the effort since the issue looks like to be on the impacket side. |
I couldn't reproduce the issue with a share name containing a quote. However, I checked the single quote from your comment and it is actually a weird encoded character: |
@cdelafuente-r7 OSX has a habbit of using |
@adfoster-r7, thanks again for testing. Regarding the failed tests against Window 7:
This module seems to work when testing against 445/TCP. The error message is related to the first try against 139/TCP (NetBios). The module does not set
This module is set to use Rex SMB client only. This error shows that the All these old modules will need to be redesigned/refactored to be able to use RubySMB by default. |
That's interesting, I got different results if I run a Pry session directly or within MSF:
|
OK..... here are some older OSs for backward compatibility....
|
Windows 2000 SP3 does not appear to work (this is not a regression, as it does the exact same thing on master):
The password I'm using is correct and I can browse a fileshare hosted on this VM from a Windows XP VM using the username/password I proved the scanner. |
It looks like all outstanding issues have been resolved. I updated the I'm going to go ahead and merge this into 6.x. Thanks @cdelafuente-r7 for all of your work on this and thanks to everyone who helped test it out! |
Release NotesAdded SMB v3 support for client operations to the Metasploit Framework. Modules which already used the new SMB client will now be capable of connecting to servers with all three SMB v3 dialects (3.0, 3.0.2, 3.1.1). In cases where an SMB 3.x dialect is negotiated, the default behavior will be to encrypt the communications to the server (users can disable this by setting |
This adds SMBv3 support to Framework by including the latest changes to the
ruby_smb
library.It depends on this PR to be merged.EDIT: The
ruby_smb
PR is merged now.This also adds two new options for the SMB client:
SMB::ProtocolVersion
: One or a list of comma-separated SMB protocol versions to negotiate (e.g. "1" or "1,2" or "2,3,1")SMB::AlwaysEncrypt
: Enforces encryption even if the server does not require it (SMB3.x only). Note that when it is set to false, the SMB client will still encrypt the communication if the server requires itOne of the biggest changes is that
ruby_smb
is now the default client, which means SMB versions 1, 2 and 3 are automatically negotiated, unless specified otherwise. Some modules still requireRex
SMB client and were updated to force its use. As a consequence, these modules will only be able to use SMBv1.Verification Steps
Windows target setup
To get the current configuration state of the SMB server, run this in Powershell:
To disable SMBv1, run this in an elevated Powershell:
To disable SMBv2 and SMBv3 (it is not possible to disable one separately), run this in an elevated Powershell:
Change
$false
to$true
to re-enable the protocol versions using the same Powershell command.To require encryption on the server (SMB3), run this in an elevated Powershell:
To enable per-share encryption on the server (SMB3), run this in an elevated Powershell:
Samba target setup
The easiest way is to use docker and dperson/samba.
The following command will create and start a container running on ports 139 and 445, with user
smbuser
(password123456
) and with a share calledhome
(sharing local path/share
). Note that-S
will disable SMB2 minimum version, which means SMB1 will be available. Remove it if you don't want SMB1 support.Monitoring setup
I recommend using Wireshark filtering port 139 and 445 with displaying only SMB packets:
tcp port 445 || tcp port 139
smb||smb2
Also, open a separate terminal to check the logs:
Tests
Example with
modules/auxiliary/scanner/smb/smb_enumusers
module.Verify the SMB version that has been negotiated in the logs:
In this case, the client asked for version 1, 2 or 3 and the server picked SMBv3. The communication should be encrypted by default. You can verify this in a Wireshark:
Note that encryption should occur only after the session setup.
You can test the two new options (when available):
Test SMBv1 only:
Verify the log shows the correct version:
Verify the packet capture shows only SMB1 packets.
Test SMBv1 and SMBv2:
Verify the log shows the correct version:
Verify the packet capture shows only SMB2 packets.
Disable SMB2 (see Windows target setup) and re-run the test.
Verify the log shows the correct version:
Verify the packet capture shows only SMB1 packets.
Try other combinations
Test SMB3 without encryption (SMB3 and encryption should be enabled on the server):
Verify the SMB version that has been negotiated in the logs:
Verify the packet capture shows only SMB3 packets without encryption.