-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
centralizing parsing of nmap results
- Loading branch information
Showing
14 changed files
with
235 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from typing import List | ||
|
||
from loguru import logger | ||
from backend.models import Address, Host, Profile, ScanEvent | ||
|
||
|
||
class NMapParserService(object): | ||
""" | ||
An attempt at a service that can centralize nmap parsing, so ONE `ScanEvent` can be created from the scan results. | ||
""" | ||
|
||
def __init__(self, scan_results: dict = None, profile: Profile = None): | ||
self.scan_results = scan_results | ||
self.profile = profile | ||
|
||
def build_scan_event_from_results(self) -> ScanEvent: | ||
|
||
scan_event = ScanEvent() | ||
scan_event.profile_id = self.profile.profile_id | ||
scan_event.profile = self.profile | ||
scan_event.scan_command = self.scan_results["nmaprun"]["@args"] | ||
scan_event.scan_start = self.scan_results["nmaprun"]["@start"] | ||
scan_event.scan_end = self.scan_results["nmaprun"]["runstats"]["finished"]["@time"] | ||
scan_event.scan_status = self.scan_results["nmaprun"]["runstats"]["finished"]["@exit"] | ||
|
||
hosts: List[Host] = [] | ||
host_list = self.scan_results["nmaprun"]["host"] | ||
for host in host_list: | ||
try: | ||
host_obj = Host() | ||
host_obj.start_time = host.get("@starttime", None) | ||
host_obj.end_time = host.get("@endtime", None) | ||
host_status = host.get("status", "UNKNOWN") | ||
if host_status: | ||
host_obj.state = host_status.get("@state", None) | ||
host_obj.reason = host_status.get("@reason", None) | ||
|
||
address = host["address"] | ||
if address: | ||
if isinstance(address, dict): | ||
host_address = Address() | ||
host_address.address_type = address.get("@addrtype", None) | ||
host_address.address = address["@addr"] | ||
host_address.vendor = address.get("@vendor", None) | ||
host_obj.addresses.append(host_address) | ||
elif isinstance(address, list): | ||
for addr in address: | ||
host_address = Address() | ||
host_address.address_type = addr.get("@addrtype", None) | ||
host_address.address = addr["@addr"] | ||
host_address.vendor = addr.get("@vendor", None) | ||
host_obj.addresses.append(host_address) | ||
hosts.append(host_obj) | ||
except Exception as e: | ||
logger.error(f"Error parsing host for profile {self.profile.profile_id}: {e}") | ||
|
||
scan_event.hosts = hosts | ||
|
||
return scan_event |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
from datetime import datetime | ||
from loguru import logger | ||
from backend import models | ||
from sqlalchemy.orm import Session | ||
|
||
from backend.service.nmap import NmapScanner | ||
from backend.service.nmap_parser import NMapParserService | ||
|
||
|
||
class ProfileScanService(object): | ||
""" | ||
This class is responsible for scanning a profile. It will leverage the nmap service for a multi-step scan and interact with the database to store the results. | ||
""" | ||
|
||
def __init__(self, profile_id: str = None, db: Session = None): | ||
self.profile_id = profile_id | ||
self.db = db | ||
|
||
def get_profile(self): | ||
profile = self.db.query(models.Profile).filter(models.Profile.profile_id == self.profile_id).first() | ||
if not profile: | ||
logger.error("Profile not found.") | ||
return None | ||
|
||
self.profile = profile | ||
return profile | ||
|
||
def scan_profile(self): | ||
""" | ||
This has to be done as a two-part scan. First we will scan using a ping scan to get the IP addresses of hosts that are "up" | ||
and then we will scan the IP addresses using "detailed" mode. | ||
""" | ||
|
||
profile = self.get_profile() | ||
nmap_scanner = NmapScanner() | ||
|
||
scan_results = {} | ||
try: | ||
ping_results = nmap_scanner.scan( | ||
profile.ip_range, "ping" | ||
) # TODO: make this configurable, because not all networks will need a two-step scan | ||
up_hosts = [] | ||
if ping_results: | ||
|
||
nmap_hosts = ping_results["nmaprun"]["host"] | ||
for host in nmap_hosts: | ||
if host["status"]["@state"] == "up": | ||
address = host["address"] # address can be a dict or a list | ||
if isinstance(address, dict): | ||
if address["@addrtype"] == "ipv4": # TODO: handle ipv6 | ||
up_hosts.append(host["address"]["@addr"]) | ||
elif isinstance(address, list): | ||
for addr in address: | ||
if addr["@addrtype"] == "ipv4": | ||
up_hosts.append(addr["@addr"]) | ||
|
||
logger.info(f"Hosts that are up: {up_hosts}") | ||
if len(up_hosts) > 0: | ||
concat_ips: str = " ".join(up_hosts) | ||
scan_results = nmap_scanner.scan(concat_ips, "detailed") | ||
if scan_results and "nmaprun" in scan_results: | ||
|
||
nmap_parser = NMapParserService(scan_results, profile) | ||
|
||
scan_event = nmap_parser.build_scan_event_from_results() | ||
profile.scan_events.append(scan_event) | ||
profile.last_scan = datetime.now() | ||
self.db.add(profile) | ||
self.db.commit() | ||
|
||
except Exception as e: | ||
logger.error(f"Error scanning profile {self.profile_id}: {e}") | ||
return | ||
|
||
# now let's scan the IP addresses that are "up" | ||
|
||
return profile | ||
|
||
def __process_scan_results(self, scan_results: dict) -> models.Profile: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
version: "3.7" | ||
|
||
services: | ||
backend: | ||
build: | ||
|
Oops, something went wrong.