Пример #1
0
    def _get_inaccessible_subnets_ips(self):
        """
        For each of the machine's IPs, checks if it's in one of the subnets specified in the
        'inaccessible_subnets' config value. If so, all other subnets in the config value shouldn't be accessible.
        All these subnets are returned.
        :return: A list of subnets that shouldn't be accessible from the machine the monkey is running on.
        """
        subnets_to_scan = []
        if len(WormConfiguration.inaccessible_subnets) > 1:
            for subnet_str in WormConfiguration.inaccessible_subnets:
                if NetworkScanner._is_any_ip_in_subnet(
                    [unicode(x) for x in self._ip_addresses], subnet_str):
                    # If machine has IPs from 2 different subnets in the same group, there's no point checking the other
                    # subnet.
                    for other_subnet_str in WormConfiguration.inaccessible_subnets:
                        if other_subnet_str == subnet_str:
                            continue
                        if not NetworkScanner._is_any_ip_in_subnet(
                            [unicode(x)
                             for x in self._ip_addresses], other_subnet_str):
                            subnets_to_scan.append(
                                NetworkRange.get_range_obj(other_subnet_str))
                    break

        return subnets_to_scan
Пример #2
0
    def get_cross_segment_issues_per_subnet_pair(scans, source_subnet,
                                                 target_subnet):
        """
        Gets list of cross segment issues from source_subnet to target_subnet.
        :param scans:           List of all scan telemetry entries. Must have monkey_guid,
        ip_addr and services.
                                This should be a PyMongo cursor object.
        :param source_subnet:   The subnet which shouldn't be able to access target_subnet.
        :param target_subnet:   The subnet which shouldn't be accessible from source_subnet.
        :return:
        """
        if source_subnet == target_subnet:
            return []
        source_subnet_range = NetworkRange.get_range_obj(source_subnet)
        target_subnet_range = NetworkRange.get_range_obj(target_subnet)

        cross_segment_issues = []

        scans.rewind()  # If we iterated over scans already we need to rewind.
        for scan in scans:
            target_ip = scan["data"]["machine"]["ip_addr"]
            if target_subnet_range.is_in_range(str(target_ip)):
                monkey = NodeService.get_monkey_by_guid(scan["monkey_guid"])
                cross_segment_ip = get_ip_in_src_and_not_in_dst(
                    monkey["ip_addresses"], source_subnet_range,
                    target_subnet_range)

                if cross_segment_ip is not None:
                    cross_segment_issues.append({
                        "source":
                        cross_segment_ip,
                        "hostname":
                        monkey["hostname"],
                        "target":
                        target_ip,
                        "services":
                        scan["data"]["machine"]["services"],
                        "icmp":
                        scan["data"]["machine"]["icmp"],
                        "is_self":
                        False,
                    })

        return cross_segment_issues + ReportService.get_cross_segment_issues_of_single_machine(
            source_subnet_range, target_subnet_range)
Пример #3
0
    def get_cross_segment_issues_per_subnet_pair(scans, source_subnet,
                                                 target_subnet):
        """
        Gets list of cross segment issues from source_subnet to target_subnet.
        :param scans:           List of all scan telemetry entries. Must have monkey_guid, ip_addr and services.
                                This should be a PyMongo cursor object.
        :param source_subnet:   The subnet which shouldn't be able to access target_subnet.
        :param target_subnet:   The subnet which shouldn't be accessible from source_subnet.
        :return:
        """
        if source_subnet == target_subnet:
            return []
        source_subnet_range = NetworkRange.get_range_obj(source_subnet)
        target_subnet_range = NetworkRange.get_range_obj(target_subnet)

        cross_segment_issues = []

        scans.rewind()  # If we iterated over scans already we need to rewind.
        for scan in scans:
            target_ip = scan['data']['machine']['ip_addr']
            if target_subnet_range.is_in_range(unicode(target_ip)):
                monkey = NodeService.get_monkey_by_guid(scan['monkey_guid'])
                cross_segment_ip = ReportService.get_ip_in_src_and_not_in_dst(
                    monkey['ip_addresses'], source_subnet_range,
                    target_subnet_range)

                if cross_segment_ip is not None:
                    cross_segment_issues.append({
                        'source':
                        cross_segment_ip,
                        'hostname':
                        monkey['hostname'],
                        'target':
                        target_ip,
                        'services':
                        scan['data']['machine']['services'],
                        'is_self':
                        False
                    })

        return cross_segment_issues + ReportService.get_cross_segment_issues_of_single_machine(
            source_subnet_range, target_subnet_range)
