Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/metasploit/framework/mssql/tdssslproxy.rb
Views: 11784
# -*- coding: binary -*-12require 'openssl'34#5# TDSSSLProxy:6#7# SQL Server uses the TDS protocol to transmit data between clients and8# servers. Of course this sits on top of TCP.9#10# By default, the TDS payload is not encrypted. However, if "force11# encryption" is set under the SQL Server protocol properties, it will12# use SSL/TLS to encrypt the TDS data. Oddly, the entire TCP stream is13# not encrypted (as is say for HTTPS), but instead a TDS header is14# put on the front of the TLS packet. As a result, the full TLS/SSL15# setup is done within a series of TDS payloads.16#17# This "proxy" basically creates a fake SSL endpoint (s2) from which it18# can add/remove the TDS header as required. This is implemented as a19# socket pair (think, a bidirectional pipe), where the other end is s1:20#21# sslsock <-> s1 <-> s2 <-> tdssock <-> target SQL Server.22#23# (tdssock is the reference to the "sock" from the scanner module)24#25# TO DO:26#27# This enables brute force of a SQL Server which requires encryption.28# However, future updates will permit any read/write using29# mssql_send_recv() to use crypto if required and transparently to30# other MSF developers.31#32# Cheers, JH3334class TDSSSLProxy3536TYPE_TDS7_LOGIN = 1637TYPE_PRE_LOGIN_MESSAGE = 1838STATUS_END_OF_MESSAGE = 0x013940def initialize(sock)41@tdssock = sock42@s1, @s2 = Rex::Socket.tcp_socket_pair43end4445def cleanup46@running = false47@t1.join48end4950def setup_ssl51@running = true52@t1 = Thread.start { ssl_setup_thread }53ctx = OpenSSL::SSL::SSLContext.new(:SSLv23)54ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM"55@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx)56@ssl_socket.connect57end5859def send_recv(pkt)60@ssl_socket.write(pkt)61done = false62resp = ""6364while (not done)65head = @ssl_socket.read(8)66if !(head and head.length == 8)67return false68end6970# Is this the last buffer?71if (head[1, 1] == "\x01" or not check_status)72done = true73end7475# Grab this block's length76rlen = head[2, 2].unpack('n')[0] - 87778while (rlen > 0)79buff = @ssl_socket.read(rlen)80return if not buff81resp << buff82rlen -= buff.length83end8485end86resp87end8889def ssl_setup_thread90while @running do91res = select([@tdssock, @s2], nil, nil, 0.1)92if res93res[0].each do |r|94# response from SQL Server for client95if r == @tdssock96resp = @tdssock.recv(4096)97if @ssl_socket.state[0, 5] == "SSLOK"98@s2.send(resp, 0)99else100@s2.send(resp[8..-1], 0)101end102end103104# request from client for SQL Server105if r == @s2106resp = @s2.recv(4096)107# SSL negotiation completed - just send it on108if @ssl_socket.state[0, 5] == "SSLOK"109@tdssock.send(resp, 0)110# Still doing SSL111else112tds_pkt_len = 8 + resp.length113pkt_hdr = ''114pkt_hdr << [TYPE_PRE_LOGIN_MESSAGE, STATUS_END_OF_MESSAGE, tds_pkt_len, 0x0000, 0x00, 0x00].pack('CCnnCC')115pkt = pkt_hdr << resp116@tdssock.send(pkt, 0)117end118end119end120end121end122@s1.close123@s2.close124end125end126127128129