Database, WebSockets, REST API, Basic Front End

This commit is contained in:
Evan Reichard 2021-03-19 18:49:14 -04:00
parent 042f83a035
commit 457f79b94f
36 changed files with 1426 additions and 196 deletions

View File

@ -15,5 +15,5 @@ setup(
"flask_socketio",
"sqlalchemy",
],
extras_require={"dev": ["pre-commit", "black", "flake8"]},
extras_require={"dev": ["pre-commit", "black", "flake8", "pytest"]},
)

View File

@ -1,10 +1,17 @@
import click
from importlib.metadata import version
from overseer.config import EnvConfig
from overseer.scanner import ScanManager
from overseer.database import DatabaseConnector
from flask import Flask
from flask.cli import FlaskGroup
__version__ = version("overseer")
app = Flask(__name__)
config = EnvConfig()
database = DatabaseConnector(config.DATA_PATH)
scan_manager = ScanManager()
def create_app():

View File

@ -0,0 +1,25 @@
open_websockets = []
"""
EVENT:
DATA:
{
id: 1,
target: "127.0.0.1",
total_progress: 90,
tcp_progress: 80,
udp_progress: 100,
}
"""
def send_websocket_event(data):
"""Send an event to all registered websockets.
Arguments:
data -- Data to send over the websocket(s)
"""
print("EMITTING DATA: %s" % data)
for socket in open_websockets:
socket.send(data)

View File

@ -1,7 +1,9 @@
from overseer import app
from overseer.api import open_websockets
from flask_socketio import SocketIO
socketio = SocketIO(app, path="/api/v1/socket.io")
open_websockets.append(socketio)
@socketio.on("message")

View File

@ -1,11 +1,91 @@
import overseer
from overseer.api.v1 import api
from flask import request
@api.route("/status", methods=["GET"])
def status():
return "STATUS PLACEHOLDER"
"""
GET:
REQUEST: /api/v1/status
RESPONSE:
{
version: "0.0.1",,
active_scans: [
<WEBSOCKET_DATA>
],
}
"""
return {
"version": overseer.__version__,
"active_scans": overseer.scan_manager.get_status(),
}
@api.route("/scan", methods=["GET"])
def scan():
return "SCAN PLACEHOLDER"
@api.route("/scans", methods=["POST"])
def scans_post():
"""
POST:
REQUEST: /api/v1/scans
DATA: { target: 'www.google.com' }
RESPONSE: { status: "started" }
"""
data = request.get_json()
if data is None or "target" not in data:
return {"error": "Missing 'target'"}, 422
history_id = overseer.scan_manager.perform_scan(data["target"])
if history_id is None:
return {"error": "Unable to resolve hostname."}, 422
return {"status": "started", "id": history_id}
@api.route("/scans/<string:target>", methods=["GET"])
def scan_get_history(target):
"""
GET:
REQUEST: /api/v1/scans/www.google.com
/api/v1/scans/1.1.1.1
RESPONSE: { "data": [ <ARRAY_OF_SCAN_HISTORY> ] }
"""
page = 1
if overseer.scan_manager.is_ip(target):
scan_results = overseer.database.get_scan_results_by_target(
page, ip_addr=target
)
else:
scan_results = overseer.database.get_scan_results_by_target(
page, hostname=target
)
return {"data": __normalize_scan_results(scan_results)}
# TODO
@api.route("/search", methods=["GET"])
def scan_get_all(search):
"""
GET:
REQUEST: /api/v1/search?query=1.1.1.1
/api/v1/search?query=192.168.0.0/24
/api/v1/search?query=www.google.com&page=2
RESPONSE: { data: [ <ARRAY_OF_TARGETS> ] }
"""
return "SEARCH PLACEHOLDER"
def __normalize_scan_results(scan_results):
return list(
map(
lambda x: {
"results": x.results.split(","),
"created_at": x.created_at,
"status": x.status,
"error": x.error,
},
scan_results,
)
)

View File

@ -9,3 +9,4 @@ def get_env(key, default=None, required=False):
class EnvConfig:
DATABASE = get_env("OVERSEER_DB", default="sqlite")
DATA_PATH = get_env("OVERSEER_DATA_PATH", default="./")

View File

