mirror of
https://github.com/ChronosX88/PyNesca.git
synced 2024-11-22 13:12:18 +00:00
95 lines
3.4 KiB
Python
95 lines
3.4 KiB
Python
import ipaddress
|
|
from core.prototypes.AbstractParser import AbstractParser
|
|
from core.prototypes.AbstractModuleClass import internal
|
|
|
|
|
|
class Parser(AbstractParser):
|
|
|
|
def parse_fields(self, ports:'port_field', ips:'address_field') -> {'ipv4_objects',
|
|
'ports'}:
|
|
result = dict()
|
|
result['ports'] = self.parse_port_field(ports)
|
|
result['ipv4_ranges'] = self.get_all_addresses(ips)
|
|
return result
|
|
|
|
@internal
|
|
def parse_port_field(self, ports):
|
|
"""
|
|
Parses ports from string, returns them as integers in the list.
|
|
Handles non-existent ports and non-port values.
|
|
"""
|
|
if ports:
|
|
# Using set to avoid repetitions
|
|
parsed = set()
|
|
ports = ports.split(",")
|
|
for port in ports:
|
|
try:
|
|
# Input is in range form ("100-200"):
|
|
if '-' in port:
|
|
start, end = map(int, port.split('-'))
|
|
parsed.update(
|
|
[p for p in range(start, end + 1) if 65355 >= p > 0])
|
|
# Input is a single port ("80"):
|
|
else:
|
|
parsed.add(int(port))
|
|
except ValueError as e:
|
|
# If we get any not integer just ignore it
|
|
pass
|
|
return sorted(list(parsed))
|
|
else:
|
|
# Change to default ports from constant
|
|
return [21, 22, 23, 25, 80, 443, 110, 111, 135, 139, 445, 8080, 8443, 53, 143, 989, 990, 3306, 1080, 5554, 6667, 2222, 4444, 666, 6666, 1337, 2020, 31337]
|
|
|
|
@internal
|
|
def parse_address_field(self, ips):
|
|
"""
|
|
Parses ip input string, returns the generator over them.
|
|
|
|
Supports next inputs:
|
|
1) 1.2.3.4
|
|
2) 192.168.0.0/24
|
|
3) 1.2.3.4 - 5.6.7.8
|
|
Any non-ip value will be ignored.
|
|
"""
|
|
|
|
# A set to contain non repeating ip objects from ipaddress
|
|
for ip_obj in self.get_all_addresses():
|
|
# The object is just one ip, simply yield it:
|
|
if isinstance(ip_obj, ipaddress.IPv4Address):
|
|
yield ip_obj
|
|
# The object is a network, yield every host in it:
|
|
else:
|
|
for host in ip_obj:
|
|
yield host
|
|
|
|
@internal
|
|
def get_all_addresses(self, ips):
|
|
ip_objects = set()
|
|
inputs = [ip.strip() for ip in ips.split(',')]
|
|
|
|
for input_ in inputs:
|
|
try:
|
|
# Input is in range form ("1.2.3.4 - 5.6.7.8"):
|
|
if '-' in input_:
|
|
input_ips = input_.split('-')
|
|
ranges = set(
|
|
ipaddress.summarize_address_range(
|
|
*map(lambda x: ipaddress.IPv4Address(x.strip()), input_ips)
|
|
)
|
|
)
|
|
ip_objects.update(ranges)
|
|
# Input is in CIDR form ("192.168.0.0/24"):
|
|
elif '/' in input_:
|
|
network = ipaddress.ip_network(input_)
|
|
ip_objects.add(network)
|
|
# Input is a single ip ("1.1.1.1"):
|
|
else:
|
|
ip = ipaddress.ip_address(input_)
|
|
ip_objects.add(ip)
|
|
except ValueError as e:
|
|
print(e)
|
|
# If we get any non-ip value just ignore it
|
|
pass
|
|
ip_objects = list(ip_objects)
|
|
return ip_objects
|