Squashed more commits back into 1

bug/bundler_fix
Jonathan Harms 2015-06-23 21:37:08 +09:30 committed by Louis Sato
parent 675100946b
commit 5266860cec
5 changed files with 133 additions and 47 deletions

View File

@ -32,6 +32,11 @@ module Metasploit
validates :windows_authentication,
inclusion: { in: [true, false] }
attr_accessor :tdsencryption
validates :tdsencryption,
inclusion: { in: [true, false] }
def attempt_login(credential)
result_options = {
credential: credential,
@ -70,6 +75,7 @@ module Metasploit
self.use_ntlm2_session = true if self.use_ntlm2_session.nil?
self.use_ntlmv2 = true if self.use_ntlmv2.nil?
self.windows_authentication = false if self.windows_authentication.nil?
self.tdsencryption = false if self.tdsencryption.nil?
end
end

View File

@ -49,12 +49,6 @@ module Metasploit
disconnect if self.sock
connect
# Send a prelogin packet and check that encryption is not enabled
#if mssql_prelogin() != ENCRYPT_NOT_SUP
# raise ::Rex::ConnectionError, "Encryption is not supported"
#end
mssql_prelogin()
if windows_authentication
@ -153,7 +147,14 @@ module Metasploit
# has a strange behavior that differs from the specifications
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification
resp = mssql_send_recv(pkt,15, false)
if tdsencryption == true
proxy = TDSSSLProxy.new(sock)
proxy.setup_ssl()
resp = proxy.send_recv(pkt)
else
resp = mssql_send_recv(pkt)
end
# Get default data
begin
@ -202,13 +203,13 @@ module Metasploit
pkt = pkt_hdr.pack("CCnnCC") + ntlmssp
#resp = mssql_send_recv(pkt)
proxy = TDSSSLProxy.new(sock)
proxy.setup_ssl()
resp = mssql_ssl_send_recv(pkt,proxy)
proxy.cleanup
proxy = nil
if self.tdsencryption == true
resp = mssql_ssl_send_recv(pkt,proxy)
proxy.cleanup
proxy = nil
else
resp = mssql_send_recv(pkt)
end
#SQL Server Authentification
else
@ -290,12 +291,16 @@ module Metasploit
# Packet header and total length including header
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
#resp = mssql_send_recv(pkt)
proxy = TDSSSLProxy.new(sock)
proxy.setup_ssl()
resp = mssql_ssl_send_recv(pkt,proxy)
proxy.cleanup
proxy = nil
if self.tdsencryption == true
proxy = TDSSSLProxy.new(sock)
proxy.setup_ssl()
resp = mssql_ssl_send_recv(pkt,proxy)
proxy.cleanup
proxy = nil
else
resp = mssql_send_recv(pkt)
end
end
info = {:errors => []}
@ -598,8 +603,14 @@ module Metasploit
]
version = [0x55010008,0x0000].pack("Vv")
encryption = ENCRYPT_NOT_SUP # off
encryption = ENCRYPT_ON
# if manually set, we will honour
if tdsencryption == true
encryption = ENCRYPT_ON
else
encryption = ENCRYPT_NOT_SUP
end
instoptdata = "MSSQLServer\0"
threadid = "\0\0" + Rex::Text.rand_text(2)
@ -652,12 +663,57 @@ module Metasploit
if idx > 0
encryption_mode = resp[idx,1].unpack("C")[0]
else
#force to ENCRYPT_NOT_SUP and hope for the best
raise RunTimeError, "Unable to parse encryption req. "\
"from server during prelogin()"
encryption_mode = ENCRYPT_NOT_SUP
end
if encryption_mode != ENCRYPT_NOT_SUP and enc_error
raise RuntimeError,"Encryption is not supported"
##########################################################
# Our initial prelogin pkt above said we didnt support
# encryption (it's quicker and the default).
#
# Per the matrix on the following link, SQL Server will
# terminate the connection if it does require TLS,
# otherwise it will accept an unencrypted session. As
# part of this initial response packet, it also returns
# ENCRYPT_REQ.
#
# https://msdn.microsoft.com\
# /en-us/library/ee320519(v=sql.105).aspx
#
##########################################################
if encryption_mode == ENCRYPT_REQ
# restart prelogin process except that we tell SQL Server
# than we are now able to encrypt
disconnect if self.sock
connect
# offset 35 is the flag - turn it on
pkt[35] = [ENCRYPT_ON].pack('C')
self.tdsencryption = true
framework_module.print_status("TLS encryption has " \
"been enabled based on server response.")
resp = mssql_send_recv(pkt)
idx = 0
while resp and resp[0,1] != "\xff" and resp.length > 5
token = resp.slice!(0,5)
token = token.unpack("Cnn")
idx -= 5
if token[0] == 0x01
idx += token[1]
break
end
end
if idx > 0
encryption_mode = resp[idx,1].unpack("C")[0]
else
raise RuntimeError, "Unable to parse encryption "\
"req during pre-login"
end
end
encryption_mode
end