@ -1,105 +1,139 @@
import models
from overseer.models import Base, ScanTarget, ScanHistory
import ipaddress
from datetime import datetime
from os import path
from sqlalchemy import (
create_engine,
or_,
)
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from sqlalchemy.orm.exc import NoResultFound
class DatabaseConnector:
def __init__(self, data_path, in_memory=False):
if in_memory:
self.engine = create_engine(
"sqlite+pysqlite:///:memory:", echo=True, future=True
"sqlite+pysqlite:///:memory:", echo=False, future=True
)
else:
db_path = path.join(data_path, "overseer.sqlite")
self.engine = create_engine(
"sqlite+pysqlite:///%s" % db_path,
echo=True,
echo=False,
future=True,
)
models.Base.metadata.create_all(self.engine)
Base.metadata.create_all(self.engine)
self.__cleanup_stale_records()
def create_scan_result(self, ip_addr, scan_results, hostname=None):
int_ip_addr = int(ipaddress.ip_addr(ip_addr))
def __cleanup_stale_records(self):
session = Session(bind=self.engine)
history_filter = ScanHistory.status == "IN_PROGRESS"
all_stale = session.query(ScanHistory).filter(history_filter).all()
# Does an existing target exist?
scan_target = (
session.query(models.ScanTarget)
.filter(
or_(
models.ScanTarget.ip == int_ip_addr,
models.ScanTarget.hostname == hostname,
)
)
.first()
)
for stale in all_stale:
stale.status = "FAILED"
stale.message = "Stale history"
# TODO: Do we need to update hostname?
# Nope, create one
if not scan_target:
scan_target = models.ScanTarget(ip=int_ip_addr, hostname=hostname)
session.add(scan_target)
session.commit()
# Create scan history
scan_history = models.ScanHistory(
target_id=scan_target.id,
results=",".join(map(str, scan_results)),
datetime=datetime.now(),
)
session.add(scan_history)
session.commit()
session.close()
def get_scan_results(self, **kwargs):
"""Returns scan results for the queries target.
Keyword arguments:
hostname -- The hostname of the target.
ip_addr -- The IP address of the target.
"""
def create_scan_target(self, **kwargs):
if len(kwargs.keys() & {"ip_addr", "hostname"}) != 1:
raise ValueError("Missing keyword argument: ip_addr or hostname")
hostname = kwargs["hostname"] if "hostname" in kwargs else None
ip_addr = kwargs["ip_addr"] if "ip_addr" in kwargs else None
int_ip_addr = int(ipaddress.ip_addr(ip_addr)) if ip_addr else None
if "ip_addr" in kwargs:
int_ip_addr = int(ipaddress.ip_address(kwargs["ip_addr"]))
scan_target = ScanTarget(ip=int_ip_addr, updated_at=datetime.now())
elif "hostname" in kwargs:
scan_target = ScanTarget(
hostname=kwargs["hostname"], updated_at=datetime.now()
)
session = Session(bind=self.engine, expire_on_commit=False)
session.add(scan_target)
session.commit()
session.close()
return scan_target
def get_scan_target(self, **kwargs):
if len(kwargs.keys() & {"ip_addr", "hostname"}) != 1:
raise ValueError("Missing keyword argument: ip_addr or hostname")
if "ip_addr" in kwargs:
int_ip_addr = int(ipaddress.ip_address(kwargs["ip_addr"]))
target_filter = ScanTarget.ip == int_ip_addr
elif "hostname" in kwargs:
target_filter = ScanTarget.hostname == kwargs["hostname"]
session = Session(bind=self.engine)
scan_target = session.query(ScanTarget).filter(target_filter).first()
session.close()
return scan_target
# Get all scan histories
scan_histories = (
session.query(models.ScanHistory)
.join(models.ScanHistory.target)
.filter(
or_(
models.ScanTarget.ip == int_ip_addr,
models.ScanTarget.hostname == hostname,
)
)
def get_all_scan_targets(self, page=1):
session = Session(bind=self.engine)
scan_targets = (
session.query(ScanTarget)
.order_by(ScanTarget.updated_at.desc())
.offset((page - 1) * 25)
.limit(25)
.all()
)
session.close()
return scan_targets
def create_scan_result(self, status, results=[], error=None, **kwargs):
scan_target = self.get_scan_target(**kwargs)
if not scan_target:
scan_target = self.create_scan_target(**kwargs)
scan_history = ScanHistory(
target_id=scan_target.id,
results=",".join(results),
status=status,
error=error,
created_at=datetime.now(),
)
session = Session(bind=self.engine, expire_on_commit=False)
session.add(scan_history)
session.commit()
session.close()
return scan_history
def update_scan_result(self, history_id, status, results=None, error=None):
session = Session(bind=self.engine, expire_on_commit=False)
scan_history = session.query(ScanHistory).get(history_id)
if scan_history is None:
raise NoResultFound("ScanHistory %s does not exist" % history_id)
scan_history.status = status
if results is not None:
scan_history.results = ",".join(results)
if error is not None:
scan_history.error = error
session.commit()
session.close()
return scan_history
def get_scan_results_by_target(self, page=1, **kwargs):
if len(kwargs.keys() & {"ip_addr", "hostname"}) != 1:
raise ValueError("Missing keyword argument: ip_addr or hostname")
if "ip_addr" in kwargs:
int_ip_addr = int(ipaddress.ip_address(kwargs["ip_addr"]))
history_filter = ScanTarget.ip == int_ip_addr
elif "hostname" in kwargs:
history_filter = ScanTarget.hostname == kwargs["hostname"]
session = Session(bind=self.engine)
scan_histories = (
session.query(ScanHistory)
.join(ScanHistory.target)
.filter(history_filter)
.order_by(ScanHistory.created_at.desc())
.offset((page - 1) * 25)
.limit(25)
.all()
)
session.close()
return scan_histories
# FOR TESTING PURPOSES
def main():
data_path = "/Users/evanreichard/Development/git/overseer/src/overseer"
db = DatabaseConnector(data_path)
db.create_scan_result("1.2.3.4", [5, 6, 7, 8], "test222.com")
db.get_scan_results(ip_addr="1.2.3.4")
if __name__ == "__main__":
main()

View File

@ -13,13 +13,16 @@ class ScanTarget(Base):
# Integer representation of an IP Address
ip = Column(Integer, index=True, unique=True)
# Corresponding hostname.
# Corresponding hostname
hostname = Column(String, index=True, unique=True)
# Updated At
updated_at = Column(DateTime())
def __repr__(self):
return (
f"ScanTarget(id={self.id!r}, ip={self.ip!r}, "
f"hostname={self.hostname!r})"
f"hostname={self.hostname!r}, updated_at={self.updated_at!r})"
)
@ -32,17 +35,24 @@ class ScanHistory(Base):
# Scan Target Reference
target_id = Column(Integer, ForeignKey("scan_target.id"))
# Results
# Results (53 TCP, 53 UDP)
results = Column(String)
# DateTime
datetime = Column(DateTime())
# Created At
created_at = Column(DateTime())
# Status (IN_PROGRESS, COMPLETE, FAILED)
status = Column(String)
# Error Message (If applicable)
error = Column(String)
# Relationship
target = relationship("ScanTarget", foreign_keys=[target_id])
def __repr__(self):
return (
f"ScanHistory(id={self.id!r}, target={self.target!r}, "
f"results={self.results!r}, datetime={self.datetime!r})"
f"ScanHistory(id={self.id!r}, target_id={self.target_id!r}, "
f"results={self.results!r}, created_at={self.created_at!r}, "
f"status={self.status!r}, error={self.error!r})"
)

View File

@ -2,23 +2,20 @@ from overseer import app
from flask import make_response, render_template, send_from_directory
from overseer.api.v1 import api as api_v1
"""
Initial Entrypoint to the SPA (i.e. 'index.html')
"""
@app.route("/", methods=["GET"])
def main_entry():
"""
Initial Entrypoint to the SPA (i.e. 'index.html')
"""
return make_response(render_template("index.html"))
"""
Front End Static Resources
"""
@app.route("/static/<path:path>")
def static_resources(path):
"""
Front End Static Resources
"""
return send_from_directory("static", path)

View File

@ -0,0 +1,498 @@
# Nmap nmap payload database -*- mode: fundamental; -*-
# $Id$
#
# These payloads are sent with every host discovery or port scan probe
# by default. This database should only include payloads that are
# unlikely to crash services, trip IDS alerts, or change state on the
# server. The idea behind these is to evoke a response using a payload.
# Some of them are taken from nmap-service-probes.
#
# This collection of data is (C) 1996-2010 by Insecure.Com
# LLC. It is distributed under the Nmap Public Source license as
# provided in the LICENSE file of the source distribution or at
# https://nmap.org/data/LICENSE . Note that this license
# requires you to license your own work under a compatible open source
# license. If you wish to embed Nmap technology into proprietary
# software, we sell alternative licenses (contact sales@insecure.com).
# Dozens of software vendors already license Nmap technology such as
# host discovery, port scanning, OS detection, and version detection.
# For more details, see https://nmap.org/book/man-legal.html
#
# Each entry begins with a protocol (only "udp" is supported) followed
# by a comma-separated list of ports, followed by one or more quoted
# strings containing the payload. These elements may be broken across
# several lines. For future expansion, additional keywords may follow
# the payload data. Any data following one of these keywords must be on
# the same line as the keyword so that unknown keywords can be ignored
# by the parser. Currently this file contains some entries with the
# "source" keyword to specify a desired source port, but it is not
# honored by Nmap.
#
# Example:
# udp 1234 "payloaddatapayloaddata"
# "payloaddatapayloaddata"
# source 5678
# GenericLines. Use for the echo service.
udp 7 "\x0D\x0A\x0D\x0A"
# DNSStatusRequest
udp 53,5353,26198 "\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# DNS VER
udp 53,5353,26198
"\x77\x77\x01\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03"
# DHCP INFORM
udp 67
"\x01\x01\x06\x00"
"\x01\x23\x45\x67\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x35\xd4\xd8\x51\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63\x35\x01"
"\x08\xff"
# TFTP GET
udp 69 "\x00\x01r7tftp.txt\x00octet\x00"
# QUIC packet with unsupported version Q999
# Also found on 443, but need to check whether DTLS or QUIC is more prevalent
udp 80 "\r12345678Q999\x00"
# RPCCheck
udp 111
"\x72\xFE\x1D\x13\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA0"
"\x00\x01\x97\x7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
# ONCRPC CALL
udp 111,2049,4045,32768-65535
"\x3e\xec\xe3\xca\x00\x00\x00\x00\x00\x00\x00\x02\x00"
"\xbc\x61\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# NTPRequest
udp 123
"\xE3\x00\x04\xFA\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xC5\x4F\x23\x4B\x71\xB1\x52\xF3"
# NTP REQ
udp 123
"\xd9\x00\x0a\xfa\x00\x00\x00"
"\x00\x00\x01\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6"
"\xf1\x5e\xdb\x78\x00\x00\x00"
# DCERPC CALL
udp 135,1025-1199
"\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00"
"\x00\x00\x01\x00\x00\x00\xb8\x10\xb8\x10\x00\x00\x00\x00\x01\x00\x00"
"\x00\x00\x00\x01\x00\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67"
"\x89\xab\xcd\xef\xe7\x03\x00\x00\xfe\xdc\xba\x98\x76\x54\x32\x10\x01"
"\x23\x45\x67\x89\xab\xcd\xef\xe7\x03\x00\x00"
# NBTStat
udp 137
"\x80\xF0\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00"
"\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01"
# CIFS NS NAME QUERY UC
udp 137
"\x01\x91\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01"
# CIFS NS NAME QUERY BC
udp 137
"\x01\x91\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00"
"\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01"
# SNMPv3GetRequest
udp 161,260,3401
"\x30\x3A\x02\x01\x03\x30\x0F\x02\x02\x4A\x69\x02\x03\x00\xFF\xE3"
"\x04\x01\x04\x02\x01\x03\x04\x10\x30\x0E\x04\x00\x02\x01\x00\x02"
"\x01\x00\x04\x00\x04\x00\x04\x00\x30\x12\x04\x00\x04\x00\xA0\x0C"
"\x02\x02\x37\xF0\x02\x01\x00\x02\x01\x00\x30\x00"
# SNMP PUBLIC WALK
udp 161,260,3401
"\x30\x1f\x02\x01\x00\x04\x06public\xa1\x12\x02\x01\x00\x02"
"\x01\x00\x02\x01\x00\x30\x07\x30\x05\x06\x01\x00\x05\x00"
# Sqlping - disabled because it trips a Snort rule with SID 2049
# ("MS-SQL ping attempt").
# udp 1434 "\x02"
# xdmcp - X Display Manager Control Protocol. Version 1, packet type
# Query (2), no authorization names. We expect a Willing or Unwilling
# packet in reply.
# http://cgit.freedesktop.org/xorg/doc/xorg-docs/plain/hardcopy/XDMCP/xdmcp.PS.gz
udp 177 "\x00\x01\x00\x02\x00\x01\x00"
# Connectionless LDAP - used by Microsoft Active Directory
udp 389
"\x30\x84\x00\x00\x00\x2d\x02\x01\x07\x63\x84\x00\x00\x00\x24\x04\x00"
"\x0a\x01\x00\x0a\x01\x00\x02\x01\x00\x02\x01\x64\x01\x01\x00\x87\x0b"
"objectClass0\x84\x00\x00\x00\x00"
# svrloc
udp 427
"\x02\x01\x00\x006 \x00\x00\x00\x00\x00\x01\x00\x02en\x00\x00\x00\x15"
"service:service-agent\x00\x07default\x00\x00\x00\x00"
# DTLS
udp 443,853,3391,4433,4740,5349,5684,5868,6514,6636,8232,10161,10162,12346,12446,12546,12646,12746,12846,12946,13046
# DTLS 1.0, length 52
"\x16\xfe\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x36"
# ClientHello, length 40, sequence 0, offset 0
"\x01\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x2a"
# DTLS 1.2
"\xfe\xfd"
# Random
"\x00\x00\x00\x00\x7c\x77\x40\x1e\x8a\xc8\x22\xa0\xa0\x18\xff\x93"
"\x08\xca\xac\x0a\x64\x2f\xc9\x22\x64\xbc\x08\xa8\x16\x89\x19\x3f"
# Session id length 0, cookie length 0
"\x00\x00"
# Cipher suites, mandatory TLS_RSA_WITH_AES_128_CBC_SHA
"\x00\x02\x00\x2f"
# Compressors (NULL)
"\x01\x00"
# Internet Key Exchange version 1, phase 1 Main Mode. We offer every
# combination of (DES, 3DES) and (MD5, SHA) in the hope that one of them will
# be acceptable. Because we use a fixed cookie, we set the association lifetime
# to 1 second to reduce the chance that repeated probes will look like
# retransmissions (and therefore not get a response). This payload comes from
# ike-scan --lifetime 1 --cookie 0011223344556677 --trans=5,2,1,2 --trans=5,1,1,2 --trans=1,2,1,2 --trans=1,1,1,2
# We expect another phase 1 message in response. This payload works better with
# a source port of 500 or a randomized initiator cookie.
udp 500
# Initiator cookie 0x0011223344556677, responder cookie 0x0000000000000000.
"\x00\x11\x22\x33\x44\x55\x66\x77\x00\x00\x00\x00\x00\x00\x00\x00"
# Version 1, Main Mode, flags 0x00, message ID 0x00000000, length 192.
"\x01\x10\x02\x00\x00\x00\x00\x00\x00\x00\x00\xC0"
# Security Association payload, length 164, IPSEC, IDENTITY.
"\x00\x00\x00\xA4\x00\x00\x00\x01\x00\x00\x00\x01"
# Proposal 1, length 152, ISAKMP, 4 transforms.
"\x00\x00\x00\x98\x01\x01\x00\x04"
# Transform 1, 3DES-CBC, SHA, PSK, group 2.
"\x03\x00\x00\x24\x01\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# Transform 2, 3DES-CBC, MD5, PSK, group 2.
"\x03\x00\x00\x24\x02\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x01"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# Transform 3, DES-CBC, SHA, PSK, group 2.
"\x03\x00\x00\x24\x03\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x02"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# Transform 4, DES-CBC, MD5, PSK, group 2.
"\x00\x00\x00\x24\x04\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x01"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
source 500
# IPSEC START
udp 500,4500
"\x31\x27\xfc"
"\xb0\x38\x10\x9e\x89\x00\x00\x00\x00\x00\x00\x00\x00\x01\x10\x02\x00"
"\x00\x00\x00\x00\x00\x00\x00\xcc\x0d\x00\x00\x5c\x00\x00\x00\x01\x00"
"\x00\x00\x01\x00\x00\x00\x50\x01\x01\x00\x02\x03\x00\x00\x24\x01\x01"
"\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x04\x00\x02\x80\x03\x00"
"\x03\x80\x0b\x00\x01\x00\x0c\x00\x04\x00\x00\x0e\x10\x00\x00\x00\x24"
"\x02\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x01\x80\x04\x00\x02\x80"
"\x03\x00\x03\x80\x0b\x00\x01\x00\x0c\x00\x04\x00\x00\x0e\x10\x0d\x00"
"\x00\x18\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4"
"\x61\x00\x00\x00\x04\x0d\x00\x00\x14\x40\x48\xb7\xd5\x6e\xbc\xe8\x85"
"\x25\xe7\xde\x7f\x00\xd6\xc2\xd3\x0d\x00\x00\x14\x90\xcb\x80\x91\x3e"
"\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f\x00\x00\x00\x14\x26\x24"
"\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19"
source 500
# Routing Information Protocol version 1. Special-case request for the entire
# routing table (address family 0, address 0.0.0.0, metric 16). RFC 1058,
# section 3.4.1.
udp 520
"\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x10"
# RMCP ASF ping
udp 623
"\x06\x00\xff\x06" # RMCP version 6, sequence 0xff, normal RMCP class ASF
"\x00\x00\x11\xbe" # IAN ASF code 4542
"\x80\x00\x00\x00" # payload-less ASF presence ping
# IPMI
# RMCP Get Channel Auth Capabilities
udp 623
"\x06\x00\xff\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x20\x18"
"\xc8\x81\x00\x38\x8e\x04\xb5"
# serialnumberd. This service runs on Mac OS X Server. This probe
# requests the serial number of another server. In response we expect a
# packet starting with "SNRESPS:", followed by some data whose purpose
# is not known.
udp 626 "SNQUERY: 127.0.0.1:AAAAAA:xsvr"
# OpenVPN P_CONTROL_HARD_RESET_CLIENT_V2
# Byte 0; 0x38 opcode
# Byte 1-8: Session ID, random
# Byte 9: Message packet-id array length (0)
# Byte 10-13: Message packet-id (0)
udp 1194 "8d\xc1x\x01\xb8\x9b\xcb\x8f\0\0\0\0\0"
# OpenVPN when in PKI mode and without the "HMAC Firewall" setting enabled
# (tls-auth) should respond to the following probe, which is
# 0x38<8 random bytes><4 null bytes>
udp 1194
"\x38\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00"
# Citrix MetaFrame application browser service
# Original idea from http://sh0dan.org/oldfiles/hackingcitrix.html
# Payload contents copied from Wireshark capture of Citrix Program
# Neighborhood client application. The application uses this payload to
# locate Citrix servers on the local network. Response to this probe is
# a 48 byte UDP payload as shown here:
#
# 0000 30 00 02 31 02 fd a8 e3 02 00 06 44 c0 a8 80 55
# 0010 00 00 00 00 00 00 00 00 00 00 00 00 02 00 06 44
# 0020 c0 a8 80 56 00 00 00 00 00 00 00 00 00 00 00 00
#
# The first 12 bytes appear to be the same in all responses.
#
# Bytes 0x00 appears to be a packet length field
# Bytes 0x0C - 0x0F are the IP address of the server
# Bytes 0x10 - 0x13 may vary, 0x14 - 0x1F do not appear to
# Bytes 0x20 - 0x23 are the IP address of the primary system in a server farm
# configuration
# Bytes 0x24 - 0x27 can vary, 0x28 - 0x2F do not appear to
udp 1604
"\x1e\x00\x01\x30\x02\xfd\xa8\xe3\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# RADIUS Access-Request. This is a degenerate packet with no username or
# password; we expect an Access-Reject in response. The Identifier and Request
# Authenticator are both 0. It was generated by running
# echo 'User-Password = ""' | radclient <ip> auth ""
# and then manually stripping out the password.
#
# Section 2 of the RFC says "A request from a client for which the
# RADIUS server does not have a shared secret MUST be silently
# discarded." So this payload only works when the server is configured
# (or misconfigured) to know the scanning machine as a client.
#
# RFC 2865: "The early deployment of RADIUS was done using UDP port
# number 1645, which conflicts with the "datametrics" service. The
# officially assigned port number for RADIUS is 1812.
udp 1645,1812
"\x01\x00\x00\x14"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# L2TP ICRQ
udp 1701
"\xc8\x02"
"\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x80\x08\x00\x00\x00\x00\x00"
"\x01\x80\x08\x00\x00\x00\x02\x01\x00\x80\x0e\x00\x00\x00\x07"
"nxp-scan\x80\x0a\x00\x00\x00\x03\x00\x00\x00\x03\x80"
"\x08\x00\x00\x00\x09\x00\x00"
# UPNP MSEARCH
udp 1900
"M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\n"
"Man: \"ssdp:discover\"\r\nMX: 5\r\nST: ssdp:all\r\n\r\n"
# NFS version 2, RFC 1831. XID 0x00000000, program 100003 (NFS), procedure
# NFSPROC_NULL (does nothing, see section 2.2.1), null authentication (see
# section 9.1).
udp 2049
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA3"
"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
# GPRS Tunneling Protocol (GTP)
udp 2123,2152
# GTPv1, protocol 1
"\x32"
# EchoRequest
"\x01"
# message length
"\x00\x04"
# Tunnel endpoint identifier
"\x00\x00\x42\x00"
# sequence number
"\x13\x37"
# N-PDU number
"\x00"
# next extension header type
"\x00"
# GPRS Tunneling Protocol (GTP) "prime" v2
# This same packet can be used for GTP v2 on ports 2123 and 2152 if you change
# the first byte from \x4e to \x40
udp 3386
# GTP'v2
"\x4e"
# EchoRequest
"\x01"
# message length
"\x00\x04"
# sequence number
"\xde\xfe\xc8\x00"
# Freelancer game server status query
# http://sourceforge.net/projects/gameq/
# (relevant files: games.ini, packets.ini, freelancer.php)
udp 2302 "\x00\x02\xf1\x26\x01\x26\xf0\x90\xa6\xf0\x26\x57\x4e\xac\xa0\xec\xf8\x68\xe4\x8d\x21"
# Apple Remote Desktop (ARD)
udp 3283 "\0\x14\0\x01\x03"
# STUN Binding request, see RFC 5389 Section 6
# message type = 0x001, Binding (see Section 18.1)
# message length = 0
# magic cookie = 0x2112a442
# transaction ID = "\x00"*12
udp 3478 "\x00\x01\x00\x00\x21\x12\xa4\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# Sun Service Tag Discovery protocol (stdiscover)
# http://arc.opensolaris.org/caselog/PSARC/2006/638/stdiscover_protocolv2.pdf
# Would work better with a varying cookie; the second and later sends of this
# probe will be interpreted as resends by the server and will be ignored.
udp 6481 "[PROBE] 0000"
# NAT-PMP external IP address request. See section 3.2 of
# http://files.dns-sd.org/draft-cheshire-nat-pmp.txt.
udp 5351 "\x00\x00"
# DNS Service Discovery (DNS-SD) service query, as used in Zeroconf.
# Transaction ID 0x0000, flags 0x0000, 1 question: PTR query for
# _services._dns-sd._udp.local. If the remote host supports DNS-SD it will send
# back a list of all its services. This is the same as a packet capture of
# dns-sd -B _services._dns-sd._udp .
# See section 9 of
# http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt.
# This first probe is a QU probe, meaning a unicast response is desired
udp 5353
"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x09_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0C\x80\x01"
# This second probe is a QM probe, meaning a unicast response is desired
udp 5353
"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x09_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0C\x00\x01"
# PCANY STATUS
udp 5632 "ST"
# CoAP GET .well-known/core
udp 5683 "@\x01\x01\xce\xbb.well-known\x04core"
# UT2K PING
udp 7777 "None\x00"
# Ubiquiti Discovery Service - v1
udp 10001 "\x01\x00\x00\x00"
# Amanda backup service noop request. I think that this does nothing on the
# server but only asks it to send back its feature list. In reply we expect an
# ACK or (more likely) an ERROR. I couldn't find good online documentation of
# the Amanda network protocol. There is parsing code in the Amanda source at
# common-src/security-util.c. This is based on a packet capture of
# amcheck <config> <host>
udp 10080
"Amanda 2.6 REQ HANDLE 000-00000000 SEQ 0\n"
"SERVICE noop\n"
# VxWorks Wind River Debugger
udp 17185
# Random XID
"\x00\x00\x00\x00"
# RPC version 2 procedure call
"\x00\x00\x00\x00\x00\x00\x00\x02"
# WDB version 1
"\x55\x55\x55\x55\x00\x00\x00\x01"
# WDB_TARGET_PING
"\x00\x00\x00\x00"
# RPC Auth NULL
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# Checksum
"\xff\xff\x55\x13"
# WDB wrapper (length and sequence number)
"\x00\x00\x00\x30\x00\x00\x00\x01"
# Empty data?
"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00"
# VXWORKS DEBUG (alternative?)
udp 17185
"\x72\x37\x72\x37\x00\x00\x00"
"\x00\x00\x00\x00\x02\x55\x55\x55\x55\x00\x00\x00\x01\x00\x00\x00\x01"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"
"\xff\x55\x10\x00\x00\x00\x3c\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00"
"\x00\x00\x00\x00\x00\x00"
# Quake 2 and Quake 3 game servers (and servers of derived games like Nexuiz).
# Gets game information from the server (see probe responses in
# nmap-service-probes). These services typically run on a base port or a
# few numbers higher.
# Quake 2. Typical ports: 27910-97914.
udp 27910-27914 "\xff\xff\xff\xffstatus"
# Quake 3. Typical ports:
# 26000-26004: Nexuiz
# 27960-27964: Various games
# 30720-30724: Tremulous
# 44400: Warsow
udp 26000-26004,27960-27964,30720-30724,44400 "\xff\xff\xff\xffgetstatus"
# Murmur 1.2.X (Mumble server)
# UDP ping. "abcdefgh" is an identifier. See
# http://mumble.sourceforge.net/Protocol.
udp 64738 "\x00\x00\x00\x00abcdefgh"
# Ventrilo 2.1.2+
# UDP general status request (encrypted).
# See http://aluigi.altervista.org/papers.htm#ventrilo
udp 3784
"\x01\xe7\xe5\x75\x31\xa3\x17\x0b\x21\xcf\xbf\x2b\x99\x4e\xdd\x19\xac\xde\x08\x5f\x8b\x24\x0a\x11\x19\xb6\x73\x6f\xad\x28\x13\xd2\x0a\xb9\x12\x75"
# Kademlia (kad) as used by various P2P applications. Send a Kademlia ping
# 4665, 4666, 4672, 6429: eDonkey/eMule and variants
udp 4665,4666,4672,6429 "\xE4\x60"
# TeamSpeak 2
# UDP login request
# See http://wiki.wireshark.org/TeamSpeak2
udp 8767
"\xf4\xbe\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x002x\xba\x85\tTeamSpeak\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nWindows XP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00 \x00<\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08nickname\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# TS3INIT1
udp 9987
"TS3INIT1\x00\x65\x00\x00\x88\x0a\x39\x7b\x0f\x00\x5b\x55\x72\xef\xdc\x78\x32\x6b\x00\x00\x00\x00\x00\x00\x00\x00"
# TeamSpeak 3
# UDP login request (encrypted)
# http://seclists.org/nmap-dev/2013/q3/72
udp 9987
"\x05\xca\x7f\x16\x9c\x11\xf9\x89\x00\x00\x00\x00\x02\x9d\x74\x8b\x45\xaa\x7b\xef\xb9\x9e\xfe\xad\x08\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x3e\x00\x97\x2b\x1c\x71\xb2\x4e\xc0\x61\xf1\xd7\x6f\xc5\x7e\xf6\x48\x52\xbf\x82\x6a\xa2\x3b\x65\xaa\x18\x7a\x17\x38\xc3\x81\x27\xc3\x47\xfc\xa7\x35\xba\xfc\x0f\x9d\x9d\x72\x24\x9d\xfc\x02\x17\x6d\x6b\xb1\x2d\x72\xc6\xe3\x17\x1c\x95\xd9\x69\x99\x57\xce\xdd\xdf\x05\xdc\x03\x94\x56\x04\x3a\x14\xe5\xad\x9a\x2b\x14\x30\x3a\x23\xa3\x25\xad\xe8\xe6\x39\x8a\x85\x2a\xc6\xdf\xe5\x5d\x2d\xa0\x2f\x5d\x9c\xd7\x2b\x24\xfb\xb0\x9c\xc2\xba\x89\xb4\x1b\x17\xa2\xb6"
# Memcached
# version request (shorter response than stats)
# https://github.com/memcached/memcached/blob/master/doc/protocol.txt
udp 11211
"\0\x01\0\0\0\x01\0\0version\r\n"
# Steam, typically using a port in 27015-27030. Send a "Source Engine query"
udp 27015-27030
"\xff\xff\xff\xffTSource Engine Query\x00"
# TRIN00 UNIX PING
udp 27444 "png l44adsl"
# BO PING
udp 31337
"\xce\x63\xd1\xd2\x16\xe7\x13\xcf\x38"
"\xa5\xa5\x86\xb2\x75\x4b\x99\xaa\x32\x58"
# TRIN00 WIN PING
udp 34555 "png []..Ks"
# Beckhoff ADS discovery request
# https://github.com/ONE75/adsclient/blob/master/src/AdsClient.Finder/DeviceFinder.cs#L49-L64
udp 48899
"\x03\x66\x14\x71\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01\x10\x27\x00\x00\x00\x00"

View File

@ -0,0 +1,225 @@
import ipaddress
import overseer
from threading import Thread
from io import open
import socket
import os
import re
import time
class ScanManager:
def __init__(self):
self.pending_shutdown = False
self.active_scans = []
self.broadcast_thread = Thread(target=self.__broadcast_thread)
self.broadcast_thread.start()
def __broadcast_thread(self):
while not self.pending_shutdown:
time.sleep(5)
if len(self.active_scans) == 0:
continue
for scan in self.active_scans:
# WebSocket progress
total_progress = (scan.tcp_progress + scan.udp_progress) / 2
overseer.api.send_websocket_event(
{
"id": scan.history_id,
"target": scan.target,
"status": "RUNNING",
"tcp_progress": scan.tcp_progress,
"udp_progress": scan.udp_progress,
"total_progress": round(total_progress),
}
)
if scan.tcp_progress + scan.udp_progress != 200:
continue
# Combine ports
results = list(map(lambda x: "%s UDP" % x, scan.udp_results))
results.extend(
list(map(lambda x: "%s TCP" % x, scan.tcp_results))
) # noqa: E501
results.sort()
# Update database
overseer.database.update_scan_result(
scan.history_id, "COMPLETE", results=results
)
# WebSocket completion
overseer.api.send_websocket_event(
{
"id": scan.history_id,
"target": scan.target,
"status": "COMPLETE",
"results": results,
}
)
# Cleanup active scan
scan.join()
self.active_scans.remove(scan)
def shutdown(self):
self.pending_shutdown = True
self.broadcast_thread.join()
def get_status(self):
return list(
map(
lambda x: {
"id": x.history_id,
"target": x.target,
"status": "IN_PROGRESS",
"tcp_progress": x.tcp_progress,
"udp_progress": x.udp_progress,
"total_progress": round(
(x.tcp_progress + x.udp_progress) / 2
), # noqa: E501
},
self.active_scans,
)
)
def perform_scan(self, target):
try:
target = socket.gethostbyname(target)
except socket.error:
return None
if self.is_ip(target):
scan_history = overseer.database.create_scan_result(
"IN_PROGRESS", ip_addr=target
)
else:
scan_history = overseer.database.create_scan_result(
"IN_PROGRESS", hostname=target
)
new_scan = Scanner(target, scan_history.id)
new_scan.start()
self.active_scans.append(new_scan)
return scan_history.id
def is_ip(self, target):
try:
ipaddress.ip_address(target)
return True
except ValueError:
return False
class Scanner(Thread):
def __init__(self, target, history_id):
Thread.__init__(self)
self.target = target
self.history_id = history_id
self.port_count = 1000
self.tcp_progress = 0
self.udp_progress = 0
self.tcp_results = []
self.udp_results = []
self.udp_payloads = {}
self.__load_nmap_payloads()
def __load_nmap_payloads(self):
"""Load and parse nmap UDP payloads"""
# Open file & remove comments
nmap_payloads = os.path.join(
os.path.dirname(__file__), "./resources/nmap-payloads"
)
f = open(nmap_payloads, "r", encoding="unicode_escape")
raw_file = re.sub(
r"^(#|\s*#).*$", "", f.read(), flags=re.MULTILINE | re.UNICODE
)
f.close()
# Find all matches
results = re.findall(
r"(^udp.*?)(?=udp|\Z)",
raw_file,
flags=re.MULTILINE | re.DOTALL | re.UNICODE,
)
for raw_match in results:
match = raw_match.strip()
match_payloads = list(
map(lambda x: x.strip(), re.findall(r'\"(.*)"', match))
)
raw_ports = re.match(r"^udp\s([\d,-]*)", match).group(1)
for raw_port in raw_ports.split(","):
if "-" in raw_port:
port_range = raw_port.split("-")
start_port = int(port_range[0])
end_port = int(port_range[1])
for port_match in range(start_port, end_port + 1):
if port_match not in self.udp_payloads:
self.udp_payloads[port_match] = []
self.udp_payloads[port_match].extend(match_payloads)
else:
port_match = int(raw_port)
if port_match not in self.udp_payloads:
self.udp_payloads[port_match] = []
self.udp_payloads[port_match].extend(match_payloads)
def run(self):
tcp_thread = Thread(target=self.__scan_tcp)
udp_thread = Thread(target=self.__scan_udp)
tcp_thread.start()
udp_thread.start()
tcp_thread.join()
udp_thread.join()
return {"TCP": self.tcp_results, "UDP": self.udp_results}
def __scan_tcp(self):
for port in range(1, self.port_count):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.1)
result = s.connect_ex((self.target, port))
if result == 0:
self.tcp_results.append(port)
s.close()
self.tcp_progress = round(port / self.port_count * 100)
def __scan_udp(self):
for port in range(1, self.port_count):
# print("UDP port %s..." % port)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(0.01)
payloads = ["\x00"]
if port in self.udp_payloads:
payloads = self.udp_payloads[port]
for payload in payloads:
s.sendto(payload.encode("utf-8"), (self.target, port))
try:
s.recvfrom(1)
self.udp_results.append(port)
break
except ConnectionRefusedError:
pass
except socket.timeout:
pass
s.close()
self.udp_progress = round(port / self.port_count * 100)
# FOR TESTING PURPOSES
def main():
sm = ScanManager()
sm.perform_scan("localhost")
# sm.perform_scan("10.0.20.254")
# sm.perform_scan("10.0.21.20")
if __name__ == "__main__":
main()

