Compare commits

..

4 Commits

Author SHA1 Message Date
Daniel Sagi
b6fe065dae added windows support using a powershell snippet for interface enum 2022-08-25 21:15:32 +03:00
Daniel Sagi
ad9956e18c fixed bug in subnets appending 2022-08-25 20:05:32 +03:00
Daniel Sagi
7f98e384a5 added pyroute2 as a dependency 2022-08-25 19:30:14 +03:00
Daniel Sagi
0a1e61fd8b changed to using pyroute2 instead of manually parsing /proc/net/route and instead of psutil for interface enum 2022-08-25 19:29:46 +03:00
3 changed files with 69 additions and 29 deletions

View File

@@ -1,6 +1,5 @@
FROM python:3.8-alpine as builder
RUN apk update
RUN apk add --no-cache \
linux-headers \
tcpdump \

View File

@@ -1,14 +1,13 @@
import json
import os
import struct
import sys
import socket
import logging
import itertools
import requests
from pathlib import Path
from enum import Enum
from netaddr import IPNetwork, IPAddress, AddrFormatError
from psutil import net_if_addrs
from kube_hunter.conf import get_config
from kube_hunter.modules.discovery.kubernetes_client import list_all_k8s_cluster_nodes
@@ -142,7 +141,7 @@ class FromPodHostDiscovery(Discovery):
gateway_subnet = self.gateway_discovery()
if gateway_subnet:
subnets += gateway_subnet
subnets.append(gateway_subnet)
should_scan_apiserver = False
if self.event.kubeservicehost:
@@ -226,20 +225,22 @@ class FromPodHostDiscovery(Discovery):
# netifaces currently does not have a maintainer. so we backported to linux support only for this cause.
# TODO: implement WMI queries for windows support
# https://stackoverflow.com/a/6556951
if not Path("/proc/net/route").exists():
logging.debug("Error getting default gateway from /proc/net/route. not runnning in linux environment")
return False
if sys.platform in ["linux", "linux2"]:
try:
from pyroute2 import IPDB
try:
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != "00000000" or not int(fields[3], 16) & 2:
# If not default route or not RTF_GATEWAY, skip it
continue
return [socket.inet_ntoa(struct.pack("<L", int(fields[2], 16))), "24"]
except Exception as x:
logging.debug(f"Exception when parsing /proc/net/route to figure default gateway: {x}")
ip = IPDB()
gateway_ip = ip.routes["default"]["gateway"]
ip.release()
return [gateway_ip, "24"]
except Exception as x:
logging.debug(f"Exception while fetching default gateway from container - {x}")
finally:
ip.release()
else:
logging.debug("Not running in a linux env, will not scan default subnet")
return False
# querying AWS's interface metadata api v1 | works only from a pod
def aws_metadata_v1_discovery(self):
@@ -360,21 +361,61 @@ class HostDiscovery(Discovery):
# generate all subnets from all internal network interfaces
def generate_interfaces_subnet(self, sn="24"):
ifaces = net_if_addrs()
for _, ifaceAddresses in ifaces.items():
# filter only ipv4 addresses on interface
ipv4_addresses = list(filter(lambda x: x.family == socket.AF_INET, ifaceAddresses))
if ipv4_addresses:
for address in ipv4_addresses:
if sys.platform == "win32":
return self.generate_interfaces_subnet_windows()
elif sys.platform in ["linux", "linux2"]:
return self.generate_interfaces_subnet_linux()
def generate_interfaces_subnet_linux(self, sn="24"):
try:
from pyroute2 import IPRoute
ip = IPRoute()
for i in ip.get_addr():
# whitelist only ipv4 ips
if i["family"] == socket.AF_INET:
ipaddress = i[0].get_attr("IFA_ADDRESS")
# TODO: add this instead of hardcoded 24 subnet, (add a flag for full scan option)
# subnet = i['prefixlen']
# unless specified explicitly with localhost scan flag, skip localhost ip addresses
if not self.event.localhost and address.address.__str__().startswith(
InterfaceTypes.LOCALHOST.value
):
if not self.event.localhost and ipaddress.startswith(InterfaceTypes.LOCALHOST.value):
continue
ip_network = IPNetwork(f"{address.address}/{sn}")
ip_network = IPNetwork(f"{ipaddress}/{sn}")
for ip in ip_network:
yield ip
except Exception as x:
logging.debug(f"Exception while generating subnet scan from local interfaces: {x}")
finally:
ip.release()
def generate_interfaces_subnet_windows(self, sn="24"):
from subprocess import check_output
local_subnets = (
check_output(
"powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy bypass -Command "
' "& {'
"Get-NetIPConfiguration | Get-NetIPAddress | Where-Object {$_.AddressFamily -eq 'IPv4'}"
" | Select-Object -Property IPAddress, PrefixLength | ConvertTo-Json "
' "}',
shell=True,
)
.decode()
.strip()
)
try:
subnets = json.loads(local_subnets)
for subnet in subnets:
if not self.event.localhost and subnet["IPAddress"].startswith(InterfaceTypes.LOCALHOST.value):
continue
ip_network = IPNetwork(f"{subnet['IPAddress']}/{sn}")
for ip in ip_network:
yield ip
except Exception as x:
logging.debug(f"ERROR: Could not extract interface information using powershell - {x}")
# for comparing prefixes

View File

@@ -31,7 +31,7 @@ zip_safe = False
packages = find:
install_requires =
netaddr
psutil
pyroute2
requests
PrettyTable
urllib3>=1.24.3