View File

@ -1,25 +1,46 @@
# -*- coding: binary -*-
require 'openssl'
require 'socket'
require 'msf/core'
require 'msf/core/exploit/mssql_commands'
#
# 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
class TDSSSLProxy
@s1 = 0 # write ssl to this sock
@s2 = 0 # demux the unencrypted stream on this sock
@tdssock = 0
@sslsock = 0
@t1 = 0
TYPE_TDS7_LOGIN = 16
TYPE_PRE_LOGIN_MESSAGE = 18
STATUS_END_OF_MESSAGE = 0x01
def initialize(sock)
@tdssock = sock
@s1,@s2 = Socket.pair(:UNIX,:STREAM,0)
@s1,@s2 = Rex::Socket.tcp_socket_pair()
end
def cleanup()
@ -27,7 +48,7 @@ class TDSSSLProxy
end
def setup_ssl
@t1 = Thread.start { ssl_setup_thread(@s2) }
@t1 = Thread.start { ssl_setup_thread() }
ssl_context = OpenSSL::SSL::SSLContext.new(:TLSv1)
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ssl_context)
@ssl_socket.connect
@ -39,7 +60,7 @@ class TDSSSLProxy
resp = ""
while(not done)
head = @ssl_socket.sysread(8)
head = @ssl_socket.read(8)
if !(head and head.length == 8)
return false
end
@ -53,7 +74,7 @@ class TDSSSLProxy
rlen = head[2,2].unpack('n')[0] - 8
while(rlen > 0)
buff = @ssl_socket.sysread(rlen)
buff = @ssl_socket.read(rlen)
return if not buff
resp << buff
rlen -= buff.length
@ -63,25 +84,25 @@ class TDSSSLProxy
resp
end
def ssl_setup_thread(s_two)
def ssl_setup_thread()
while true do
res = select([@tdssock,s_two],nil,nil)
res = select([@tdssock,@s2],nil,nil)
for r in res[0]
# response from SQL Server for client
if r == @tdssock
resp = @tdssock.recv(4096)
if @ssl_socket.state[0,5] == "SSLOK"
s_two.send(resp,0)
@s2.send(resp,0)
else
s_two.send(resp[8..-1],0)
@s2.send(resp[8..-1],0)
end
end
# request from client for SQL Server
if r == s_two
resp = s_two.recv(4096)
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)
@ -89,7 +110,6 @@ class TDSSSLProxy
else
tds_pkt_len = 8 + resp.length
pkt_hdr = ''
pkt = ''
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)

View File

@ -69,7 +69,7 @@ module Exploit::Remote::MSSQL
Opt::RPORT(1433),
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', false]),
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentification (requires DOMAIN option set)', false]),
], Msf::Exploit::Remote::MSSQL)
register_advanced_options(

View File

@ -3,7 +3,6 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/mssql'
@ -32,6 +31,10 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
print_status("#{rhost}:#{rport} - MSSQL - Starting authentication scanner.")
if datastore['TDSENCRYPTION']
print_status("Manually enabled TLS/SSL to encrypt TDS payloads.")
end
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
@ -56,6 +59,7 @@ class Metasploit3 < Msf::Auxiliary
max_send_size: datastore['TCP::max_send_size'],
send_delay: datastore['TCP::send_delay'],
windows_authentication: datastore['USE_WINDOWS_AUTHENT'],
tdsencryption: datastore['TDSENCRYPTION'],
framework: framework,
framework_module: self,
ssl: datastore['SSL'],