forked from p15670423/monkey
Merge branch 'develop' into feature/report-backend
This commit is contained in:
commit
7e77e2d33b
|
@ -13,7 +13,7 @@ from exploit import HostExploiter
|
|||
from exploit.tools import HTTPTools, get_monkey_depth
|
||||
from exploit.tools import get_target_monkey
|
||||
from model import RDP_CMDLINE_HTTP_BITS, RDP_CMDLINE_HTTP_VBS
|
||||
from network.tools import check_port_tcp
|
||||
from network.tools import check_tcp_port
|
||||
from tools import build_monkey_commandline
|
||||
|
||||
__author__ = 'hoffer'
|
||||
|
@ -245,7 +245,7 @@ class RdpExploiter(HostExploiter):
|
|||
return True
|
||||
|
||||
if not self.host.os.get('type'):
|
||||
is_open, _ = check_port_tcp(self.host.ip_addr, RDP_PORT)
|
||||
is_open, _ = check_tcp_port(self.host.ip_addr, RDP_PORT)
|
||||
if is_open:
|
||||
self.host.os['type'] = 'windows'
|
||||
return True
|
||||
|
@ -254,7 +254,7 @@ class RdpExploiter(HostExploiter):
|
|||
def exploit_host(self):
|
||||
global g_reactor
|
||||
|
||||
is_open, _ = check_port_tcp(self.host.ip_addr, RDP_PORT)
|
||||
is_open, _ = check_tcp_port(self.host.ip_addr, RDP_PORT)
|
||||
if not is_open:
|
||||
LOG.info("RDP port is closed on %r, skipping", self.host)
|
||||
return False
|
||||
|
|
|
@ -7,7 +7,7 @@ from exploit import HostExploiter
|
|||
from exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
|
||||
from model import MONKEY_CMDLINE_DETACHED_WINDOWS, DROPPER_CMDLINE_DETACHED_WINDOWS
|
||||
from network import SMBFinger
|
||||
from network.tools import check_port_tcp
|
||||
from network.tools import check_tcp_port
|
||||
from tools import build_monkey_commandline
|
||||
|
||||
LOG = getLogger(__name__)
|
||||
|
@ -31,12 +31,12 @@ class SmbExploiter(HostExploiter):
|
|||
return True
|
||||
|
||||
if not self.host.os.get('type'):
|
||||
is_smb_open, _ = check_port_tcp(self.host.ip_addr, 445)
|
||||
is_smb_open, _ = check_tcp_port(self.host.ip_addr, 445)
|
||||
if is_smb_open:
|
||||
smb_finger = SMBFinger()
|
||||
smb_finger.get_host_fingerprint(self.host)
|
||||
else:
|
||||
is_nb_open, _ = check_port_tcp(self.host.ip_addr, 139)
|
||||
is_nb_open, _ = check_tcp_port(self.host.ip_addr, 139)
|
||||
if is_nb_open:
|
||||
self.host.os['type'] = 'windows'
|
||||
return self.host.os.get('type') in self._TARGET_OS_TYPE
|
||||
|
|
|
@ -7,7 +7,7 @@ import monkeyfs
|
|||
from exploit import HostExploiter
|
||||
from exploit.tools import get_target_monkey, get_monkey_depth
|
||||
from model import MONKEY_ARG
|
||||
from network.tools import check_port_tcp
|
||||
from network.tools import check_tcp_port
|
||||
from tools import build_monkey_commandline
|
||||
|
||||
__author__ = 'hoffer'
|
||||
|
@ -41,7 +41,7 @@ class SSHExploiter(HostExploiter):
|
|||
if servdata.get('name') == 'ssh' and servkey.startswith('tcp-'):
|
||||
port = int(servkey.replace('tcp-', ''))
|
||||
|
||||
is_open, _ = check_port_tcp(self.host.ip_addr, port)
|
||||
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
|
||||
|
|
|
@ -17,7 +17,7 @@ from impacket.dcerpc.v5 import transport
|
|||
from exploit.tools import SmbTools, get_target_monkey, get_monkey_depth
|
||||
from model import DROPPER_CMDLINE_WINDOWS, MONKEY_CMDLINE_WINDOWS
|
||||
from network import SMBFinger
|
||||
from network.tools import check_port_tcp
|
||||
from network.tools import check_tcp_port
|
||||
from tools import build_monkey_commandline
|
||||
from . import HostExploiter
|
||||
|
||||
|
@ -168,7 +168,7 @@ class Ms08_067_Exploiter(HostExploiter):
|
|||
|
||||
if not self.host.os.get('type') or (
|
||||
self.host.os.get('type') in self._TARGET_OS_TYPE and not self.host.os.get('version')):
|
||||
is_smb_open, _ = check_port_tcp(self.host.ip_addr, 445)
|
||||
is_smb_open, _ = check_tcp_port(self.host.ip_addr, 445)
|
||||
if is_smb_open:
|
||||
smb_finger = SMBFinger()
|
||||
if smb_finger.get_host_fingerprint(self.host):
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import os
|
||||
import sys
|
||||
import logging
|
||||
import traceback
|
||||
import logging.config
|
||||
from config import WormConfiguration, EXTERNAL_CONFIG_FILE
|
||||
from model import MONKEY_ARG, DROPPER_ARG
|
||||
from dropper import MonkeyDrops
|
||||
from monkey import ChaosMonkey
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import logging.config
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from config import WormConfiguration, EXTERNAL_CONFIG_FILE
|
||||
from dropper import MonkeyDrops
|
||||
from model import MONKEY_ARG, DROPPER_ARG
|
||||
from monkey import ChaosMonkey
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
@ -55,22 +58,22 @@ def main():
|
|||
config_file = opts.config
|
||||
if os.path.isfile(config_file):
|
||||
# using print because config can also change log locations
|
||||
print "Loading config from %s." % config_file
|
||||
print("Loading config from %s." % config_file)
|
||||
try:
|
||||
with open(config_file) as config_fo:
|
||||
json_dict = json.load(config_fo)
|
||||
WormConfiguration.from_dict(json_dict)
|
||||
except ValueError as e:
|
||||
print "Error loading config: %s, using default" % (e,)
|
||||
print("Error loading config: %s, using default" % (e,))
|
||||
else:
|
||||
print("Config file wasn't supplied and default path: %s wasn't found, using internal default" % (config_file,))
|
||||
|
||||
print "Loaded Configuration: %r" % WormConfiguration.as_dict()
|
||||
print("Loaded Configuration: %r" % WormConfiguration.as_dict())
|
||||
|
||||
# Make sure we're not in a machine that has the kill file
|
||||
kill_path = os.path.expandvars(WormConfiguration.kill_file_path_windows) if sys.platform == "win32" else WormConfiguration.kill_file_path_linux
|
||||
if os.path.exists(kill_path):
|
||||
print "Kill path found, finished run"
|
||||
print("Kill path found, finished run")
|
||||
return True
|
||||
|
||||
try:
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import re
|
||||
from network import HostFinger
|
||||
from network.tools import check_port_tcp
|
||||
|
||||
from model.host import VictimHost
|
||||
from network import HostFinger
|
||||
from network.tools import check_tcp_port
|
||||
|
||||
SSH_PORT = 22
|
||||
SSH_SERVICE_DEFAULT = 'tcp-22'
|
||||
|
@ -38,7 +39,7 @@ class SSHFinger(HostFinger):
|
|||
self._banner_match(name, host, banner)
|
||||
return
|
||||
|
||||
is_open, banner = check_port_tcp(host.ip_addr, SSH_PORT, TIMEOUT, True)
|
||||
is_open, banner = check_tcp_port(host.ip_addr, SSH_PORT, TIMEOUT, True)
|
||||
|
||||
if is_open:
|
||||
host.services[SSH_SERVICE_DEFAULT] = {}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import time
|
||||
from random import shuffle
|
||||
|
||||
from network import HostScanner, HostFinger
|
||||
from model.host import VictimHost
|
||||
from network.tools import check_port_tcp
|
||||
from network.tools import check_tcp_ports
|
||||
|
||||
__author__ = 'itamar'
|
||||
|
||||
|
@ -17,29 +16,24 @@ class TcpScanner(HostScanner, HostFinger):
|
|||
return self.get_host_fingerprint(host, True)
|
||||
|
||||
def get_host_fingerprint(self, host, only_one_port=False):
|
||||
assert isinstance(host, VictimHost)
|
||||
"""
|
||||
Scans a target host to see if it's alive using the tcp_target_ports specified in the configuration.
|
||||
:param host: VictimHost structure
|
||||
:param only_one_port: Currently unused.
|
||||
:return: T/F if there is at least one open port. In addition, the host object is updated to mark those services as alive.
|
||||
"""
|
||||
|
||||
count = 0
|
||||
# maybe hide under really bad detection systems
|
||||
target_ports = self._config.tcp_target_ports[:]
|
||||
shuffle(target_ports)
|
||||
|
||||
for target_port in target_ports:
|
||||
ports, banners = check_tcp_ports(host.ip_addr, target_ports, self._config.tcp_scan_timeout / 1000.0)
|
||||
for target_port, banner in zip(ports, banners):
|
||||
service = 'tcp-' + str(target_port)
|
||||
host.services[service] = {}
|
||||
if banner:
|
||||
host.services[service]['banner'] = banner
|
||||
if only_one_port:
|
||||
break
|
||||
|
||||
is_open, banner = check_port_tcp(host.ip_addr,
|
||||
target_port,
|
||||
self._config.tcp_scan_timeout / 1000.0,
|
||||
self._config.tcp_scan_get_banner)
|
||||
|
||||
if is_open:
|
||||
count += 1
|
||||
service = 'tcp-' + str(target_port)
|
||||
host.services[service] = {}
|
||||
if banner:
|
||||
host.services[service]['banner'] = banner
|
||||
if only_one_port:
|
||||
break
|
||||
else:
|
||||
time.sleep(self._config.tcp_scan_interval / 1000.0)
|
||||
|
||||
return count != 0
|
||||
return len(ports) != 0
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import socket
|
||||
import select
|
||||
import logging
|
||||
import select
|
||||
import socket
|
||||
import struct
|
||||
import time
|
||||
|
||||
DEFAULT_TIMEOUT = 10
|
||||
SLEEP_BETWEEN_POLL = 0.5
|
||||
BANNER_READ = 1024
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -32,10 +34,18 @@ def struct_unpack_tracker_string(data, index):
|
|||
"""
|
||||
ascii_len = data[index:].find('\0')
|
||||
fmt = "%ds" % ascii_len
|
||||
return struct_unpack_tracker(data,index,fmt)
|
||||
return struct_unpack_tracker(data, index, fmt)
|
||||
|
||||
|
||||
def check_port_tcp(ip, port, timeout=DEFAULT_TIMEOUT, get_banner=False):
|
||||
def check_tcp_port(ip, port, timeout=DEFAULT_TIMEOUT, get_banner=False):
|
||||
"""
|
||||
Checks if a given TCP port is open
|
||||
:param ip: Target IP
|
||||
:param port: Target Port
|
||||
:param timeout: Timeout for socket connection
|
||||
:param get_banner: if true, pulls first BANNER_READ bytes from the socket.
|
||||
:return: Tuple, T/F + banner if requested.
|
||||
"""
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(timeout)
|
||||
|
||||
|
@ -43,7 +53,7 @@ def check_port_tcp(ip, port, timeout=DEFAULT_TIMEOUT, get_banner=False):
|
|||
sock.connect((ip, port))
|
||||
except socket.timeout:
|
||||
return False, None
|
||||
except socket.error, exc:
|
||||
except socket.error as exc:
|
||||
LOG.debug("Check port: %s:%s, Exception: %s", ip, port, exc)
|
||||
return False, None
|
||||
|
||||
|
@ -54,26 +64,96 @@ def check_port_tcp(ip, port, timeout=DEFAULT_TIMEOUT, get_banner=False):
|
|||
read_ready, _, _ = select.select([sock], [], [], timeout)
|
||||
if len(read_ready) > 0:
|
||||
banner = sock.recv(BANNER_READ)
|
||||
except:
|
||||
except socket.error:
|
||||
pass
|
||||
|
||||
|
||||
sock.close()
|
||||
return True, banner
|
||||
|
||||
|
||||
def check_port_udp(ip, port, timeout=DEFAULT_TIMEOUT):
|
||||
def check_udp_port(ip, port, timeout=DEFAULT_TIMEOUT):
|
||||
"""
|
||||
Checks if a given UDP port is open by checking if it replies to an empty message
|
||||
:param ip: Target IP
|
||||
:param port: Target port
|
||||
:param timeout: Timeout to wait
|
||||
:return: Tuple, T/F + banner
|
||||
"""
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.settimeout(timeout)
|
||||
|
||||
|
||||
data = None
|
||||
is_open = False
|
||||
|
||||
|
||||
try:
|
||||
sock.sendto("-", (ip, port))
|
||||
data, _ = sock.recvfrom(BANNER_READ)
|
||||
is_open = True
|
||||
except:
|
||||
except socket.error:
|
||||
pass
|
||||
sock.close()
|
||||
|
||||
return is_open, data
|
||||
|
||||
|
||||
def check_tcp_ports(ip, ports, timeout=DEFAULT_TIMEOUT, get_banner=False):
|
||||
"""
|
||||
Checks whether any of the given ports are open on a target IP.
|
||||
:param ip: IP of host to attack
|
||||
:param ports: List of ports to attack. Must not be empty.
|
||||
:param timeout: Amount of time to wait for connection.
|
||||
:param get_banner: T/F if to get first packets from server
|
||||
:return: list of open ports. If get_banner=True, then a matching list of banners.
|
||||
"""
|
||||
sockets = [socket.socket(socket.AF_INET, socket.SOCK_STREAM) for _ in range(len(ports))]
|
||||
[s.setblocking(0) for s in sockets]
|
||||
port_attempts = []
|
||||
try:
|
||||
for sock, port in zip(sockets, ports):
|
||||
LOG.debug("Connecting to port %d" % port)
|
||||
err = sock.connect_ex((ip, port))
|
||||
if err == 0:
|
||||
port_attempts.append((port, sock))
|
||||
if err == 10035: # WSAEWOULDBLOCK is valid, see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
|
||||
port_attempts.append((port, sock))
|
||||
if len(port_attempts) != 0:
|
||||
num_replies = 0
|
||||
timeout = int(round(timeout)) # clamp to integer, to avoid checking input
|
||||
time_left = timeout
|
||||
write_sockets = []
|
||||
read_sockets = []
|
||||
while num_replies != len(port_attempts):
|
||||
# bad ports show up as err_sockets
|
||||
read_sockets, write_sockets, err_sockets = \
|
||||
select.select(
|
||||
[s[1] for s in port_attempts],
|
||||
[s[1] for s in port_attempts],
|
||||
[s[1] for s in port_attempts],
|
||||
time_left)
|
||||
# any read_socket is automatically a writesocket
|
||||
num_replies = len(write_sockets) + len(err_sockets)
|
||||
if num_replies == len(port_attempts) or time_left <= 0:
|
||||
break
|
||||
else:
|
||||
time_left -= SLEEP_BETWEEN_POLL
|
||||
time.sleep(SLEEP_BETWEEN_POLL)
|
||||
|
||||
connected_ports_sockets = [x for x in port_attempts if x[1] in write_sockets]
|
||||
LOG.debug(
|
||||
"On host %s discovered the following ports %s" %
|
||||
(str(ip), ",".join([str(x) for x in connected_ports_sockets])))
|
||||
banners = []
|
||||
if get_banner:
|
||||
# read first X bytes
|
||||
banners = [sock.recv(BANNER_READ) if sock in read_sockets else ""
|
||||
for port, sock in connected_ports_sockets]
|
||||
pass
|
||||
# try to cleanup
|
||||
[s[1].close() for s in port_attempts]
|
||||
return [port for port, sock in connected_ports_sockets], banners
|
||||
else:
|
||||
return [], []
|
||||
|
||||
except socket.error as exc:
|
||||
LOG.warning("Exception when checking ports on host %s, Exception: %s", str(ip), exc)
|
||||
return [], []
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import logging
|
||||
import socket
|
||||
import sys
|
||||
|
||||
|
@ -6,6 +7,8 @@ from enum import IntEnum
|
|||
|
||||
from network.info import get_host_subnets
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Linux doesn't have WindowsError
|
||||
try:
|
||||
WindowsError
|
||||
|
@ -56,8 +59,9 @@ class InfoCollector(object):
|
|||
def get_hostname(self):
|
||||
"""
|
||||
Adds the fully qualified computer hostname to the system information.
|
||||
:return: Nothing
|
||||
:return: None. Updates class information
|
||||
"""
|
||||
LOG.debug("Reading hostname")
|
||||
self.info['hostname'] = socket.getfqdn()
|
||||
|
||||
def get_process_list(self):
|
||||
|
@ -65,8 +69,9 @@ class InfoCollector(object):
|
|||
Adds process information from the host to the system information.
|
||||
Currently lists process name, ID, parent ID, command line
|
||||
and the full image path of each process.
|
||||
:return: Nothing
|
||||
:return: None. Updates class information
|
||||
"""
|
||||
LOG.debug("Reading process list")
|
||||
processes = {}
|
||||
for process in psutil.process_iter():
|
||||
try:
|
||||
|
@ -95,6 +100,7 @@ class InfoCollector(object):
|
|||
Adds network information from the host to the system information.
|
||||
Currently updates with a list of networks accessible from host,
|
||||
containing host ip and the subnet range.
|
||||
:return: None
|
||||
:return: None. Updates class information
|
||||
"""
|
||||
LOG.debug("Reading subnets")
|
||||
self.info['network_info'] = {'networks': get_host_subnets()}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import logging
|
||||
|
||||
from . import InfoCollector
|
||||
|
||||
__author__ = 'uri'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LinuxInfoCollector(InfoCollector):
|
||||
"""
|
||||
|
@ -12,6 +16,12 @@ class LinuxInfoCollector(InfoCollector):
|
|||
super(LinuxInfoCollector, self).__init__()
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
Collect Linux system information
|
||||
Hostname, process list and network subnets
|
||||
:return: Dict of system information
|
||||
"""
|
||||
LOG.debug("Running Linux collector")
|
||||
self.get_hostname()
|
||||
self.get_process_list()
|
||||
self.get_network_info()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import ctypes
|
||||
import binascii
|
||||
import ctypes
|
||||
import logging
|
||||
import socket
|
||||
|
||||
|
@ -8,13 +8,14 @@ __author__ = 'itay.mizeretz'
|
|||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MimikatzCollector:
|
||||
class MimikatzCollector(object):
|
||||
"""
|
||||
Password collection module for Windows using Mimikatz.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
|
||||
self._isInit = False
|
||||
self._config = __import__('config').WormConfiguration
|
||||
self._dll = ctypes.WinDLL(self._config.mimikatz_dll_name)
|
||||
|
@ -31,9 +32,9 @@ class MimikatzCollector:
|
|||
Gets the logon info from mimikatz.
|
||||
Returns a dictionary of users with their known credentials.
|
||||
"""
|
||||
|
||||
if not self._isInit:
|
||||
return {}
|
||||
LOG.debug("Running mimikatz collector")
|
||||
|
||||
try:
|
||||
entry_count = self._collect()
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
from . import InfoCollector
|
||||
import logging
|
||||
|
||||
from mimikatz_collector import MimikatzCollector
|
||||
from . import InfoCollector
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
__author__ = 'uri'
|
||||
|
||||
|
||||
|
@ -12,6 +17,13 @@ class WindowsInfoCollector(InfoCollector):
|
|||
super(WindowsInfoCollector, self).__init__()
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
Collect Windows system information
|
||||
Hostname, process list and network subnets
|
||||
Tries to read credential secrets using mimikatz
|
||||
:return: Dict of system information
|
||||
"""
|
||||
LOG.debug("Running Windows collector")
|
||||
self.get_hostname()
|
||||
self.get_process_list()
|
||||
self.get_network_info()
|
||||
|
|
|
@ -8,7 +8,7 @@ from threading import Thread
|
|||
from model import VictimHost
|
||||
from network.firewall import app as firewall
|
||||
from network.info import local_ips, get_free_tcp_port
|
||||
from network.tools import check_port_tcp
|
||||
from network.tools import check_tcp_port
|
||||
from transport.base import get_last_serve_time
|
||||
|
||||
__author__ = 'hoffer'
|
||||
|
@ -40,7 +40,7 @@ def _check_tunnel(address, port, existing_sock=None):
|
|||
sock = existing_sock
|
||||
|
||||
LOG.debug("Checking tunnel %s:%s", address, port)
|
||||
is_open, _ = check_port_tcp(address, int(port))
|
||||
is_open, _ = check_tcp_port(address, int(port))
|
||||
if not is_open:
|
||||
LOG.debug("Could not connect to %s:%s", address, port)
|
||||
if not existing_sock:
|
||||
|
|
|
@ -17,6 +17,7 @@ from cc.resources.edge import Edge
|
|||
from cc.resources.node import Node
|
||||
from cc.resources.report import Report
|
||||
from cc.resources.root import Root
|
||||
from cc.resources.telemetry_feed import TelemetryFeed
|
||||
from cc.services.config import ConfigService
|
||||
|
||||
__author__ = 'Barak'
|
||||
|
@ -89,5 +90,6 @@ def init_app(mongo_url):
|
|||
api.add_resource(Edge, '/api/netmap/edge', '/api/netmap/edge/')
|
||||
api.add_resource(Node, '/api/netmap/node', '/api/netmap/node/')
|
||||
api.add_resource(Report, '/api/report', '/api/report/')
|
||||
api.add_resource(TelemetryFeed, '/api/telemetry-feed', '/api/telemetry-feed/')
|
||||
|
||||
return app
|
||||
|
|
|
@ -36,7 +36,7 @@ def run_local_monkey():
|
|||
|
||||
# run the monkey
|
||||
try:
|
||||
args = ["%s m0nk3y -s %s:%s" % (target_path, local_ip_addresses()[0], ISLAND_PORT)]
|
||||
args = ['"%s" m0nk3y -s %s:%s' % (target_path, local_ip_addresses()[0], ISLAND_PORT)]
|
||||
if sys.platform == "win32":
|
||||
args = "".join(args)
|
||||
pid = subprocess.Popen(args, shell=True).pid
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
from datetime import datetime
|
||||
|
||||
import dateutil
|
||||
import flask_restful
|
||||
from flask import request
|
||||
|
||||
from cc.database import mongo
|
||||
from cc.services.node import NodeService
|
||||
|
||||
__author__ = 'itay.mizeretz'
|
||||
|
||||
|
||||
class TelemetryFeed(flask_restful.Resource):
|
||||
def get(self, **kw):
|
||||
timestamp = request.args.get('timestamp')
|
||||
if "null" == timestamp or timestamp is None: # special case to avoid ugly JS code...
|
||||
telemetries = mongo.db.telemetry.find({})
|
||||
else:
|
||||
telemetries = mongo.db.telemetry.find({'timestamp': {'$gt': dateutil.parser.parse(timestamp)}})
|
||||
|
||||
return \
|
||||
{
|
||||
'telemetries': [TelemetryFeed.get_displayed_telemetry(telem) for telem in telemetries],
|
||||
'timestamp': datetime.now().isoformat()
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_displayed_telemetry(telem):
|
||||
return \
|
||||
{
|
||||
'id': telem['_id'],
|
||||
'timestamp': telem['timestamp'].strftime('%d/%m/%Y %H:%M:%S'),
|
||||
'hostname': NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname'],
|
||||
'brief': TELEM_PROCESS_DICT[telem['telem_type']](telem)
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_tunnel_telem_brief(telem):
|
||||
tunnel = telem['data']['proxy']
|
||||
if tunnel is None:
|
||||
return 'No tunnel is used.'
|
||||
else:
|
||||
tunnel_host_ip = tunnel.split(":")[-2].replace("//", "")
|
||||
tunnel_host = NodeService.get_monkey_by_ip(tunnel_host_ip)['hostname']
|
||||
return 'Tunnel set up to machine: %s.' % tunnel_host
|
||||
|
||||
@staticmethod
|
||||
def get_state_telem_brief(telem):
|
||||
if telem['data']['done']:
|
||||
return 'Monkey died.'
|
||||
else:
|
||||
return 'Monkey started.'
|
||||
|
||||
@staticmethod
|
||||
def get_exploit_telem_brief(telem):
|
||||
target = telem['data']['machine']['ip_addr']
|
||||
exploiter = telem['data']['exploiter']
|
||||
result = telem['data']['result']
|
||||
if result:
|
||||
return 'Monkey successfully exploited %s using the %s exploiter.' % (target, exploiter)
|
||||
else:
|
||||
return 'Monkey failed exploiting %s using the %s exploiter.' % (target, exploiter)
|
||||
|
||||
@staticmethod
|
||||
def get_scan_telem_brief(telem):
|
||||
return 'Monkey discovered machine %s.' % telem['data']['machine']['ip_addr']
|
||||
|
||||
@staticmethod
|
||||
def get_systeminfo_telem_brief(telem):
|
||||
return 'Monkey collected system information.'
|
||||
|
||||
@staticmethod
|
||||
def get_trace_telem_brief(telem):
|
||||
return 'Monkey reached max depth.'
|
||||
|
||||
|
||||
TELEM_PROCESS_DICT = \
|
||||
{
|
||||
'tunnel': TelemetryFeed.get_tunnel_telem_brief,
|
||||
'state': TelemetryFeed.get_state_telem_brief,
|
||||
'exploit': TelemetryFeed.get_exploit_telem_brief,
|
||||
'scan': TelemetryFeed.get_scan_telem_brief,
|
||||
'system_info_collection': TelemetryFeed.get_systeminfo_telem_brief,
|
||||
'trace': TelemetryFeed.get_trace_telem_brief
|
||||
}
|
|
@ -15,7 +15,9 @@ class MapPageComponent extends React.Component {
|
|||
selected: null,
|
||||
selectedType: null,
|
||||
killPressed: false,
|
||||
showKillDialog: false
|
||||
showKillDialog: false,
|
||||
telemetry: [],
|
||||
telemetryLastTimestamp: null
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -25,13 +27,18 @@ class MapPageComponent extends React.Component {
|
|||
|
||||
componentDidMount() {
|
||||
this.updateMapFromServer();
|
||||
this.interval = setInterval(this.updateMapFromServer, 1000);
|
||||
this.interval = setInterval(this.timedEvents, 1000);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
timedEvents = () => {
|
||||
this.updateMapFromServer();
|
||||
this.updateTelemetryFromServer();
|
||||
};
|
||||
|
||||
updateMapFromServer = () => {
|
||||
fetch('/api/netmap')
|
||||
.then(res => res.json())
|
||||
|
@ -44,6 +51,21 @@ class MapPageComponent extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
updateTelemetryFromServer = () => {
|
||||
fetch('/api/telemetry-feed?timestamp='+this.state.telemetryLastTimestamp)
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
let newTelem = this.state.telemetry.concat(res['telemetries']);
|
||||
|
||||
this.setState(
|
||||
{
|
||||
telemetry: newTelem,
|
||||
telemetryLastTimestamp: res['timestamp']
|
||||
});
|
||||
this.props.onStatusChange();
|
||||
});
|
||||
};
|
||||
|
||||
selectionChanged(event) {
|
||||
if (event.nodes.length === 1) {
|
||||
fetch('/api/netmap/node?id=' + event.nodes[0])
|
||||
|
@ -104,6 +126,26 @@ class MapPageComponent extends React.Component {
|
|||
)
|
||||
};
|
||||
|
||||
renderTelemetryEntry(telemetry) {
|
||||
return (
|
||||
<div key={telemetry.id}>
|
||||
<span className="date">{telemetry.timestamp}</span>
|
||||
<span className="source"> {telemetry.hostname}:</span>
|
||||
<span className="event"> {telemetry.brief}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderTelemetryConsole() {
|
||||
return (
|
||||
<div className="telemetry-console">
|
||||
{
|
||||
this.state.telemetry.map(this.renderTelemetryEntry)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
|
@ -122,17 +164,7 @@ class MapPageComponent extends React.Component {
|
|||
<b style={{color: '#aeaeae'}}> | </b>
|
||||
<span>Island Communication <i className="fa fa-lg fa-minus" style={{color: '#a9aaa9'}} /></span>
|
||||
</div>
|
||||
{
|
||||
/*
|
||||
<div className="telemetry-console">
|
||||
<div>
|
||||
<span className="date">2017-10-16 16:00:05</span>
|
||||
<span className="source"> monkey-elastic</span>
|
||||
<span className="event"> bla bla</span>
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
}
|
||||
{ this.renderTelemetryConsole() }
|
||||
<div style={{height: '80vh'}}>
|
||||
<ReactiveGraph graph={this.state.graph} options={options} events={this.events}/>
|
||||
</div>
|
||||
|
|
|
@ -277,13 +277,14 @@ body {
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 70px;
|
||||
height: 130px;
|
||||
background: rgba(0,0,0,0.7);
|
||||
border-radius: 5px;
|
||||
border: 3px solid #aaa;
|
||||
padding: 0.5em;
|
||||
color: white;
|
||||
font-family: Consolas, "Courier New", monospace;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.telemetry-console .date {
|
||||
|
|
|
@ -2,16 +2,17 @@
|
|||
|
||||
MONKEY_FOLDER=/var/monkey_island
|
||||
INSTALLATION_FOLDER=/var/monkey_island/installation
|
||||
PYTHON_FOLDER=/var/monkey_island/bin/python
|
||||
|
||||
cp -f ${MONKEY_FOLDER}/monkey.sh /usr/bin/monkey
|
||||
chmod 755 /usr/bin/monkey
|
||||
|
||||
# Fix dependency bug
|
||||
pip uninstall -y bson
|
||||
# Prepare python virtualenv
|
||||
pip2 install virtualenv --no-index --find-links file://$INSTALLATION_FOLDER
|
||||
virtualenv -p python2.7 ${PYTHON_FOLDER}
|
||||
|
||||
# install pip requirements
|
||||
pip install -r $MONKEY_FOLDER/pip_requirements.txt --no-index --find-links file://$INSTALLATION_FOLDER
|
||||
|
||||
${PYTHON_FOLDER}/bin/python -m pip install -r $MONKEY_FOLDER/pip_requirements.txt --no-index --find-links file://$INSTALLATION_FOLDER
|
||||
|
||||
# remove installation folder and unnecessary files
|
||||
rm -rf ${INSTALLATION_FOLDER}
|
||||
|
|
|
@ -8,4 +8,6 @@ rm -f /etc/init/monkey-mongo.conf
|
|||
[ -f "/lib/systemd/system/monkey-island.service" ] && rm -f /lib/systemd/system/monkey-island.service
|
||||
[ -f "/lib/systemd/system/monkey-mongo.service" ] && rm -f /lib/systemd/system/monkey-mongo.service
|
||||
|
||||
rm -r -f /var/monkey_island
|
||||
|
||||
exit 0
|
|
@ -9,4 +9,5 @@ flask
|
|||
Flask-Pymongo
|
||||
Flask-Restful
|
||||
jsonschema
|
||||
netifaces
|
||||
netifaces
|
||||
virtualenv
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd /var/monkey_island/cc
|
||||
python main.py
|
||||
/var/monkey_island/bin/python/bin/python main.py
|
|
@ -0,0 +1 @@
|
|||
xcopy %1 %2
|
|
@ -1,3 +1,18 @@
|
|||
bin\openssl\openssl.exe genrsa -out cc\server.key 1024
|
||||
bin\openssl\openssl.exe req -new -config bin\openssl\openssl.cfg -key cc\server.key -out cc\server.csr -subj "/C=GB/ST=London/L=London/O=Global Security/OU=Monkey Department/CN=monkey.com"
|
||||
bin\openssl\openssl.exe x509 -req -days 366 -in cc\server.csr -signkey cc\server.key -out cc\server.crt
|
||||
@echo off
|
||||
|
||||
IF [%1] == [] (
|
||||
set mydir=%cd%\
|
||||
) ELSE (
|
||||
set mydir=%~1%
|
||||
)
|
||||
|
||||
echo Monkey Island folder: %mydir%
|
||||
|
||||
SET OPENSSL_CONF=%mydir%bin\openssl\openssl.cfg
|
||||
copy "%mydir%windows\openssl.cfg" "%mydir%bin\openssl\openssl.cfg"
|
||||
|
||||
@echo on
|
||||
|
||||
"%mydir%bin\openssl\openssl.exe" genrsa -out "%mydir%cc\server.key" 1024
|
||||
"%mydir%bin\openssl\openssl.exe" req -new -config "%mydir%bin\openssl\openssl.cfg" -key "%mydir%cc\server.key" -out "%mydir%cc\server.csr" -subj "/C=GB/ST=London/L=London/O=Global Security/OU=Monkey Department/CN=monkey.com"
|
||||
"%mydir%bin\openssl\openssl.exe" x509 -req -days 366 -in "%mydir%cc\server.csr" -signkey "%mydir%cc\server.key" -out "%mydir%cc\server.crt"
|
|
@ -0,0 +1,350 @@
|
|||
#
|
||||
# OpenSSL example configuration file.
|
||||
# This is mostly being used for generation of certificate requests.
|
||||
#
|
||||
|
||||
# This definition stops the following lines choking if HOME isn't
|
||||
# defined.
|
||||
HOME = .
|
||||
RANDFILE = $ENV::HOME/.rnd
|
||||
|
||||
# Extra OBJECT IDENTIFIER info:
|
||||
#oid_file = $ENV::HOME/.oid
|
||||
oid_section = new_oids
|
||||
|
||||
# To use this configuration file with the "-extfile" option of the
|
||||
# "openssl x509" utility, name here the section containing the
|
||||
# X.509v3 extensions to use:
|
||||
# extensions =
|
||||
# (Alternatively, use a configuration file that has only
|
||||
# X.509v3 extensions in its main [= default] section.)
|
||||
|
||||
[ new_oids ]
|
||||
|
||||
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
|
||||
# Add a simple OID like this:
|
||||
# testoid1=1.2.3.4
|
||||
# Or use config file substitution like this:
|
||||
# testoid2=${testoid1}.5.6
|
||||
|
||||
# Policies used by the TSA examples.
|
||||
tsa_policy1 = 1.2.3.4.1
|
||||
tsa_policy2 = 1.2.3.4.5.6
|
||||
tsa_policy3 = 1.2.3.4.5.7
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
####################################################################
|
||||
[ CA_default ]
|
||||
|
||||
dir = ./demoCA # Where everything is kept
|
||||
certs = $dir/certs # Where the issued certs are kept
|
||||
crl_dir = $dir/crl # Where the issued crl are kept
|
||||
database = $dir/index.txt # database index file.
|
||||
#unique_subject = no # Set to 'no' to allow creation of
|
||||
# several ctificates with same subject.
|
||||
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||
|
||||
certificate = $dir/cacert.pem # The CA certificate
|
||||
serial = $dir/serial # The current serial number
|
||||
crlnumber = $dir/crlnumber # the current crl number
|
||||
# must be commented out to leave a V1 CRL
|
||||
crl = $dir/crl.pem # The current CRL
|
||||
private_key = $dir/private/cakey.pem# The private key
|
||||
RANDFILE = $dir/private/.rand # private random number file
|
||||
|
||||
x509_extensions = usr_cert # The extentions to add to the cert
|
||||
|
||||
# Comment out the following two lines for the "traditional"
|
||||
# (and highly broken) format.
|
||||
name_opt = ca_default # Subject Name options
|
||||
cert_opt = ca_default # Certificate field options
|
||||
|
||||
# Extension copying option: use with caution.
|
||||
# copy_extensions = copy
|
||||
|
||||
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||
# so this is commented out by default to leave a V1 CRL.
|
||||
# crlnumber must also be commented out to leave a V1 CRL.
|
||||
# crl_extensions = crl_ext
|
||||
|
||||
default_days = 365 # how long to certify for
|
||||
default_crl_days= 30 # how long before next CRL
|
||||
default_md = default # use public key default MD
|
||||
preserve = no # keep passed DN ordering
|
||||
|
||||
# A few difference way of specifying how similar the request should look
|
||||
# For type CA, the listed attributes must be the same, and the optional
|
||||
# and supplied fields are just that :-)
|
||||
policy = policy_match
|
||||
|
||||
# For the CA policy
|
||||
[ policy_match ]
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
# For the 'anything' policy
|
||||
# At this point in time, you must list all acceptable 'object'
|
||||
# types.
|
||||
[ policy_anything ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = privkey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
||||
|
||||
# Passwords for private keys if not present they will be prompted for
|
||||
# input_password = secret
|
||||
# output_password = secret
|
||||
|
||||
# This sets a mask for permitted string types. There are several options.
|
||||
# default: PrintableString, T61String, BMPString.
|
||||
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
|
||||
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
|
||||
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||
# MASK:XXXX a literal mask value.
|
||||
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
|
||||
string_mask = utf8only
|
||||
|
||||
# req_extensions = v3_req # The extensions to add to a certificate request
|
||||
|
||||
[ req_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = AU
|
||||
countryName_min = 2
|
||||
countryName_max = 2
|
||||
|
||||
stateOrProvinceName = State or Province Name (full name)
|
||||
stateOrProvinceName_default = Some-State
|
||||
|
||||
localityName = Locality Name (eg, city)
|
||||
|
||||
0.organizationName = Organization Name (eg, company)
|
||||
0.organizationName_default = Internet Widgits Pty Ltd
|
||||
|
||||
# we can do this but it is not needed normally :-)
|
||||
#1.organizationName = Second Organization Name (eg, company)
|
||||
#1.organizationName_default = World Wide Web Pty Ltd
|
||||
|
||||
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||
#organizationalUnitName_default =
|
||||
|
||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||
commonName_max = 64
|
||||
|
||||
emailAddress = Email Address
|
||||
emailAddress_max = 64
|
||||
|
||||
# SET-ex3 = SET extension number 3
|
||||
|
||||
[ req_attributes ]
|
||||
challengePassword = A challenge password
|
||||
challengePassword_min = 4
|
||||
challengePassword_max = 20
|
||||
|
||||
unstructuredName = An optional company name
|
||||
|
||||
[ usr_cert ]
|
||||
|
||||
# These extensions are added when 'ca' signs a request.
|
||||
|
||||
# This goes against PKIX guidelines but some CAs do it and some software
|
||||
# requires this to avoid interpreting an end user certificate as a CA.
|
||||
|
||||
basicConstraints=CA:FALSE
|
||||
|
||||
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||
# the certificate can be used for anything *except* object signing.
|
||||
|
||||
# This is OK for an SSL server.
|
||||
# nsCertType = server
|
||||
|
||||
# For an object signing certificate this would be used.
|
||||
# nsCertType = objsign
|
||||
|
||||
# For normal client use this is typical
|
||||
# nsCertType = client, email
|
||||
|
||||
# and for everything including object signing:
|
||||
# nsCertType = client, email, objsign
|
||||
|
||||
# This is typical in keyUsage for a client certificate.
|
||||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
# This will be displayed in Netscape's comment listbox.
|
||||
nsComment = "OpenSSL Generated Certificate"
|
||||
|
||||
# PKIX recommendations harmless if included in all certificates.
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
|
||||
# This stuff is for subjectAltName and issuerAltname.
|
||||
# Import the email address.
|
||||
# subjectAltName=email:copy
|
||||
# An alternative to produce certificates that aren't
|
||||
# deprecated according to PKIX.
|
||||
# subjectAltName=email:move
|
||||
|
||||
# Copy subject details
|
||||
# issuerAltName=issuer:copy
|
||||
|
||||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||
#nsBaseUrl
|
||||
#nsRevocationUrl
|
||||
#nsRenewalUrl
|
||||
#nsCaPolicyUrl
|
||||
#nsSslServerName
|
||||
|
||||
# This is required for TSA certificates.
|
||||
# extendedKeyUsage = critical,timeStamping
|
||||
|
||||
[ v3_req ]
|
||||
|
||||
# Extensions to add to a certificate request
|
||||
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
[ v3_ca ]
|
||||
|
||||
|
||||
# Extensions for a typical CA
|
||||
|
||||
|
||||
# PKIX recommendation.
|
||||
|
||||
subjectKeyIdentifier=hash
|
||||
|
||||
authorityKeyIdentifier=keyid:always,issuer
|
||||
|
||||
# This is what PKIX recommends but some broken software chokes on critical
|
||||
# extensions.
|
||||
#basicConstraints = critical,CA:true
|
||||
# So we do this instead.
|
||||
basicConstraints = CA:true
|
||||
|
||||
# Key usage: this is typical for a CA certificate. However since it will
|
||||
# prevent it being used as an test self-signed certificate it is best
|
||||
# left out by default.
|
||||
# keyUsage = cRLSign, keyCertSign
|
||||
|
||||
# Some might want this also
|
||||
# nsCertType = sslCA, emailCA
|
||||
|
||||
# Include email address in subject alt name: another PKIX recommendation
|
||||
# subjectAltName=email:copy
|
||||
# Copy issuer details
|
||||
# issuerAltName=issuer:copy
|
||||
|
||||
# DER hex encoding of an extension: beware experts only!
|
||||
# obj=DER:02:03
|
||||
# Where 'obj' is a standard or added object
|
||||
# You can even override a supported extension:
|
||||
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||
|
||||
[ crl_ext ]
|
||||
|
||||
# CRL extensions.
|
||||
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||
|
||||
# issuerAltName=issuer:copy
|
||||
authorityKeyIdentifier=keyid:always
|
||||
|
||||
[ proxy_cert_ext ]
|
||||
# These extensions should be added when creating a proxy certificate
|
||||
|
||||
# This goes against PKIX guidelines but some CAs do it and some software
|
||||
# requires this to avoid interpreting an end user certificate as a CA.
|
||||
|
||||
basicConstraints=CA:FALSE
|
||||
|
||||
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||
# the certificate can be used for anything *except* object signing.
|
||||
|
||||
# This is OK for an SSL server.
|
||||
# nsCertType = server
|
||||
|
||||
# For an object signing certificate this would be used.
|
||||
# nsCertType = objsign
|
||||
|
||||
# For normal client use this is typical
|
||||
# nsCertType = client, email
|
||||
|
||||
# and for everything including object signing:
|
||||
# nsCertType = client, email, objsign
|
||||
|
||||
# This is typical in keyUsage for a client certificate.
|
||||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
# This will be displayed in Netscape's comment listbox.
|
||||
nsComment = "OpenSSL Generated Certificate"
|
||||
|
||||
# PKIX recommendations harmless if included in all certificates.
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
|
||||
# This stuff is for subjectAltName and issuerAltname.
|
||||
# Import the email address.
|
||||
# subjectAltName=email:copy
|
||||
# An alternative to produce certificates that aren't
|
||||
# deprecated according to PKIX.
|
||||
# subjectAltName=email:move
|
||||
|
||||
# Copy subject details
|
||||
# issuerAltName=issuer:copy
|
||||
|
||||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||
#nsBaseUrl
|
||||
#nsRevocationUrl
|
||||
#nsRenewalUrl
|
||||
#nsCaPolicyUrl
|
||||
#nsSslServerName
|
||||
|
||||
# This really needs to be in place for it to be a proxy certificate.
|
||||
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
||||
|
||||
####################################################################
|
||||
[ tsa ]
|
||||
|
||||
default_tsa = tsa_config1 # the default TSA section
|
||||
|
||||
[ tsa_config1 ]
|
||||
|
||||
# These are used by the TSA reply generation only.
|
||||
dir = ./demoCA # TSA root directory
|
||||
serial = $dir/tsaserial # The current serial number (mandatory)
|
||||
crypto_device = builtin # OpenSSL engine to use for signing
|
||||
signer_cert = $dir/tsacert.pem # The TSA signing certificate
|
||||
# (optional)
|
||||
certs = $dir/cacert.pem # Certificate chain to include in reply
|
||||
# (optional)
|
||||
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
|
||||
|
||||
default_policy = tsa_policy1 # Policy if request did not specify it
|
||||
# (optional)
|
||||
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
|
||||
digests = md5, sha1 # Acceptable message digests (mandatory)
|
||||
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
|
||||
clock_precision_digits = 0 # number of digits after dot. (optional)
|
||||
ordering = yes # Is ordering defined for timestamps?
|
||||
# (optional, default: no)
|
||||
tsa_name = yes # Must the TSA name be included in the reply?
|
||||
# (optional, default: no)
|
||||
ess_cert_id_chain = no # Must the ESS cert id chain be included?
|
||||
# (optional, default: no)
|
|
@ -0,0 +1 @@
|
|||
del %1
|
|
@ -1,3 +1,4 @@
|
|||
if not exist db mkdir db
|
||||
start windows\run_mongodb.bat
|
||||
start windows\run_cc.bat
|
||||
start windows\run_cc.bat
|
||||
start https://localhost:5000
|
Loading…
Reference in New Issue