Пример #4
0
def is_segmentation_violation(current_monkey: Monkey, target_ip: str,
                              source_subnet: str, target_subnet: str) -> bool:
    """
    Checks is a specific communication is a segmentation violation.
    :param current_monkey:  The source monkey which originated the communication.
    :param target_ip:       The target with which the current monkey communicated with.
    :param source_subnet:   The segment the monkey belongs to.
    :param target_subnet:   Another segment which the monkey isn't supposed to communicate with.
    :return:    True if this is a violation of segmentation between source_subnet and target_subnet; Otherwise, False.
    """
    if source_subnet == target_subnet:
        return False
    source_subnet_range = NetworkRange.get_range_obj(source_subnet)
    target_subnet_range = NetworkRange.get_range_obj(target_subnet)

    if target_subnet_range.is_in_range(str(target_ip)):
        cross_segment_ip = get_ip_in_src_and_not_in_dst(
            current_monkey.ip_addresses, source_subnet_range,
            target_subnet_range)

        return cross_segment_ip is not None
Пример #5
0
def get_segmentation_violation_event(current_monkey, source_subnet, target_ip,
                                     target_subnet):
    return Event.create_event(
        title="Segmentation event",
        message=SEGMENTATION_VIOLATION_EVENT_TEXT.format(
            hostname=current_monkey.hostname,
            source_ip=get_ip_if_in_subnet(
                current_monkey.ip_addresses,
                NetworkRange.get_range_obj(source_subnet)),
            source_seg=source_subnet,
            target_ip=target_ip,
            target_seg=target_subnet),
        event_type=zero_trust_consts.EVENT_TYPE_MONKEY_NETWORK)
Пример #6
0
    def initialize(self):
        """
        Set up scanning.
        based on configuration: scans local network and/or scans fixed list of IPs/subnets.
        """
        # get local ip addresses
        self._ip_addresses = local_ips()

        if not self._ip_addresses:
            raise Exception("Cannot find local IP address for the machine")

        LOG.info("Found local IP addresses of the machine: %r", self._ip_addresses)
        # for fixed range, only scan once.
        self._ranges = [NetworkRange.get_range_obj(address_str=x) for x in WormConfiguration.subnet_scan_list]
        if WormConfiguration.local_network_scan:
            self._ranges += get_interfaces_ranges()
        self._ranges += self._get_inaccessible_subnets_ips()
        LOG.info("Base local networks to scan are: %r", self._ranges)
Пример #7
0
def create_or_add_findings_for_all_pairs(all_subnets, current_monkey):
    # Filter the subnets that this monkey is part of.
    this_monkey_subnets = []
    for subnet in all_subnets:
        if get_ip_if_in_subnet(current_monkey.ip_addresses,
                               NetworkRange.get_range_obj(subnet)) is not None:
            this_monkey_subnets.append(subnet)

    # Get all the other subnets.
    other_subnets = list(set(all_subnets) - set(this_monkey_subnets))

    # Calculate the cartesian product - (this monkey subnets X other subnets). These pairs are the pairs that the monkey
    # should have tested.
    all_subnets_pairs_for_this_monkey = itertools.product(
        this_monkey_subnets, other_subnets)

    for subnet_pair in all_subnets_pairs_for_this_monkey:
        SegmentationFinding.create_or_add_to_existing_finding(
            subnets=list(subnet_pair),
            status=zero_trust_consts.STATUS_PASSED,
            segmentation_event=get_segmentation_done_event(
                current_monkey, subnet_pair))
Пример #8
0
 def _is_any_ip_in_subnet(ip_addresses, subnet_str):
     for ip_address in ip_addresses:
         if NetworkRange.get_range_obj(subnet_str).is_in_range(ip_address):
             return True
     return False