View File

@ -0,0 +1 @@
#overseer-body[data-v-dc8467c2]{background-color:#ff0;width:100%;height:100%}#center[data-v-dc8467c2]{margin:0 auto;width:800px;height:100%;background-color:purple}#overseer-search[data-v-dc8467c2]{width:400px;border-radius:5px;height:40px;margin-top:300px;font-size:1rem;padding:.3rem .8rem;text-indent:0;outline:none;border:0 solid}#overseer-header[data-v-182df07c]{background-color:green;width:100%;height:60px}#overseer-notifications[data-v-5c26d9a3]{height:100%;width:320px;padding:10px;float:right;background-color:#00f}.overseer-notification[data-v-5c26d9a3]{width:300px;height:65px;background-color:green;border-radius:5px;border:1px solid #000;text-align:start;padding:10px}#overseer-app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;height:100%}body,html{height:100%;width:100%;margin:0}

View File

@ -1 +0,0 @@
h3[data-v-b9167eee]{margin:40px 0 0}ul[data-v-b9167eee]{list-style-type:none;padding:0}li[data-v-b9167eee]{display:inline-block;margin:0 10px}a[data-v-b9167eee]{color:#42b983}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;margin-top:60px}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,2 +0,0 @@
(function(e){function t(t){for(var n,a,u=t[0],s=t[1],i=t[2],p=0,v=[];p<u.length;p++)a=u[p],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&v.push(o[a][0]),o[a]=0;for(n in s)Object.prototype.hasOwnProperty.call(s,n)&&(e[n]=s[n]);c&&c(t);while(v.length)v.shift()();return l.push.apply(l,i||[]),r()}function r(){for(var e,t=0;t<l.length;t++){for(var r=l[t],n=!0,u=1;u<r.length;u++){var s=r[u];0!==o[s]&&(n=!1)}n&&(l.splice(t--,1),e=a(a.s=r[0]))}return e}var n={},o={app:0},l=[];function a(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,a),r.l=!0,r.exports}a.m=e,a.c=n,a.d=function(e,t,r){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(a.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)a.d(r,n,function(t){return e[t]}.bind(null,n));return r},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="/static/";var u=window["webpackJsonp"]=window["webpackJsonp"]||[],s=u.push.bind(u);u.push=t,u=u.slice();for(var i=0;i<u.length;i++)t(u[i]);var c=s;l.push([0,"chunk-vendors"]),r()})({0:function(e,t,r){e.exports=r("56d7")},"034f":function(e,t,r){"use strict";r("85ec")},4805:function(e,t,r){"use strict";r("8ce0")},"56d7":function(e,t,r){"use strict";r.r(t);r("e260"),r("e6cf"),r("cca6"),r("a79d");var n=r("2b0e"),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"app"}},[n("img",{attrs:{alt:"Vue logo",src:r("cf05")}}),n("HelloWorld",{attrs:{msg:"Welcome to Your Vue.js App"}})],1)},l=[],a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"hello"},[r("h1",[e._v(e._s(e.msg))]),e._m(0),r("h3",[e._v("Installed CLI Plugins")]),e._m(1),r("h3",[e._v("Essential Links")]),e._m(2),r("h3",[e._v("Ecosystem")]),e._m(3)])},u=[function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("p",[e._v(" For a guide and recipes on how to configure / customize this project,"),r("br"),e._v(" check out the "),r("a",{attrs:{href:"https://cli.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("vue-cli documentation")]),e._v(". ")])},function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("ul",[r("li",[r("a",{attrs:{href:"https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel",target:"_blank",rel:"noopener"}},[e._v("babel")])]),r("li",[r("a",{attrs:{href:"https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint",target:"_blank",rel:"noopener"}},[e._v("eslint")])])])},function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("ul",[r("li",[r("a",{attrs:{href:"https://vuejs.org",target:"_blank",rel:"noopener"}},[e._v("Core Docs")])]),r("li",[r("a",{attrs:{href:"https://forum.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("Forum")])]),r("li",[r("a",{attrs:{href:"https://chat.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("Community Chat")])]),r("li",[r("a",{attrs:{href:"https://twitter.com/vuejs",target:"_blank",rel:"noopener"}},[e._v("Twitter")])]),r("li",[r("a",{attrs:{href:"https://news.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("News")])])])},function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("ul",[r("li",[r("a",{attrs:{href:"https://router.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("vue-router")])]),r("li",[r("a",{attrs:{href:"https://vuex.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("vuex")])]),r("li",[r("a",{attrs:{href:"https://github.com/vuejs/vue-devtools#vue-devtools",target:"_blank",rel:"noopener"}},[e._v("vue-devtools")])]),r("li",[r("a",{attrs:{href:"https://vue-loader.vuejs.org",target:"_blank",rel:"noopener"}},[e._v("vue-loader")])]),r("li",[r("a",{attrs:{href:"https://github.com/vuejs/awesome-vue",target:"_blank",rel:"noopener"}},[e._v("awesome-vue")])])])}],s={name:"HelloWorld",props:{msg:String}},i=s,c=(r("4805"),r("2877")),p=Object(c["a"])(i,a,u,!1,null,"b9167eee",null),v=p.exports,f={name:"App",components:{HelloWorld:v}},h=f,_=(r("034f"),Object(c["a"])(h,o,l,!1,null,null,null)),g=_.exports;n["a"].config.productionTip=!1,new n["a"]({render:function(e){return e(g)}}).$mount("#app")},"85ec":function(e,t,r){},"8ce0":function(e,t,r){},cf05:function(e,t,r){e.exports=r.p+"img/logo.82b9c7a5.png"}});
//# sourceMappingURL=app.124cfaf1.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(function(e){function t(t){for(var r,c,s=t[0],a=t[1],u=t[2],l=0,p=[];l<s.length;l++)c=s[l],Object.prototype.hasOwnProperty.call(o,c)&&o[c]&&p.push(o[c][0]),o[c]=0;for(r in a)Object.prototype.hasOwnProperty.call(a,r)&&(e[r]=a[r]);f&&f(t);while(p.length)p.shift()();return i.push.apply(i,u||[]),n()}function n(){for(var e,t=0;t<i.length;t++){for(var n=i[t],r=!0,s=1;s<n.length;s++){var a=n[s];0!==o[a]&&(r=!1)}r&&(i.splice(t--,1),e=c(c.s=n[0]))}return e}var r={},o={app:0},i=[];function c(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,c),n.l=!0,n.exports}c.m=e,c.c=r,c.d=function(e,t,n){c.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},c.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,t){if(1&t&&(e=c(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(c.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)c.d(n,r,function(t){return e[t]}.bind(null,r));return n},c.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return c.d(t,"a",t),t},c.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},c.p="/static/";var s=window["webpackJsonp"]=window["webpackJsonp"]||[],a=s.push.bind(s);s.push=t,s=s.slice();for(var u=0;u<s.length;u++)t(s[u]);var f=a;i.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("56d7")},"034f":function(e,t,n){"use strict";n("85ec")},"3b75":function(e,t,n){},"56d7":function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("2b0e"),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"overseer-app"}},[n("OverseerHeader"),n("OverseerNotifications"),n("OverseerHome")],1)},i=[],c=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"overseer-body"}},[n("div",{attrs:{id:"center"}},[n("input",{attrs:{id:"overseer-search",placeholder:"IP / Hostname",type:"text"}})])])}],a={name:"OverseerHome"},u=a,f=(n("c931"),n("2877")),l=Object(f["a"])(u,c,s,!1,null,"dc8467c2",null),p=l.exports,d=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"overseer-header"}})},v=[],b={name:"OverseerHeader"},_=b,O=(n("8033"),Object(f["a"])(_,d,v,!1,null,"182df07c",null)),h=O.exports,m=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"overseer-notifications"}},e._l(e.items,(function(t){return n("div",{key:t.id,staticClass:"overseer-notification"},[n("b",[e._v("Target: ")]),e._v(" "+e._s(t.target)+" "),n("br"),n("b",[e._v("Status: ")]),e._v(e._s(t.status)+" "),n("br"),"total_progress"in t?n("span",[n("b",[e._v("Progress: ")]),e._v(e._s(t.total_progress)+" "),n("br")]):e._e()])})),0)},g=[],y={name:"OverseerNotifications",computed:{items:function(){return this.$store.state.notifications}}},w=y,j=(n("d09c"),Object(f["a"])(w,m,g,!1,null,"5c26d9a3",null)),x=j.exports,E={name:"App",components:{OverseerHome:p,OverseerHeader:h,OverseerNotifications:x}},S=E,P=(n("034f"),Object(f["a"])(S,o,i,!1,null,null,null)),T=P.exports,C=(n("7db0"),n("159b"),n("b64b"),n("2f62"));r["a"].use(C["a"]);var H=new C["a"].Store({state:{ws_connected:!1,notifications:[]},mutations:{SOCKET_connect:function(e,t){e.ws_connected=!0,console.log("CONNECT: ",e,t)},SOCKET_disconnect:function(e,t){e.ws_connected=!1,console.log("DISCONNECT: ",e,t)},SOCKET_message:function(e,t){var n=e.notifications.find((function(e){return e.id==t.id}));n?Object.keys(t).forEach((function(e){r["a"].set(n,e,t[e])})):e.notifications.push(t)}},actions:{}}),N=n("8e27"),$=n.n(N),k=n("5132"),K=n.n(k);r["a"].use(new K.a({debug:!0,connection:$()({path:"/api/v1/socket.io"}),vuex:{store:H,actionPrefix:"SOCKET_",mutationPrefix:"SOCKET_"}})),r["a"].config.productionTip=!1,console.log(H),new r["a"]({render:function(e){return e(T)},store:H}).$mount("#app")},8033:function(e,t,n){"use strict";n("3b75")},"85ec":function(e,t,n){},a2a5:function(e,t,n){},c931:function(e,t,n){"use strict";n("a2a5")},d09c:function(e,t,n){"use strict";n("e6eb")},e6eb:function(e,t,n){}});
//# sourceMappingURL=app.77b1e8f6.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/static/favicon.ico"><title>overseer_client</title><link href="/static/css/app.fb0c6e1c.css" rel="preload" as="style"><link href="/static/js/app.124cfaf1.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.983c3185.js" rel="preload" as="script"><link href="/static/css/app.fb0c6e1c.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but overseer_client doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.983c3185.js"></script><script src="/static/js/app.124cfaf1.js"></script></body></html>
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/static/favicon.ico"><title>overseer_client</title><link href="/static/css/app.4d1483d7.css" rel="preload" as="style"><link href="/static/js/app.77b1e8f6.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.6130e7bc.js" rel="preload" as="script"><link href="/static/css/app.4d1483d7.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but overseer_client doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.6130e7bc.js"></script><script src="/static/js/app.77b1e8f6.js"></script></body></html>

View File

@ -1,15 +0,0 @@
<html>
<head>
<title>Overseer - Port Scanner</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.min.js" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io({ path: "/api/v1/socket.io" });
socket.on('connect', function() {
socket.emit('json', {data: 'I\'m connected!'});
});
</script>
</head>
<body>
<p>This is a test</p>
</body>
</html>

View File

@ -9,7 +9,11 @@
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^2.6.11"
"socket.io-client": "^4.0.0",
"vue": "^2.6.11",
"vue-router": "^3.5.1",
"vue-socket.io": "^3.0.10",
"vuex": "^3.6.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",

View File

@ -1,28 +1,39 @@
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
<div id="overseer-app">
<OverseerHeader/>
<OverseerNotifications/>
<OverseerHome/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import OverseerHome from './components/OverseerHome.vue'
import OverseerHeader from './components/OverseerHeader.vue'
import OverseerNotifications from './components/OverseerNotifications.vue'
export default {
name: 'App',
components: {
HelloWorld
OverseerHome,
OverseerHeader,
OverseerNotifications
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
#overseer-app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
height: 100%;
}
html, body {
height: 100%;
width: 100%;
margin: 0px;
}
</style>

View File

@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,18 @@
<template>
<div id="overseer-header">
</div>
</template>
<script>
export default {
name: 'OverseerHeader'
}
</script>
<style scoped>
#overseer-header {
background-color: green;
width: 100%;
height: 60px;
}
</style>

View File

@ -0,0 +1,38 @@
<template>
<div id="overseer-body">
<div id="center">
<input id="overseer-search" placeholder="IP / Hostname" type="text">
</div>
</div>
</template>
<script>
export default {
name: 'OverseerHome'
}
</script>
<style scoped>
#overseer-body {
background-color: yellow;
width: 100%;
height: 100%;
}
#center {
margin: 0px auto;
width: 800px;
height: 100%;
background-color: purple;
}
#overseer-search {
width: 400px;
border-radius: 5px;
height: 40px;
margin-top: 300px;
font-size: 1rem;
padding: .3rem .8rem;
text-indent: 0px;
outline: none;
border: 0px solid;
}
</style>

View File

@ -0,0 +1,43 @@
<template>
<div id="overseer-notifications">
<div class="overseer-notification" v-for="item in items" :key="item.id">
<b>Target: </b> {{ item.target }} <br>
<b>Status: </b>{{ item.status }} <br>
<span v-if="'total_progress' in item">
<b>Progress: </b>{{item.total_progress}} <br>
</span>
</div>
</div>
</template>
<script>
export default {
name: 'OverseerNotifications',
computed: {
items() {
return this.$store.state.notifications
}
}
}
</script>
<style scoped>
#overseer-notifications {
height: 100%;
width: 320px;
padding: 10px;
float: right;
background-color: blue;
}
.overseer-notification {
width: 300px;
height: 65px;
background-color: green;
border-radius: 5px;
border: 1px solid black;
text-align: start;
padding: 10px;
margin: 3px 0px;
}
</style>

View File

@ -1,8 +1,27 @@
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import router from './router'
import socketio from 'socket.io-client';
import VueRouter from 'vue-router'
import VueSocketIO from 'vue-socket.io'
Vue.use(new VueSocketIO({
debug: true,
connection: socketio({ path: "/api/v1/socket.io" }),
vuex: {
store,
actionPrefix: 'SOCKET_',
mutationPrefix: 'SOCKET_'
},
}))
Vue.config.productionTip = false
console.log(store)
new Vue({
render: h => h(App),
render: h => h(App),
router,
store,
}).$mount('#app')

View File

@ -0,0 +1,34 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
ws_connected: false,
notifications: []
},
mutations: {
"SOCKET_connect"(state, status) {
state.ws_connected = true
console.log("CONNECT: ", state, status);
},
"SOCKET_disconnect"(state, status) {
state.ws_connected = false
console.log("DISCONNECT: ", state, status);
},
"SOCKET_message"(state, message) {
let matchedItem = state.notifications.find(item => item.id == message.id);
if (matchedItem){
Object.keys(message).forEach(key => {
// matchedItem[key] = message[key]
Vue.set(matchedItem, key, message[key])
});
} else {
state.notifications.push(message);
}
}
},
actions: {
}
})

