Class: TDSSSLProxy
- Inherits:
-
Object
- Object
- TDSSSLProxy
- Defined in:
- lib/metasploit/framework/mssql/tdssslproxy.rb
Overview
TDSSSLProxy:
SQL Server uses the TDS protocol to transmit data between clients and servers. Of course this sits on top of TCP.
By default, the TDS payload is not encrypted. However, if “force encryption” is set under the SQL Server protocol properties, it will use SSL/TLS to encrypt the TDS data. Oddly, the entire TCP stream is not encrypted (as is say for HTTPS), but instead a TDS header is put on the front of the TLS packet. As a result, the full TLS/SSL setup is done within a series of TDS payloads.
This “proxy” basically creates a fake SSL endpoint (s2) from which it can add/remove the TDS header as required. This is implemented as a socket pair (think, a bidirectional pipe), where the other end is s1:
sslsock <-> s1 <-> s2 <-> tdssock <-> target SQL Server.
(tdssock is the reference to the “sock” from the scanner module)
TO DO:
This enables brute force of a SQL Server which requires encryption. However, future updates will permit any read/write using mssql_send_recv() to use crypto if required and transparently to other MSF developers.
Cheers, JH
Constant Summary collapse
- TYPE_TDS7_LOGIN =
16
- TYPE_PRE_LOGIN_MESSAGE =
18
- STATUS_END_OF_MESSAGE =
0x01
Instance Method Summary collapse
- #cleanup ⇒ Object
-
#initialize(sock) ⇒ TDSSSLProxy
constructor
A new instance of TDSSSLProxy.
- #send_recv(pkt) ⇒ Object
- #setup_ssl ⇒ Object
- #ssl_setup_thread ⇒ Object
Constructor Details
#initialize(sock) ⇒ TDSSSLProxy
Returns a new instance of TDSSSLProxy.
41 42 43 44 |
# File 'lib/metasploit/framework/mssql/tdssslproxy.rb', line 41 def initialize(sock) @tdssock = sock @s1, @s2 = Rex::Socket.tcp_socket_pair end |
Instance Method Details
#cleanup ⇒ Object
46 47 48 49 |
# File 'lib/metasploit/framework/mssql/tdssslproxy.rb', line 46 def cleanup @running = false @t1.join end |
#send_recv(pkt) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/metasploit/framework/mssql/tdssslproxy.rb', line 60 def send_recv(pkt) @ssl_socket.write(pkt) done = false resp = "" while (not done) head = @ssl_socket.read(8) if !(head and head.length == 8) return false end # Is this the last buffer? if (head[1, 1] == "\x01" or not check_status) done = true end # Grab this block's length rlen = head[2, 2].unpack('n')[0] - 8 while (rlen > 0) buff = @ssl_socket.read(rlen) return if not buff resp << buff rlen -= buff.length end end resp end |
#setup_ssl ⇒ Object
51 52 53 54 55 56 57 58 |
# File 'lib/metasploit/framework/mssql/tdssslproxy.rb', line 51 def setup_ssl @running = true @t1 = Thread.start { ssl_setup_thread } ctx = OpenSSL::SSL::SSLContext.new(:SSLv23) ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM" @ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx) @ssl_socket.connect end |
#ssl_setup_thread ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/metasploit/framework/mssql/tdssslproxy.rb', line 90 def ssl_setup_thread while @running do res = select([@tdssock, @s2], nil, nil, 0.1) if res res[0].each do |r| # response from SQL Server for client if r == @tdssock resp = @tdssock.recv(4096) if @ssl_socket.state[0, 5] == "SSLOK" @s2.send(resp, 0) else @s2.send(resp[8..-1], 0) end end # request from client for SQL Server if r == @s2 resp = @s2.recv(4096) # SSL negotiation completed - just send it on if @ssl_socket.state[0, 5] == "SSLOK" @tdssock.send(resp, 0) # Still doing SSL else tds_pkt_len = 8 + resp.length pkt_hdr = '' pkt_hdr << [TYPE_PRE_LOGIN_MESSAGE, STATUS_END_OF_MESSAGE, tds_pkt_len, 0x0000, 0x00, 0x00].pack('CCnnCC') pkt = pkt_hdr << resp @tdssock.send(pkt, 0) end end end end end @s1.close @s2.close end |