-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Support Encrypted MSSQL Sessions #20677
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
a6c4485 to
750e664
Compare
| def dio_close_handler(packet) | ||
| rsock.close | ||
|
|
||
| return super(packet) | ||
| end |
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 was removed because the #close method is no longer replaced with something that'd close the channel. The original logic was prone to creating recursion loops during development and would send a close command back to Meterpreter when Meterpreter initiated the close operation.
The new implementation should simply things by always closing the channel from the channel object level instead of the rsock. Now when a channel is closed by Meterpreter, the #dio_close_handler will simply close and cleanup the channel locally without echoing the command back to Meterpreter.
When the channel is closed by Metasploit Framework, it's either closed by lsock.close which causes an EOF to be read in the Relay Manager which will dispatch to the on_exit callback, which by default calls #close_write. Alternatively, the channel object can be closed directly, but there's no longer a loop as everything is notified.
|
I started work on a test module for testing socket channels (TCP client, TCP server and UDP). It's a WIP, but can be used for testing here: https://github.com/zeroSteiner/metasploit-framework/blob/feat/mod/socket-channel-tests/test/modules/post/test/socket_channels.rb I think it probably makes sense to keep it in a separate branch and PR it on its own especially if there are pre-existing issues and inconsistencies. Preview |
750e664 to
8c5fc07
Compare
|
I managed to rebase this after the socket channel tests were landed. This should be unblocked and ready for review now. |
1b01451 to
865aca3
Compare
|
Now this has been rebased again to include the relaying code. The combo here enables relaying NTLM to servers that require TLS connections. |
jheysel-r7
left a comment
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.
Great work @zeroSteiner. Everything is working as expected.
Thanks for pushing changes to the Gemfiles to make for easy testing 🙏
Testing
MSSQL encrypted authentication working:
msf auxiliary(scanner/mssql/mssql_login) > run
[*] 172.16.199.131:1433 - MSSQL - Starting authentication scanner.
[*] 172.16.199.131:1433 - TDS Encryption enabled
[!] No active DB -- Credential data will not be saved!
[+] 172.16.199.131:1433 - Login Successful: KERBEROS\Administrator:N0tpassword!
[*] 172.16.199.131:1433 - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.131:1433 - Bruteforce completed, 1 credential was successful.
[*] 172.16.199.131:1433 - You can open an MSSQL session with these credentials and CreateSession set to true
[*] Auxiliary module execution completed
Encrypted SMB to MSSQL relay working:
msf auxiliary(server/relay/smb_to_mssql) > set rhosts 172.16.199.131
rhosts => 172.16.199.131
msf auxiliary(server/relay/smb_to_mssql) > run
[*] Auxiliary module running as background job 0.
msf auxiliary(server/relay/smb_to_mssql) >
[*] SMB Server is running. Listening on 0.0.0.0:445
[*] Server started.
[*] New request from 172.16.199.200
[*] Received request for \Administrator
[*] Relaying to next target mssql://172.16.199.131:1433
[*] TLS encryption has been enabled based on server response.
[+] Identity: \Administrator - Successfully authenticated against relay target mssql://172.16.199.131:1433
[SMB] NTLMv1-SSP Client : 172.16.199.131
[SMB] NTLMv1-SSP Username : \Administrator
[SMB] NTLMv1-SSP Hash : Administrator:::59ebf02d1dc00f5b00000000000000000000000000000000:d63ca2db774f8cdfff351d142ad023e890ad6b124f02261a:82d8300f1243a3c4
[+] Relay succeeded
[*] MSSQL session 1 opened (172.16.199.1:51281 -> 172.16.199.131:1433) at 2025-12-02 09:57:40 -0800
[*] Received request for \Administrator
[*] Identity: \Administrator - All targets relayed to
[*] New request from 172.16.199.200
[*] Received request for KERBEROS\Administrator
[*] Relaying to next target mssql://172.16.199.131:1433
[*] TLS encryption has been enabled based on server response.
[+] Identity: KERBEROS\Administrator - Successfully authenticated against relay target mssql://172.16.199.131:1433
[SMB] NTLMv1-SSP Client : 172.16.199.131
[SMB] NTLMv1-SSP Username : KERBEROS\Administrator
[SMB] NTLMv1-SSP Hash : Administrator::KERBEROS:27b938bb1e684cf700000000000000000000000000000000:9503699648f3bdc2b9d69919134a2682016f56d2e8295f85:4c197f51b006836a
[+] Relay succeeded
[*] MSSQL session 2 opened (172.16.199.1:51298 -> 172.16.199.131:1433) at 2025-12-02 09:57:42 -0800
[*] Received request for KERBEROS\Administrator
[*] Identity: KERBEROS\Administrator - All targets relayed to
Pivoted TCP client channel I/O works in both directions.
Both have the ability to close the connection:

PosgreSQL over SSL working:
msf auxiliary(scanner/postgres/postgres_login) > set createsession true
createsession => true
msf auxiliary(scanner/postgres/postgres_login) > set ssl true
ssl => true
msf auxiliary(scanner/postgres/postgres_login) > run
[!] 172.16.199.136:5432 - No active DB -- Credential data will not be saved!
[+] 172.16.199.136:5432 - 172.16.199.136:5432 - Login Successful: msfuser:testpass@msfdb
[*] PostgreSQL session 8 opened (172.16.199.1:52048 -> 172.16.199.136:5432) at 2025-12-02 11:31:40 -0800
[*] 172.16.199.136:5432 - Scanned 1 of 1 hosts (100% complete)
[*] 172.16.199.136:5432 - Bruteforce completed, 1 credential was successful.
[*] 172.16.199.136:5432 - 1 Postgres session was opened successfully.
[*] Auxiliary module execution completed
d53f42c to
c425f15
Compare
Release NotesThis enables sessions to MSSQL servers that require encryption. These changes add a new MsTds::Channel which leverages Rex's socket abstraction to facilitate the necessary encapsulation for the TLS negotiation. |
This enables sessions to MSSQL servers that require encryption. Currently, Metasploit can bruteforce MSSQL servers that offer/require encryption because our login method will proxy the traffic over an SSL socket using the old
TDSSSLProxyclass. The existing logic didn't support sessions though, so when a user wanted encryption (setSSLto true) or the server required it, Metasploit would fail to establish an interactive session or do anything after the login operation. Metasploit was effecitvely unable to communicate with the MSSQL server after the login operation when encryption was requried or enabled.These changes add a new
MsTds::Channelwhich leverages Rex's socket abstraction to facilitate the necessary encapsulation for the TLS negotiation. The TLS negotiation is more complex than other protocols because the frames used during the negotiation process have to be encapsulated within MS-TDS framing. Once TLS is established, the MS-TDS frames are within the tunnel. This encapsulation can be seen in theMsTds::Channelclass#writeand#_read_handlermethods.The
MsTds::Channelhas a couple of advantages over the old proxy class. The first is the channel object is now always used for the communication, there's no need to switch to writing to the proxy object or swap sockets instead when SSL is in use. The second is that it's using the newRex::Proto::Tcp#starttlsmethod which ensures that the TLS options are consistent with other usages in the framework.Requires:
monitor_sockcan be used with the callbacks#starttlsmethodCloses #18745
Verification
MsTds::Channelobjectmssql_loginmodule to authenticate to it and establish an interactive sessionmsfconsoleprompt, notmeterpreter, use theconnectcommand and the-cargument to specify the session object, connect to a netcat listenerCtrl+Cfrom Metasploit, repeat the connection setup and terminate it from the netcat listenerMsTds::Channelby closing the connection from the MSSQL server using theKILLquery verb just know that theKILLquery can't be used to kill the connection that's making the query.#starttlsmethod)