View File

@ -1,5 +1,5 @@
module.exports = {
publicPath: "/static/",
outputDir: "../overseer/static/",
indexPath: "../templates/index2.html"
indexPath: "../templates/index.html"
}

View File

@ -941,6 +941,11 @@
"@types/connect" "*"
"@types/node" "*"
"@types/component-emitter@^1.2.10":
version "1.2.10"
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea"
integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==
"@types/connect-history-api-fallback@*":
version "1.3.4"
resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.4.tgz#8c0f0e6e5d8252b699f5a662f51bdf82fd9d8bb8"
@ -1551,6 +1556,11 @@ address@^1.1.2:
resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==
after@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
aggregate-error@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
@ -1715,6 +1725,11 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
arraybuffer.slice@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
asn1.js@^5.2.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
@ -1858,11 +1873,21 @@ babel-plugin-polyfill-regenerator@^0.1.2:
dependencies:
"@babel/helper-define-polyfill-provider" "^0.1.5"
backo2@1.0.2, backo2@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base64-arraybuffer@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812"
integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=
base64-js@^1.0.2:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@ -1930,6 +1955,11 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
blob@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
bluebird@^3.1.1, bluebird@^3.5.5:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@ -2556,11 +2586,21 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
component-emitter@^1.2.1:
component-bind@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=
component-emitter@^1.2.1, component-emitter@~1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
component-inherit@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
compressible@~2.0.16:
version "2.0.18"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
@ -2966,13 +3006,20 @@ debug@^3.1.1, debug@^3.2.6:
dependencies:
ms "^2.1.1"
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
debug@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
@ -3290,6 +3337,56 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
engine.io-client@~3.5.0:
version "3.5.1"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.5.1.tgz#b500458a39c0cd197a921e0e759721a746d0bdb9"
integrity sha512-oVu9kBkGbcggulyVF0kz6BV3ganqUeqXvD79WOFKa+11oK692w1NyFkuEj4xrkFRpZhn92QOqTk4RQq5LiBXbQ==
dependencies:
component-emitter "~1.3.0"
component-inherit "0.0.3"
debug "~3.1.0"
engine.io-parser "~2.2.0"
has-cors "1.1.0"
indexof "0.0.1"
parseqs "0.0.6"
parseuri "0.0.6"
ws "~7.4.2"
xmlhttprequest-ssl "~1.5.4"
yeast "0.1.2"
engine.io-client@~5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-5.0.0.tgz#65733887c8999d280e1dd7f241779a2c66e9559e"
integrity sha512-e6GK0Fqvq45Nu/j7YdIVqXtDPvlsggAcfml3QiEiGdJ1qeh7IQU6knxSN3+yy9BmbnXtIfjo1hK4MFyHKdc9mQ==
dependencies:
base64-arraybuffer "0.1.4"
component-emitter "~1.3.0"
debug "~4.3.1"
engine.io-parser "~4.0.1"
has-cors "1.1.0"
parseqs "0.0.6"
parseuri "0.0.6"
ws "~7.4.2"
yeast "0.1.2"
engine.io-parser@~2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7"
integrity sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==
dependencies:
after "0.8.2"
arraybuffer.slice "~0.0.7"
base64-arraybuffer "0.1.4"
blob "0.0.5"
has-binary2 "~1.0.2"
engine.io-parser@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-4.0.2.tgz#e41d0b3fb66f7bf4a3671d2038a154024edb501e"
integrity sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==
dependencies:
base64-arraybuffer "0.1.4"
enhanced-resolve@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
@ -4132,6 +4229,18 @@ has-bigints@^1.0.0:
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
has-binary2@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d"
integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==
dependencies:
isarray "2.0.1"
has-cors@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@ -4502,6 +4611,11 @@ indexes-of@^1.0.1:
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
indexof@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=
infer-owner@^1.0.3, infer-owner@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
@ -4890,6 +5004,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isarray@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -6014,6 +6133,16 @@ parse5@^6.0.1:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
parseqs@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5"
integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==
parseuri@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a"
integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@ -7245,6 +7374,54 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
socket.io-client@^2.1.1:
version "2.4.0"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.4.0.tgz#aafb5d594a3c55a34355562fc8aea22ed9119a35"
integrity sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==
dependencies:
backo2 "1.0.2"
component-bind "1.0.0"
component-emitter "~1.3.0"
debug "~3.1.0"
engine.io-client "~3.5.0"
has-binary2 "~1.0.2"
indexof "0.0.1"
parseqs "0.0.6"
parseuri "0.0.6"
socket.io-parser "~3.3.0"
to-array "0.1.4"
socket.io-client@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.0.0.tgz#643cc25e5b5bbe37be75ecd317156a3335bb495a"
integrity sha512-27yQxmXJAEYF19Ygyl8FPJ0if0wegpSmkIIbrWJeI7n7ST1JyH8bbD5v3fjjGY5cfCanACJ3dARUAyiVFNrlTQ==
dependencies:
"@types/component-emitter" "^1.2.10"
backo2 "~1.0.2"
component-emitter "~1.3.0"
debug "~4.3.1"
engine.io-client "~5.0.0"
parseuri "0.0.6"
socket.io-parser "~4.0.4"
socket.io-parser@~3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6"
integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==
dependencies:
component-emitter "~1.3.0"
debug "~3.1.0"
isarray "2.0.1"
socket.io-parser@~4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0"
integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==
dependencies:
"@types/component-emitter" "^1.2.10"
component-emitter "~1.3.0"
debug "~4.3.1"
sockjs-client@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add"
@ -7745,6 +7922,11 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
to-arraybuffer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@ -8148,6 +8330,18 @@ vue-loader@^15.9.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-router@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.1.tgz#edf3cf4907952d1e0583e079237220c5ff6eb6c9"
integrity sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw==
vue-socket.io@^3.0.10:
version "3.0.10"
resolved "https://registry.yarnpkg.com/vue-socket.io/-/vue-socket.io-3.0.10.tgz#76135bf5043baf484c648636a7a9822b4c11c084"
integrity sha512-XGYjD30Q9xAeHpBnp2SU+ljEe59qpGKaAQe4VOO9ezuly09MlzrT2ZZPJu3BVFpQwKdjQDz1I2fV9r4YjlZDCA==
dependencies:
socket.io-client "^2.1.1"
vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
version "4.1.3"
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35"
@ -8174,6 +8368,11 @@ vue@^2.6.11:
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==
vuex@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
watchpack-chokidar2@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957"
@ -8439,6 +8638,16 @@ ws@^6.0.0, ws@^6.2.1:
dependencies:
async-limiter "~1.0.0"
ws@~7.4.2:
version "7.4.4"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
xmlhttprequest-ssl@~1.5.4:
version "1.5.5"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@ -8511,6 +8720,11 @@ yargs@^16.0.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
yorkie@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/yorkie/-/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9"

View File

@ -0,0 +1,19 @@
import pytest
import ipaddress
from overseer.database import DatabaseConnector
def test_create_scan_target():
db = DatabaseConnector(None, True)
hostname = db.create_scan_target(hostname="google.com")
ip_address = db.create_scan_target(ip_addr="1.1.1.1")
assert hostname.id == 1
assert hostname.hostname == "google.com"
assert ip_address.id == 2
assert ip_address.ip == int(ipaddress.ip_address("1.1.1.1"))
# def test_get_scan_target():
# def test_get_all_scan_target():
# def test_create_scan_result():
# def test_update_scan_result():
# def test_get_scan_results_by_target():