Add elasticsearch fingerprinting.

This commit is contained in:
Daniel Goldberg 2017-09-25 15:13:36 +03:00
parent cb7bb56588
commit 86d6cdfba3
4 changed files with 78 additions and 12 deletions

View File

@ -1,13 +1,14 @@
import os import os
import sys import sys
from network.range import FixedRange, RelativeRange, ClassCRange import types
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter,\ import uuid
SambaCryExploiter
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger
from abc import ABCMeta from abc import ABCMeta
from itertools import product from itertools import product
import uuid
import types from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \
SambaCryExploiter
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, ElasticFinger
from network.range import FixedRange
__author__ = 'itamar' __author__ = 'itamar'
@ -15,6 +16,7 @@ GUID = str(uuid.getnode())
EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin') EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin')
def _cast_by_example(value, example): def _cast_by_example(value, example):
""" """
a method that casts a value to the type of the parameter given as example a method that casts a value to the type of the parameter given as example
@ -142,7 +144,8 @@ class Configuration(object):
scanner_class = TcpScanner scanner_class = TcpScanner
finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger] finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger]
exploiter_classes = [SmbExploiter, WmiExploiter, RdpExploiter, Ms08_067_Exploiter, # Windows exploits exploiter_classes = [SmbExploiter, WmiExploiter, RdpExploiter, Ms08_067_Exploiter, # Windows exploits
SSHExploiter, ShellShockExploiter, SambaCryExploiter # Linux SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux
ElasticFinger,
] ]
# how many victims to look for in a single scan iteration # how many victims to look for in a single scan iteration
@ -178,7 +181,7 @@ class Configuration(object):
range_class = FixedRange range_class = FixedRange
range_size = 1 range_size = 1
range_fixed = ['',] range_fixed = ['', ]
blocked_ips = ['', ] blocked_ips = ['', ]
@ -186,7 +189,15 @@ class Configuration(object):
HTTP_PORTS = [80, 8080, 443, HTTP_PORTS = [80, 8080, 443,
8008, # HTTP alternate 8008, # HTTP alternate
] ]
tcp_target_ports = [22, 2222, 445, 135, 3389] tcp_target_ports = [22,
445,
135,
3389,
80,
8080,
443,
8008,
9200]
tcp_target_ports.extend(HTTP_PORTS) tcp_target_ports.extend(HTTP_PORTS)
tcp_scan_timeout = 3000 # 3000 Milliseconds tcp_scan_timeout = 3000 # 3000 Milliseconds
tcp_scan_interval = 200 tcp_scan_interval = 200
@ -211,13 +222,17 @@ class Configuration(object):
# User and password dictionaries for exploits. # User and password dictionaries for exploits.
def get_exploit_user_password_pairs(self): def get_exploit_user_password_pairs(self):
"""
Returns all combinations of the configurations users and passwords
:return:
"""
return product(self.exploit_user_list, self.exploit_password_list) return product(self.exploit_user_list, self.exploit_password_list)
exploit_user_list = ['Administrator', 'root', 'user'] exploit_user_list = ['Administrator', 'root', 'user']
exploit_password_list = ["Password1!", "1234", "password", "12345678"] exploit_password_list = ["Password1!", "1234", "password", "12345678"]
# smb/wmi exploiter # smb/wmi exploiter
smb_download_timeout = 300 # timeout in seconds smb_download_timeout = 300 # timeout in seconds
smb_service_name = "InfectionMonkey" smb_service_name = "InfectionMonkey"
# Timeout (in seconds) for sambacry's trigger to yield results. # Timeout (in seconds) for sambacry's trigger to yield results.
@ -243,7 +258,6 @@ class Configuration(object):
# Monkey copy filename on share (64 bit) # Monkey copy filename on share (64 bit)
sambacry_monkey_copy_filename_64 = "monkey64_2" sambacry_monkey_copy_filename_64 = "monkey64_2"
# system info collection # system info collection
collect_system_info = True collect_system_info = True
@ -253,4 +267,5 @@ class Configuration(object):
mimikatz_dll_name = "mk.dll" mimikatz_dll_name = "mk.dll"
WormConfiguration = Configuration() WormConfiguration = Configuration()

View File

@ -39,6 +39,7 @@
"SSHFinger", "SSHFinger",
"PingScanner", "PingScanner",
"HTTPFinger", "HTTPFinger",
"ElasticFinger",
"SMBFinger" "SMBFinger"
], ],
"max_iterations": 3, "max_iterations": 3,
@ -83,7 +84,8 @@
80, 80,
8080, 8080,
443, 443,
8008 8008,
9200
], ],
"timeout_between_iterations": 10, "timeout_between_iterations": 10,
"use_file_logging": true, "use_file_logging": true,

View File

@ -23,5 +23,6 @@ from tcp_scanner import TcpScanner
from smbfinger import SMBFinger from smbfinger import SMBFinger
from sshfinger import SSHFinger from sshfinger import SSHFinger
from httpfinger import HTTPFinger from httpfinger import HTTPFinger
from elasticfinger import ElasticFinger
from info import local_ips from info import local_ips
from info import get_free_tcp_port from info import get_free_tcp_port

View File

@ -0,0 +1,48 @@
import json
import logging
from contextlib import closing
import requests
from requests.exceptions import Timeout, ConnectionError
from model.host import VictimHost
from network import HostFinger
ES_PORT = 9200
ES_SERVICE = 'es-3306'
LOG = logging.getLogger(__name__)
__author__ = 'danielg'
class ElasticFinger(HostFinger):
"""
Fingerprints mysql databases, only on port 3306
"""
def __init__(self):
self._config = __import__('config').WormConfiguration
def get_host_fingerprint(self, host):
"""
Returns elasticsearch metadata
:param host:
:return: Success/failure, data is saved in the host struct
"""
assert isinstance(host, VictimHost)
try:
url = 'http://%s:%s/' % (host.ip_addr, ES_PORT)
with closing(requests.get(url, timeout=1)) as req:
data = json.loads(req.text)
host.services[ES_SERVICE] = {}
host.services[ES_SERVICE]['name'] = 'ElasticSearch'
host.services[ES_SERVICE]['cluster_name'] = data['name']
host.services[ES_SERVICE]['version'] = data['version']['number']
return True
except Timeout:
LOG.debug("Got timeout while trying to read header information")
except ConnectionError: # Someone doesn't like us
LOG.debug("Unknown connection error")
except KeyError:
LOG.debug("Failed parsing the ElasticSearch JSOn response")
return False