forked from p15670423/monkey
Remove range classes in config
network now scans several range classes according to config
This commit is contained in:
parent
d3ce956224
commit
898644df7b
|
@ -8,7 +8,6 @@ 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.range import FixedRange
|
||||
|
||||
__author__ = 'itamar'
|
||||
|
||||
|
@ -182,7 +181,6 @@ class Configuration(object):
|
|||
# Auto detect and scan local subnets
|
||||
local_network_scan = True
|
||||
|
||||
range_class = FixedRange
|
||||
range_fixed = ['', ]
|
||||
|
||||
blocked_ips = ['', ]
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
"www.google.com"
|
||||
],
|
||||
"keep_tunnel_open_time": 60,
|
||||
"range_class": "RelativeRange",
|
||||
"range_fixed": [
|
||||
""
|
||||
],
|
||||
|
|
|
@ -8,6 +8,7 @@ import itertools
|
|||
import netifaces
|
||||
from subprocess import check_output
|
||||
from random import randint
|
||||
from range import CidrRange
|
||||
|
||||
|
||||
def get_host_subnets():
|
||||
|
@ -129,7 +130,7 @@ def check_internet_access(services):
|
|||
return False
|
||||
|
||||
|
||||
def get_ips_from_interfaces():
|
||||
def get_interfaces_ranges():
|
||||
"""
|
||||
Returns a list of IPs accessible in the host in each network interface, in the subnet.
|
||||
Limits to a single class C if the network is larger
|
||||
|
@ -138,15 +139,14 @@ def get_ips_from_interfaces():
|
|||
res = []
|
||||
ifs = get_host_subnets()
|
||||
for net_interface in ifs:
|
||||
address_str = unicode(net_interface['addr'])
|
||||
netmask_str = unicode(net_interface['netmask'])
|
||||
host_address = ipaddress.ip_address(address_str)
|
||||
address_str = net_interface['addr']
|
||||
netmask_str = net_interface['netmask']
|
||||
ip_interface = ipaddress.ip_interface(u"%s/%s" % (address_str, netmask_str))
|
||||
# limit subnet scans to class C only
|
||||
if ip_interface.network.num_addresses > 255:
|
||||
ip_interface = ipaddress.ip_interface(u"%s/24" % address_str)
|
||||
addrs = [str(addr) for addr in ip_interface.network.hosts() if addr != host_address]
|
||||
res.extend(addrs)
|
||||
res.append(CidrRange(cidr_range="%s/24" % (address_str, )))
|
||||
else:
|
||||
res.append(CidrRange(cidr_range="%s/%s" % (address_str, netmask_str)))
|
||||
return res
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
|||
import time
|
||||
|
||||
from config import WormConfiguration
|
||||
from info import local_ips, get_ips_from_interfaces
|
||||
from info import local_ips, get_interfaces_ranges
|
||||
from range import *
|
||||
from . import HostScanner
|
||||
|
||||
|
@ -20,9 +20,8 @@ class NetworkScanner(object):
|
|||
|
||||
def initialize(self):
|
||||
"""
|
||||
Set up scanning based on configuration
|
||||
FixedRange -> Reads from range_fixed field in configuration
|
||||
otherwise, takes a range from every IP address the current host has.
|
||||
Set up scanning.
|
||||
based on configuration: scans local network and/or scans fixed list of IPs/subnets.
|
||||
:return:
|
||||
"""
|
||||
# get local ip addresses
|
||||
|
@ -33,13 +32,9 @@ class NetworkScanner(object):
|
|||
|
||||
LOG.info("Found local IP addresses of the machine: %r", self._ip_addresses)
|
||||
# for fixed range, only scan once.
|
||||
if WormConfiguration.range_class is FixedRange:
|
||||
self._ranges = [WormConfiguration.range_class(fixed_addresses=WormConfiguration.range_fixed)]
|
||||
else:
|
||||
self._ranges = [WormConfiguration.range_class(ip_address)
|
||||
for ip_address in self._ip_addresses]
|
||||
self._ranges = [NetworkRange.get_range_obj(address_str=x) for x in WormConfiguration.range_fixed]
|
||||
if WormConfiguration.local_network_scan:
|
||||
self._ranges += [FixedRange([ip_address for ip_address in get_ips_from_interfaces()])]
|
||||
self._ranges += get_interfaces_ranges()
|
||||
LOG.info("Base local networks to scan are: %r", self._ranges)
|
||||
|
||||
def get_victim_machines(self, scan_type, max_find=5, stop_callback=None):
|
||||
|
|
|
@ -18,6 +18,32 @@ class NetworkRange(object):
|
|||
self._shuffle = shuffle
|
||||
self._config = __import__('config').WormConfiguration
|
||||
|
||||
def get_range(self):
|
||||
return [x for x in self._get_range() if (x & 0xFF != 0)] # remove broadcast ips
|
||||
|
||||
def __iter__(self):
|
||||
base_range = self.get_range()
|
||||
if self._shuffle:
|
||||
random.shuffle(base_range)
|
||||
|
||||
for x in base_range:
|
||||
yield VictimHost(self._number_to_ip(self._base_address + x))
|
||||
|
||||
@abstractmethod
|
||||
def _get_range(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@staticmethod
|
||||
def get_range_obj(address_str):
|
||||
address_str = address_str.strip()
|
||||
if not address_str: # Empty string
|
||||
return None
|
||||
if -1 != address_str.find('-'):
|
||||
return IpRange(ip_range=address_str)
|
||||
if -1 != address_str.find('/'):
|
||||
return CidrRange(cidr_range=address_str)
|
||||
return SingleIpRange(ip_address=address_str)
|
||||
|
||||
@staticmethod
|
||||
def _ip_to_number(address):
|
||||
return struct.unpack(">L", socket.inet_aton(address))[0]
|
||||
|
@ -26,18 +52,6 @@ class NetworkRange(object):
|
|||
def _number_to_ip(num):
|
||||
return socket.inet_ntoa(struct.pack(">L", num))
|
||||
|
||||
@abstractmethod
|
||||
def _get_range(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def __iter__(self):
|
||||
base_range = self._get_range()
|
||||
if self._shuffle:
|
||||
random.shuffle(base_range)
|
||||
|
||||
for x in base_range:
|
||||
yield VictimHost(self._number_to_ip(self._base_address + x))
|
||||
|
||||
|
||||
class ClassCRange(NetworkRange):
|
||||
def __init__(self, base_address, shuffle=True):
|
||||
|
@ -68,42 +82,65 @@ class RelativeRange(NetworkRange):
|
|||
return range(lower_end, higher_end + 1)
|
||||
|
||||
|
||||
class FixedRange(NetworkRange):
|
||||
def __init__(self, fixed_addresses, shuffle=True):
|
||||
class CidrRange(NetworkRange):
|
||||
def __init__(self, cidr_range, shuffle=True):
|
||||
base_address = 0
|
||||
super(FixedRange, self).__init__(base_address, shuffle=shuffle)
|
||||
self._fixed_addresses = fixed_addresses
|
||||
super(CidrRange, self).__init__(base_address, shuffle=shuffle)
|
||||
self._cidr_range = cidr_range.strip()
|
||||
self._ip_network = ipaddress.ip_network(unicode(self._cidr_range), strict=False)
|
||||
|
||||
def __repr__(self):
|
||||
return "<FixedRange %s>" % (",".join(self._fixed_addresses))
|
||||
return "<CidrRange %s>" % (self._cidr_range, )
|
||||
|
||||
@staticmethod
|
||||
def _cidr_range_to_ip_list(address_str):
|
||||
return [FixedRange._ip_to_number(str(x)) for x in ipaddress.ip_network(unicode(address_str), strict=False)]
|
||||
|
||||
@staticmethod
|
||||
def _ip_range_to_ip_list(address_str):
|
||||
addresses = address_str.split('-')
|
||||
if len(addresses) != 2:
|
||||
raise ValueError('Illegal address format: %s' % address_str)
|
||||
lower_end, higher_end = [FixedRange._ip_to_number(x.strip()) for x in addresses]
|
||||
if higher_end < lower_end:
|
||||
raise ValueError('Illegal address range: %s' % address_str)
|
||||
return range(lower_end, higher_end + 1)
|
||||
|
||||
@staticmethod
|
||||
def _parse_address_str(address_str):
|
||||
address_str = address_str.strip()
|
||||
if not address_str: # Empty string
|
||||
return []
|
||||
if -1 != address_str.find('-'):
|
||||
return FixedRange._ip_range_to_ip_list(address_str)
|
||||
if -1 != address_str.find('/'):
|
||||
return FixedRange._cidr_range_to_ip_list(address_str)
|
||||
return [FixedRange._ip_to_number(address_str)]
|
||||
def is_in_range(self, ip_address):
|
||||
return ipaddress.ip_address(ip_address) in self._ip_network
|
||||
|
||||
def _get_range(self):
|
||||
ip_list = list(reduce(
|
||||
lambda x, y: x.union(y),
|
||||
[set(self._parse_address_str(z)) for z in self._fixed_addresses]))
|
||||
return [x for x in ip_list if (x & 0xFF != 0)] # remove broadcast ips
|
||||
return [CidrRange._ip_to_number(str(x)) for x in self._ip_network]
|
||||
|
||||
|
||||
class IpRange(NetworkRange):
|
||||
def __init__(self, ip_range=None, lower_end_ip=None, higher_end_ip=None, shuffle=True):
|
||||
base_address = 0
|
||||
super(IpRange, self).__init__(base_address, shuffle=shuffle)
|
||||
if ip_range is not None:
|
||||
addresses = ip_range.split('-')
|
||||
if len(addresses) != 2:
|
||||
raise ValueError('Illegal IP range format: %s' % ip_range)
|
||||
self._lower_end_ip, self._higher_end_ip = [x.strip() for x in addresses]
|
||||
if self._higher_end_ip < self._lower_end_ip:
|
||||
raise ValueError('Higher end IP is smaller than lower end IP: %s' % ip_range)
|
||||
elif (lower_end_ip is not None) and (higher_end_ip is not None):
|
||||
self._lower_end_ip = lower_end_ip
|
||||
self._higher_end_ip = higher_end_ip
|
||||
else:
|
||||
raise ValueError('Illegal IP range: %s' % ip_range)
|
||||
|
||||
self._lower_end_ip_num = IpRange._ip_to_number(self._lower_end_ip)
|
||||
self._higher_end_ip_num = IpRange._ip_to_number(self._higher_end_ip)
|
||||
|
||||
def __repr__(self):
|
||||
return "<IpRange %s-%s>" % (self._lower_end_ip, self._higher_end_ip)
|
||||
|
||||
def is_in_range(self, ip_address):
|
||||
return self._lower_end_ip_num <= IpRange._ip_to_number(ip_address) <= self._higher_end_ip_num
|
||||
|
||||
def _get_range(self):
|
||||
return range(self._lower_end_ip_num, self._higher_end_ip_num + 1)
|
||||
|
||||
|
||||
class SingleIpRange(NetworkRange):
|
||||
def __init__(self, ip_address, shuffle=True):
|
||||
base_address = 0
|
||||
super(SingleIpRange, self).__init__(base_address, shuffle=shuffle)
|
||||
self._ip_address = ip_address
|
||||
|
||||
def __repr__(self):
|
||||
return "<SingleIpRange %s>" % (self._ip_address,)
|
||||
|
||||
def is_in_range(self, ip_address):
|
||||
return self._ip_address == ip_address
|
||||
|
||||
def _get_range(self):
|
||||
return [SingleIpRange._ip_to_number(self._ip_address)]
|
||||
|
||||
|
|
|
@ -205,25 +205,8 @@ SCHEMA = {
|
|||
"title": "Network range",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"range_class": {
|
||||
"title": "Range class",
|
||||
"type": "string",
|
||||
"default": "FixedRange",
|
||||
"enum": [
|
||||
"FixedRange",
|
||||
"ClassCRange"
|
||||
],
|
||||
"enumNames": [
|
||||
"Fixed Range",
|
||||
"Class C Range"
|
||||
],
|
||||
"description":
|
||||
"Determines which class to use to determine scan range."
|
||||
" Fixed Range will scan only specific IPs listed under Fixed range IP list."
|
||||
" Class C Range will scan machines in the Class C network the monkey's on."
|
||||
},
|
||||
"range_fixed": {
|
||||
"title": "Fixed range IP/subnet list",
|
||||
"title": "Scan IP/subnet list",
|
||||
"type": "array",
|
||||
"uniqueItems": True,
|
||||
"items": {
|
||||
|
@ -232,8 +215,7 @@ SCHEMA = {
|
|||
"default": [
|
||||
],
|
||||
"description":
|
||||
"List of IPs/subnets to include when using FixedRange"
|
||||
" (Only relevant for Fixed Range)."
|
||||
"List of IPs/subnets the monkey should scan."
|
||||
" Examples: \"192.168.0.1\", \"192.168.0.5-192.168.0.20\", \"192.168.0.5/24\""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,8 +315,6 @@ class ReportService:
|
|||
|
||||
@staticmethod
|
||||
def get_config_ips():
|
||||
if ConfigService.get_config_value(['basic_network', 'network_range', 'range_class'], True) != 'FixedRange':
|
||||
return []
|
||||
return ConfigService.get_config_value(['basic_network', 'network_range', 'range_fixed'], True)
|
||||
|
||||
@staticmethod
|
||||
|
|
Loading…
Reference in New Issue