From de832780b62b65a29c55d7140710d4349da2b02e Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Wed, 6 Jun 2018 13:54:21 +0300 Subject: [PATCH 1/9] Removed overly verbose logging line, triggered every 2 seconds --- monkey_island/cc/resources/root.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey_island/cc/resources/root.py b/monkey_island/cc/resources/root.py index 56a7695c7..1d9141589 100644 --- a/monkey_island/cc/resources/root.py +++ b/monkey_island/cc/resources/root.py @@ -64,7 +64,6 @@ class Root(flask_restful.Resource): infection_done = NodeService.is_monkey_finished_running() if not infection_done: report_done = False - logger.info('Report generation cannot be completed, infection is not done.') else: report_done = ReportService.is_report_generated() return dict(run_server=True, run_monkey=is_any_exists, infection_done=infection_done, report_done=report_done) From 293c204dddb7fcd184efdab3c21506564a6f42a9 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Sat, 9 Jun 2018 17:51:46 +0300 Subject: [PATCH 2/9] Created the MSSQL_fingerprinter branch, added the fingerprint class WIP. --- infection_monkey/network/mssql_fingerprint.py | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 infection_monkey/network/mssql_fingerprint.py diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py new file mode 100644 index 000000000..bbe762e27 --- /dev/null +++ b/infection_monkey/network/mssql_fingerprint.py @@ -0,0 +1,67 @@ +import logging +import socket + +from model.host import VictimHost +from network import HostFinger +from .tools import struct_unpack_tracker, struct_unpack_tracker_string + + +LOG = logging.getLogger(__name__) + + +class MSSQLFingerprint(HostFinger): + + 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. + Args: + host (str): Hostname or IP address of the SQL Server to query for information. + + Returns: + Discovered server information written to the Host info struct. + """ + + # Create a UDP socket and sets a timeout + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.settimeout(timeout) + server_address = (str(host), browser_port) + + if instance_name: + # The message is a CLNT_UCAST_INST packet to get a single instance + # https://msdn.microsoft.com/en-us/library/cc219746.aspx + message = '\x04{0}\x00'.format(instance_name) + else: + # 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 + results = [] + try: + logging.info('Sending message to requested host: {0}, {1}'.format(host, message)) + sock.sendto(message, server_address) + data, server = sock.recvfrom(buffer_size) + except socket.timeout: + logging.error('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host)) + return results + + # Loop through the server data + for server in data[3:].decode().split(';;'): + server_info = OrderedDict() + instance_info = server.split(';') + + if len(instance_info) > 1: + for i in range(1, len(instance_info), 2): + server_info[instance_info[i - 1]] = instance_info[i] + + results.append(server_info) + + # Close the socket + sock.close() + + return results From 8b22a520066ed6a45cb37270ce77b40d56a1d117 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Sat, 9 Jun 2018 18:16:39 +0300 Subject: [PATCH 3/9] Added the mssql finger class to the main network init file so it will be usable. --- infection_monkey/network/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/infection_monkey/network/__init__.py b/infection_monkey/network/__init__.py index a1df9d2e9..15c3166aa 100644 --- a/infection_monkey/network/__init__.py +++ b/infection_monkey/network/__init__.py @@ -27,3 +27,4 @@ from elasticfinger import ElasticFinger from mysqlfinger import MySQLFinger from info import local_ips from info import get_free_tcp_port +from mssql_fingerprint import MSSQLFingerprint \ No newline at end of file From d4c1871f87d2b0ae5d6f0974ec7bdd149ea7a6aa Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Sat, 9 Jun 2018 18:23:08 +0300 Subject: [PATCH 4/9] Implemented the first draft of the mssql fingerprint class Every line of code is documented and straight forward. --- infection_monkey/network/mssql_fingerprint.py | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index bbe762e27..51f5e25b0 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -3,7 +3,6 @@ import socket from model.host import VictimHost from network import HostFinger -from .tools import struct_unpack_tracker, struct_unpack_tracker_string LOG = logging.getLogger(__name__) @@ -11,6 +10,12 @@ LOG = logging.getLogger(__name__) class MSSQLFingerprint(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 @@ -23,19 +28,16 @@ class MSSQLFingerprint(HostFinger): Discovered server information written to the Host info struct. """ + assert isinstance(host, VictimHost) + # Create a UDP socket and sets a timeout sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.settimeout(timeout) - server_address = (str(host), browser_port) + sock.settimeout(self.TIMEOUT) + server_address = (str(host), self.SQL_BROWSER_DEFAULT_PORT) - if instance_name: - # The message is a CLNT_UCAST_INST packet to get a single instance - # https://msdn.microsoft.com/en-us/library/cc219746.aspx - message = '\x04{0}\x00'.format(instance_name) - else: - # The message is a CLNT_UCAST_EX packet to get all instances - # https://msdn.microsoft.com/en-us/library/cc219745.aspx - message = '\x03' + # 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() @@ -43,23 +45,22 @@ class MSSQLFingerprint(HostFinger): # send data and receive response results = [] try: - logging.info('Sending message to requested host: {0}, {1}'.format(host, message)) + LOG.info('Sending message to requested host: {0}, {1}'.format(host, message)) sock.sendto(message, server_address) - data, server = sock.recvfrom(buffer_size) + data, server = sock.recvfrom(self.BUFFER_SIZE) except socket.timeout: - logging.error('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host)) + LOG.error('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host)) + sock.close() return results + host.services[self.SERVICE_NAME] = {} + # Loop through the server data for server in data[3:].decode().split(';;'): - server_info = OrderedDict() instance_info = server.split(';') - if len(instance_info) > 1: for i in range(1, len(instance_info), 2): - server_info[instance_info[i - 1]] = instance_info[i] - - results.append(server_info) + host.services[self.SERVICE_NAME][instance_info[i - 1]] = instance_info[i] # Close the socket sock.close() From fadafdbd3ade5c16652a238c38f08d9d201e6c75 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Sat, 9 Jun 2018 18:23:54 +0300 Subject: [PATCH 5/9] Updated the config files to default include the mssql fingerfrint class: MSSQLFingerprinter, in the monkey's configuration. --- infection_monkey/config.py | 3 ++- infection_monkey/example.conf | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 7bd651965..5be1394c0 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -8,7 +8,8 @@ from itertools import product from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \ SambaCryExploiter, ElasticGroovyExploiter -from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger +from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger, \ + MSSQLFingerprint __author__ = 'itamar' diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 1baed66f2..5889b68d3 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -44,6 +44,7 @@ "HTTPFinger", "SMBFinger", "MySQLFinger", + "MSSQLFingerprint", "ElasticFinger" ], "max_iterations": 3, From 1272700fe5283922318db5bb815d7fb2e01faec5 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Sat, 9 Jun 2018 20:02:18 +0300 Subject: [PATCH 6/9] * Added an author mark and updated docs * Changed the module to use the VictimHost object as host * added True\False return statements. --- infection_monkey/network/mssql_fingerprint.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index 51f5e25b0..ab17ecb3b 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -4,6 +4,7 @@ import socket from model.host import VictimHost from network import HostFinger +__author__ = 'Maor Rayzin' LOG = logging.getLogger(__name__) @@ -21,11 +22,12 @@ class MSSQLFingerprint(HostFinger): def get_host_fingerprint(self, host): """Gets Microsoft SQL Server instance information by querying the SQL Browser service. - Args: - host (str): Hostname or IP address of the SQL Server to query for information. + :arg: + host (VictimHost): The MS-SSQL Server to query for information. - Returns: + :returns: Discovered server information written to the Host info struct. + True if success, False otherwise. """ assert isinstance(host, VictimHost) @@ -33,7 +35,7 @@ class MSSQLFingerprint(HostFinger): # 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), self.SQL_BROWSER_DEFAULT_PORT) + 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 @@ -43,7 +45,6 @@ class MSSQLFingerprint(HostFinger): message = message.encode() # send data and receive response - results = [] try: LOG.info('Sending message to requested host: {0}, {1}'.format(host, message)) sock.sendto(message, server_address) @@ -51,7 +52,7 @@ class MSSQLFingerprint(HostFinger): except socket.timeout: LOG.error('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host)) sock.close() - return results + return False host.services[self.SERVICE_NAME] = {} @@ -59,10 +60,13 @@ class MSSQLFingerprint(HostFinger): for server in data[3:].decode().split(';;'): instance_info = server.split(';') if len(instance_info) > 1: + host.services[self.SERVICE_NAME][instance_info[1]] = {} for i in range(1, len(instance_info), 2): - host.services[self.SERVICE_NAME][instance_info[i - 1]] = instance_info[i] + # 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 results + return True From d312a3a77146d40d8096e74e81bf581a8854e365 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Tue, 12 Jun 2018 13:26:28 +0300 Subject: [PATCH 7/9] * Changed name from MSSQLFingerprint to MSSQLFinger to match convention. * Added UI support for the new fingerprint in Monkey Island. * UI supports includes writing up MSSQL as a service under node's services list. --- infection_monkey/config.py | 2 +- infection_monkey/network/__init__.py | 2 +- infection_monkey/network/mssql_fingerprint.py | 4 ++-- monkey_island/cc/services/config.py | 9 +++++++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 1eacaef58..3472c63a8 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -9,7 +9,7 @@ from itertools import product from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \ SambaCryExploiter, ElasticGroovyExploiter from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger, \ - MSSQLFingerprint + MSSQLFinger __author__ = 'itamar' diff --git a/infection_monkey/network/__init__.py b/infection_monkey/network/__init__.py index 15c3166aa..fa15e357c 100644 --- a/infection_monkey/network/__init__.py +++ b/infection_monkey/network/__init__.py @@ -27,4 +27,4 @@ from elasticfinger import ElasticFinger from mysqlfinger import MySQLFinger from info import local_ips from info import get_free_tcp_port -from mssql_fingerprint import MSSQLFingerprint \ No newline at end of file +from mssql_fingerprint import MSSQLFinger \ No newline at end of file diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index ab17ecb3b..70f4f2369 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -9,13 +9,13 @@ __author__ = 'Maor Rayzin' LOG = logging.getLogger(__name__) -class MSSQLFingerprint(HostFinger): +class MSSQLFinger(HostFinger): # Class related consts SQL_BROWSER_DEFAULT_PORT = 1434 BUFFER_SIZE = 4096 TIMEOUT = 5 - SERVICE_NAME = 'mssql' + SERVICE_NAME = 'MSSQL' def __init__(self): self._config = __import__('config').WormConfiguration diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 390968a86..2887bf5a3 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -121,6 +121,14 @@ SCHEMA = { ], "title": "MySQLFinger" }, + { + "type": "string", + "enum": [ + "MSSQLFinger" + ], + "title": "MSSQLFinger" + }, + { "type": "string", "enum": [ @@ -367,6 +375,7 @@ SCHEMA = { "PingScanner", "HTTPFinger", "MySQLFinger", + "MSSQLFinger", "ElasticFinger" ], "description": "Determines which classes to use for fingerprinting" From db6f44109b6b8d8c5d86186287b3c4adc1311b4e Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Tue, 12 Jun 2018 16:29:27 +0300 Subject: [PATCH 8/9] * Responding to the PR comments with the logs and usage changes. --- infection_monkey/config.py | 2 +- infection_monkey/network/mssql_fingerprint.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 3472c63a8..6a01a7e29 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -146,7 +146,7 @@ class Configuration(object): max_iterations = 1 scanner_class = TcpScanner - finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger] + finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger, MSSQLFinger] exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux ElasticGroovyExploiter, # multi diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index 70f4f2369..9409c2255 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -50,15 +50,17 @@ class MSSQLFinger(HostFinger): sock.sendto(message, server_address) data, server = sock.recvfrom(self.BUFFER_SIZE) except socket.timeout: - LOG.error('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host)) + 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 - for server in data[3:].decode().split(';;'): - instance_info = server.split(';') + 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): From 20d4b3a642fa2688fded5c55152d75eaae3de72c Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 13 Jun 2018 16:05:12 +0300 Subject: [PATCH 9/9] Fix default config values --- infection_monkey/config.py | 4 ++-- infection_monkey/example.conf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index f4ca4e89e..eea600ff6 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -184,9 +184,9 @@ class Configuration(object): # Auto detect and scan local subnets local_network_scan = True - subnet_scan_list = ['', ] + subnet_scan_list = [] - blocked_ips = ['', ] + blocked_ips = [] # TCP Scanner HTTP_PORTS = [80, 8080, 443, diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index bc0156d8a..45eed24a3 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -8,9 +8,9 @@ ], "keep_tunnel_open_time": 60, "subnet_scan_list": [ - "" + ], - "blocked_ips": [""], + "blocked_ips": [], "current_server": "41.50.73.31:5000", "alive": true, "collect_system_info": true,