forked from p15670423/monkey
75 lines
2.5 KiB
Python
75 lines
2.5 KiB
Python
import logging
|
|
import socket
|
|
|
|
from model.host import VictimHost
|
|
from network import HostFinger
|
|
|
|
__author__ = 'Maor Rayzin'
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class MSSQLFinger(HostFinger):
|
|
|
|
# Class related consts
|
|
SQL_BROWSER_DEFAULT_PORT = 1434
|
|
BUFFER_SIZE = 4096
|
|
TIMEOUT = 5
|
|
SERVICE_NAME = 'MSSQL'
|
|
|
|
def __init__(self):
|
|
self._config = __import__('config').WormConfiguration
|
|
|
|
def get_host_fingerprint(self, host):
|
|
"""Gets Microsoft SQL Server instance information by querying the SQL Browser service.
|
|
:arg:
|
|
host (VictimHost): The MS-SSQL Server to query for information.
|
|
|
|
:returns:
|
|
Discovered server information written to the Host info struct.
|
|
True if success, False otherwise.
|
|
"""
|
|
|
|
assert isinstance(host, VictimHost)
|
|
|
|
# Create a UDP socket and sets a timeout
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
sock.settimeout(self.TIMEOUT)
|
|
server_address = (str(host.ip_addr), self.SQL_BROWSER_DEFAULT_PORT)
|
|
|
|
# The message is a CLNT_UCAST_EX packet to get all instances
|
|
# https://msdn.microsoft.com/en-us/library/cc219745.aspx
|
|
message = '\x03'
|
|
|
|
# Encode the message as a bytesarray
|
|
message = message.encode()
|
|
|
|
# send data and receive response
|
|
try:
|
|
LOG.info('Sending message to requested host: {0}, {1}'.format(host, message))
|
|
sock.sendto(message, server_address)
|
|
data, server = sock.recvfrom(self.BUFFER_SIZE)
|
|
except socket.timeout:
|
|
LOG.info('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host))
|
|
sock.close()
|
|
return False
|
|
|
|
host.services[self.SERVICE_NAME] = {}
|
|
|
|
# Loop through the server data
|
|
instances_list = data[3:].decode().split(';;')
|
|
LOG.info('{0} MSSQL instances found'.format(len(instances_list)))
|
|
for instance in instances_list:
|
|
instance_info = instance.split(';')
|
|
if len(instance_info) > 1:
|
|
host.services[self.SERVICE_NAME][instance_info[1]] = {}
|
|
for i in range(1, len(instance_info), 2):
|
|
# Each instance's info is nested under its own name, if there are multiple instances
|
|
# each will appear under its own name
|
|
host.services[self.SERVICE_NAME][instance_info[1]][instance_info[i - 1]] = instance_info[i]
|
|
|
|
# Close the socket
|
|
sock.close()
|
|
|
|
return True
|