diff --git a/examples/mssqlclient.py b/examples/mssqlclient.py index f6f49fa815..e7468c4162 100755 --- a/examples/mssqlclient.py +++ b/examples/mssqlclient.py @@ -35,7 +35,6 @@ parser = argparse.ArgumentParser(add_help = True, description = "TDS client implementation (SSL supported).") parser.add_argument('target', action='store', help='[[domain/]username[:password]@]') - parser.add_argument('-port', action='store', default='1433', help='target MSSQL port (default 1433)') parser.add_argument('-db', action='store', help='MSSQL database instance (default None)') parser.add_argument('-windows-auth', action='store_true', default=False, help='whether or not to use Windows ' 'Authentication (default False)') @@ -52,8 +51,16 @@ 'ones specified in the command line') group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' '(128 or 256 bits)') + + group = parser.add_argument_group('connection') + group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) specified in the target parameter') + group.add_argument('-target-ip', action='store', metavar = "ip address", + help='IP Address of the target machine. If omitted it will use whatever was specified as target. ' + 'This is useful when target is the NetBIOS name and you cannot resolve it') + group.add_argument('-port', action='store', default='1433', help='target MSSQL port (default 1433)') + if len(sys.argv)==1: parser.print_help() @@ -68,7 +75,7 @@ else: logging.getLogger().setLevel(logging.INFO) - domain, username, password, address = parse_target(options.target) + domain, username, password, remoteName = parse_target(options.target) if domain is None: domain = '' @@ -77,10 +84,13 @@ from getpass import getpass password = getpass("Password:") + if options.target_ip is None: + options.target_ip = remoteName + if options.aesKey is not None: options.k = True - ms_sql = tds.MSSQL(address, int(options.port)) + ms_sql = tds.MSSQL(options.target_ip, int(options.port), remoteName) ms_sql.connect() try: if options.k is True: diff --git a/impacket/tds.py b/impacket/tds.py index c0447d3350..2c71b97e50 100644 --- a/impacket/tds.py +++ b/impacket/tds.py @@ -459,10 +459,11 @@ class TDS_COLMETADATA(Structure): ) class MSSQL: - def __init__(self, address, port=1433, rowsPrinter=DummyPrint()): + def __init__(self, address, port=1433, remoteName = '', rowsPrinter=DummyPrint()): #self.packetSize = 32764 self.packetSize = 32763 self.server = address + self.remoteName = remoteName self.port = port self.socket = 0 self.replies = {} @@ -650,7 +651,6 @@ def recvTDS(self, packetSize = None): return packet def kerberosLogin(self, database, username, password='', domain='', hashes=None, aesKey='', kdcHost=None, TGT=None, TGS=None, useCache=True): - if hashes is not None: lmhash, nthash = hashes.split(':') lmhash = binascii.a2b_hex(lmhash) @@ -663,7 +663,6 @@ def kerberosLogin(self, database, username, password='', domain='', hashes=None, # Test this! if resp['Encryption'] == TDS_ENCRYPT_REQ or resp['Encryption'] == TDS_ENCRYPT_OFF: LOG.info("Encryption required, switching to TLS") - # Switching to TLS now ctx = SSL.Context(SSL.TLS_METHOD) ctx.set_cipher_list('ALL:@SECLEVEL=0'.encode('utf-8')) @@ -690,7 +689,7 @@ def kerberosLogin(self, database, username, password='', domain='', hashes=None, login['HostName'] = (''.join([random.choice(string.ascii_letters) for _ in range(8)])).encode('utf-16le') login['AppName'] = (''.join([random.choice(string.ascii_letters) for _ in range(8)])).encode('utf-16le') - login['ServerName'] = self.server.encode('utf-16le') + login['ServerName'] = self.remoteName.encode('utf-16le') login['CltIntName'] = login['AppName'] login['ClientPID'] = random.randint(0,1024) login['PacketSize'] = self.packetSize @@ -710,7 +709,7 @@ def kerberosLogin(self, database, username, password='', domain='', hashes=None, import datetime if useCache: - domain, username, TGT, TGS = CCache.parseFile(domain, username, 'MSSQLSvc/%s:%d' % (self.server, self.port)) + domain, username, TGT, TGS = CCache.parseFile(domain, username, 'MSSQLSvc/%s:%d' % (self.remoteName, self.port)) if TGS is None: # search for the port's instance name instead (instance name based SPN) @@ -725,7 +724,7 @@ def kerberosLogin(self, database, username, password='', domain='', hashes=None, pass if instanceName: - domain, username, TGT, TGS = CCache.parseFile(domain, username, 'MSSQLSvc/%s.%s:%s' % (self.server.split('.')[0], domain, instanceName)) + domain, username, TGT, TGS = CCache.parseFile(domain, username, 'MSSQLSvc/%s.%s:%s' % (self.remoteName.split('.')[0], domain, instanceName)) # First of all, we need to get a TGT for the user userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value) @@ -766,7 +765,7 @@ def kerberosLogin(self, database, username, password='', domain='', hashes=None, # FQDN is the fully qualified domain name of the server. # port is the TCP port number. # instancename is the name of the SQL Server instance. - serverName = Principal('MSSQLSvc/%s.%s:%d' % (self.server.split('.')[0], domain, self.port), type=constants.PrincipalNameType.NT_SRV_INST.value) + serverName = Principal('MSSQLSvc/%s.%s:%d' % (self.remoteName.split('.')[0], domain, self.port), type=constants.PrincipalNameType.NT_SRV_INST.value) try: tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey) except KerberosError as e: @@ -899,7 +898,7 @@ def login(self, database, username, password='', domain='', hashes = None, useWi login['HostName'] = (''.join([random.choice(string.ascii_letters) for i in range(8)])).encode('utf-16le') login['AppName'] = (''.join([random.choice(string.ascii_letters) for i in range(8)])).encode('utf-16le') - login['ServerName'] = self.server.encode('utf-16le') + login['ServerName'] = self.remoteName.encode('utf-16le') login['CltIntName'] = login['AppName'] login['ClientPID'] = random.randint(0,1024) login['PacketSize'] = self.packetSize