Skip to content

Commit 5c95aa6

Browse files
committed
Add the new encrypted MsTds channel
1 parent f3eeb59 commit 5c95aa6

File tree

2 files changed

+101
-12
lines changed

2 files changed

+101
-12
lines changed

lib/rex/proto/ms_tds/channel.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# -*- coding: binary -*-
2+
3+
require 'bindata'
4+
5+
module Rex::Proto::MsTds
6+
class Channel
7+
include Rex::IO::StreamAbstraction
8+
9+
attr_reader :params
10+
11+
# the socket that makes the outbound connection to the SQL server
12+
attr_reader :sock
13+
14+
def initialize(opts = {})
15+
@params = Rex::Socket::Parameters.from_hash(opts)
16+
17+
# it doesn't work this way so throw an exception so that's clear
18+
raise RuntimeError.new('SSL incompatible with MsTds::Socket') if @params.ssl
19+
raise ArgumentError.new('MsTds::Socket must be TCP') if @params.proto != 'tcp'
20+
21+
@sock = Rex::Socket.create_param(@params)
22+
initialize_abstraction
23+
24+
lsock.initinfo(@sock.peerinfo, @sock.localinfo)
25+
26+
monitor_sock(@sock, sink: method(:_read_handler), name: 'MonitorLocal', on_exit: method(:_exit_handler))
27+
end
28+
29+
def write(buf, opts = {})
30+
if negotiating_ssl?
31+
Rex::IO::RelayManager.io_write_all(self.sock, [18, 0x01, buf.length + 8, 0x0000, 0x00, 0x00].pack('CCnnCC') + buf) - 8
32+
else
33+
Rex::IO::RelayManager.io_write_all(self.sock, buf)
34+
end
35+
end
36+
37+
def starttls
38+
self.lsock.starttls(params)
39+
end
40+
41+
protected
42+
43+
def negotiating_ssl?
44+
return false unless self.lsock.is_a?(Rex::Socket::SslTcp)
45+
return false if self.lsock.sslsock.state.start_with?('SSLOK')
46+
47+
true
48+
end
49+
50+
def _exit_handler
51+
self.rsock.close
52+
end
53+
54+
def _read_handler(buf)
55+
if negotiating_ssl?
56+
Rex::IO::RelayManager.io_write_all(self.rsock, buf[8..]) + 8
57+
else
58+
Rex::IO::RelayManager.io_write_all(self.rsock, buf)
59+
end
60+
end
61+
end
62+
end

lib/rex/proto/mssql/client.rb

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,39 @@ def initialize(framework_module, framework, rhost, rport = 1433, proxies = nil,
7575
@current_database = ''
7676
end
7777

78+
def connect(global = true, opts={})
79+
dossl = false
80+
if(opts.has_key?('SSL'))
81+
dossl = opts['SSL']
82+
else
83+
dossl = ssl
84+
end
85+
86+
@mstds_channel = Rex::Proto::MsTds::Channel.new(
87+
'PeerHost' => opts['RHOST'] || rhost,
88+
'PeerHostname' => opts['SSLServerNameIndication'] || opts['RHOSTNAME'],
89+
'PeerPort' => (opts['RPORT'] || rport).to_i,
90+
'LocalHost' => opts['CHOST'] || chost || "0.0.0.0",
91+
'LocalPort' => (opts['CPORT'] || cport || 0).to_i,
92+
'SSL' => dossl,
93+
'SSLVersion' => opts['SSLVersion'] || ssl_version,
94+
'SSLVerifyMode' => opts['SSLVerifyMode'] || ssl_verify_mode,
95+
'SSLKeyLogFile' => opts['SSLKeyLogFile'] || sslkeylogfile,
96+
'SSLCipher' => opts['SSLCipher'] || ssl_cipher,
97+
'Proxies' => proxies,
98+
'Timeout' => (opts['ConnectTimeout'] || connection_timeout || 10).to_i,
99+
'Context' => { 'Msf' => framework, 'MsfExploit' => framework_module }
100+
)
101+
nsock = @mstds_channel.lsock
102+
# enable evasions on this socket
103+
set_tcp_evasions(nsock)
104+
105+
# Set this socket to the global socket as necessary
106+
self.sock = nsock if (global)
107+
108+
return nsock
109+
end
110+
78111
# MS SQL Server only supports Windows and Linux
79112
def map_compile_os_to_platform(server_info)
80113
return '' if server_info.blank?
@@ -340,12 +373,12 @@ def mssql_login(user='sa', pass='', db='', domain_name='')
340373
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
341374
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification
342375
if tdsencryption == true
343-
proxy = TDSSSLProxy.new(sock, sslkeylogfile: sslkeylogfile)
344-
proxy.setup_ssl
345-
resp = proxy.send_recv(pkt)
346-
else
347-
resp = mssql_send_recv(pkt, 15, false)
376+
#proxy = TDSSSLProxy.new(sock, sslkeylogfile: sslkeylogfile)
377+
#proxy.setup_ssl
378+
#resp = proxy.send_recv(pkt)
379+
@mstds_channel.starttls
348380
end
381+
resp = mssql_send_recv(pkt, 15, false)
349382

350383
# Strip the TDS header
351384
resp = resp[3..-1]
@@ -369,13 +402,7 @@ def mssql_login(user='sa', pass='', db='', domain_name='')
369402

370403
pkt = pkt_hdr.pack("CCnnCC") + type3_blob
371404

372-
if self.tdsencryption == true
373-
resp = mssql_ssl_send_recv(pkt, proxy)
374-
proxy.cleanup
375-
proxy = nil
376-
else
377-
resp = mssql_send_recv(pkt)
378-
end
405+
resp = mssql_send_recv(pkt)
379406

380407
#SQL Server Authentication
381408
else

0 commit comments

Comments
 (0)