Repository: aquasecurity/kube-hunter (language: python)

Issue:
Use of scapy and possible Apache-GPL license conflict
kube-hunter is licensed under Apache 2.0.  kube-hunter includes scapy.  scapy is licensed under GPL 2.0.  According to https://www.apache.org/licenses/GPL-compatibility.html, there is a license conflict.  How does the kube-hunter project work around/through this?
Use of scapy and possible Apache-GPL license conflict
kube-hunter is licensed under Apache 2.0.  kube-hunter includes scapy.  scapy is licensed under GPL 2.0.  According to https://www.apache.org/licenses/GPL-compatibility.html, there is a license conflict.  How does the kube-hunter project work around/through this?


Discussion / hints:

Fix patch:
diff --git a/.flake8 b/.flake8
index 008a958a..2e209839 100644
--- a/.flake8
+++ b/.flake8
@@ -1,5 +1,5 @@
 [flake8]
-ignore = E203, E266, E501, W503, B903, T499
+ignore = E203, E266, E501, W503, B903, T499, B020
 max-line-length = 120
 max-complexity = 18
 select = B,C,E,F,W,B9,T4
diff --git a/Dockerfile b/Dockerfile
index 19523913..7c1a6d8b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,4 +26,7 @@ RUN apk add --no-cache \
 COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
 COPY --from=builder /usr/local/bin/kube-hunter /usr/local/bin/kube-hunter
 
+# Add default plugins: https://github.com/aquasecurity/kube-hunter-plugins 
+RUN pip install kube-hunter-arp-spoof>=0.0.3 kube-hunter-dns-spoof>=0.0.3
+
 ENTRYPOINT ["kube-hunter"]
diff --git a/kube_hunter/conf/logging.py b/kube_hunter/conf/logging.py
index bf5ed5a1..94498836 100644
--- a/kube_hunter/conf/logging.py
+++ b/kube_hunter/conf/logging.py
@@ -4,10 +4,6 @@
 DEFAULT_LEVEL_NAME = logging.getLevelName(DEFAULT_LEVEL)
 LOG_FORMAT = "%(asctime)s %(levelname)s %(name)s %(message)s"
 
-# Suppress logging from scapy
-logging.getLogger("scapy.runtime").setLevel(logging.CRITICAL)
-logging.getLogger("scapy.loading").setLevel(logging.CRITICAL)
-
 
 def setup_logger(level_name, logfile):
     # Remove any existing handlers
diff --git a/kube_hunter/modules/hunting/__init__.py b/kube_hunter/modules/hunting/__init__.py
index 1d38fe40..d5d5e5bc 100644
--- a/kube_hunter/modules/hunting/__init__.py
+++ b/kube_hunter/modules/hunting/__init__.py
@@ -2,12 +2,10 @@
 from . import (
     aks,
     apiserver,
-    arp,
     capabilities,
     certificates,
     cves,
     dashboard,
-    dns,
     etcd,
     kubelet,
     mounts,
diff --git a/kube_hunter/modules/hunting/arp.py b/kube_hunter/modules/hunting/arp.py
deleted file mode 100644
index 0a37f1d8..00000000
--- a/kube_hunter/modules/hunting/arp.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import logging
-
-from scapy.all import ARP, IP, ICMP, Ether, sr1, srp
-
-from kube_hunter.conf import get_config
-from kube_hunter.core.events import handler
-from kube_hunter.core.events.types import Event, Vulnerability
-from kube_hunter.core.types import ActiveHunter, KubernetesCluster, ARPPoisoningTechnique
-from kube_hunter.modules.hunting.capabilities import CapNetRawEnabled
-
-logger = logging.getLogger(__name__)
-
-
-class PossibleArpSpoofing(Vulnerability, Event):
-    """A malicious pod running on the cluster could potentially run an ARP Spoof attack
-    and perform a MITM between pods on the node."""
-
-    def __init__(self):
-        Vulnerability.__init__(
-            self,
-            KubernetesCluster,
-            "Possible Arp Spoof",
-            category=ARPPoisoningTechnique,
-            vid="KHV020",
-        )
-
-
-@handler.subscribe(CapNetRawEnabled)
-class ArpSpoofHunter(ActiveHunter):
-    """Arp Spoof Hunter
-    Checks for the possibility of running an ARP spoof
-    attack from within a pod (results are based on the running node)
-    """
-
-    def __init__(self, event):
-        self.event = event
-
-    def try_getting_mac(self, ip):
-        config = get_config()
-        ans = sr1(ARP(op=1, pdst=ip), timeout=config.network_timeout, verbose=0)
-        return ans[ARP].hwsrc if ans else None
-
-    def detect_l3_on_host(self, arp_responses):
-        """returns True for an existence of an L3 network plugin"""
-        logger.debug("Attempting to detect L3 network plugin using ARP")
-        unique_macs = list({response[ARP].hwsrc for _, response in arp_responses})
-
-        # if LAN addresses not unique
-        if len(unique_macs) == 1:
-            # if an ip outside the subnets gets a mac address
-            outside_mac = self.try_getting_mac("1.1.1.1")
-            # outside mac is the same as lan macs
-            if outside_mac == unique_macs[0]:
-                return True
-        # only one mac address for whole LAN and outside
-        return False
-
-    def execute(self):
-        config = get_config()
-        self_ip = sr1(IP(dst="1.1.1.1", ttl=1) / ICMP(), verbose=0, timeout=config.network_timeout)[IP].dst
-        arp_responses, _ = srp(
-            Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=1, pdst=f"{self_ip}/24"),
-            timeout=config.network_timeout,
-            verbose=0,
-        )
-
-        # arp enabled on cluster and more than one pod on node
-        if len(arp_responses) > 1:
-            # L3 plugin not installed
-            if not self.detect_l3_on_host(arp_responses):
-                self.publish_event(PossibleArpSpoofing())
diff --git a/kube_hunter/modules/hunting/dns.py b/kube_hunter/modules/hunting/dns.py
deleted file mode 100644
index b0e037b3..00000000
--- a/kube_hunter/modules/hunting/dns.py
+++ /dev/null
@@ -1,90 +0,0 @@
-import re
-import logging
-
-from scapy.all import IP, ICMP, UDP, DNS, DNSQR, ARP, Ether, sr1, srp1, srp
-
-from kube_hunter.conf import get_config
-from kube_hunter.core.events import handler
-from kube_hunter.core.events.types import Event, Vulnerability
-from kube_hunter.core.types import ActiveHunter, KubernetesCluster, CoreDNSPoisoningTechnique
-from kube_hunter.modules.hunting.arp import PossibleArpSpoofing
-
-logger = logging.getLogger(__name__)
-
-
-class PossibleDnsSpoofing(Vulnerability, Event):
-    """A malicious pod running on the cluster could potentially run a DNS Spoof attack
-    and perform a MITM attack on applications running in the cluster."""
-
-    def __init__(self, kubedns_pod_ip):
-        Vulnerability.__init__(
-            self,
-            KubernetesCluster,
-            "Possible DNS Spoof",
-            category=CoreDNSPoisoningTechnique,
-            vid="KHV030",
-        )
-        self.kubedns_pod_ip = kubedns_pod_ip
-        self.evidence = f"kube-dns at: {self.kubedns_pod_ip}"
-
-
-# Only triggered with RunningAsPod base event
-@handler.subscribe(PossibleArpSpoofing)
-class DnsSpoofHunter(ActiveHunter):
-    """DNS Spoof Hunter
-    Checks for the possibility for a malicious pod to compromise DNS requests of the cluster
-    (results are based on the running node)
-    """
-
-    def __init__(self, event):
-        self.event = event
-
-    def get_cbr0_ip_mac(self):
-        config = get_config()
-        res = srp1(Ether() / IP(dst="1.1.1.1", ttl=1) / ICMP(), verbose=0, timeout=config.network_timeout)
-        return res[IP].src, res.src
-
-    def extract_nameserver_ip(self):
-        with open("/etc/resolv.conf") as f:
-            # finds first nameserver in /etc/resolv.conf
-            match = re.search(r"nameserver (\d+.\d+.\d+.\d+)", f.read())
-            if match:
-                return match.group(1)
-
-    def get_kube_dns_ip_mac(self):
-        config = get_config()
-        kubedns_svc_ip = self.extract_nameserver_ip()
-
-        # getting actual pod ip of kube-dns service, by comparing the src mac of a dns response and arp scanning.
-        dns_info_res = srp1(
-            Ether() / IP(dst=kubedns_svc_ip) / UDP(dport=53) / DNS(rd=1, qd=DNSQR()),
-            verbose=0,
-            timeout=config.network_timeout,
-        )
-        kubedns_pod_mac = dns_info_res.src
-        self_ip = dns_info_res[IP].dst
-
-        arp_responses, _ = srp(
-            Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=1, pdst=f"{self_ip}/24"),
-            timeout=config.network_timeout,
-            verbose=0,
-        )
-        for _, response in arp_responses:
-            if response[Ether].src == kubedns_pod_mac:
-                return response[ARP].psrc, response.src
-
-    def execute(self):
-        config = get_config()
-        logger.debug("Attempting to get kube-dns pod ip")
-        self_ip = sr1(IP(dst="1.1.1.1", ttl=1) / ICMP(), verbose=0, timeout=config.network_timeout)[IP].dst
-        cbr0_ip, cbr0_mac = self.get_cbr0_ip_mac()
-
-        kubedns = self.get_kube_dns_ip_mac()
-        if kubedns:
-            kubedns_ip, kubedns_mac = kubedns
-            logger.debug(f"ip={self_ip} kubednsip={kubedns_ip} cbr0ip={cbr0_ip}")
-            if kubedns_mac != cbr0_mac:
-                # if self pod in the same subnet as kube-dns pod
-                self.publish_event(PossibleDnsSpoofing(kubedns_pod_ip=kubedns_ip))
-        else:
-            logger.debug("Could not get kubedns identity")
diff --git a/setup.cfg b/setup.cfg
index 53a2f8ac..3e22976c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,7 +32,6 @@ packages = find:
 install_requires =
     netaddr
     netifaces
-    scapy>=2.4.3
     requests
     PrettyTable
     urllib3>=1.24.3


Test patch:
diff --git a/tests/core/test_handler.py b/tests/core/test_handler.py
index 5cf1546d..46baab59 100644
--- a/tests/core/test_handler.py
+++ b/tests/core/test_handler.py
@@ -20,14 +20,12 @@
     AccessApiServerActive,
     AccessApiServerWithToken,
 )
-from kube_hunter.modules.hunting.arp import ArpSpoofHunter
 from kube_hunter.modules.hunting.capabilities import PodCapabilitiesHunter
 from kube_hunter.modules.hunting.certificates import CertificateDiscovery
 
 from kube_hunter.modules.hunting.cves import K8sClusterCveHunter
 from kube_hunter.modules.hunting.cves import KubectlCVEHunter
 from kube_hunter.modules.hunting.dashboard import KubeDashboard
-from kube_hunter.modules.hunting.dns import DnsSpoofHunter
 from kube_hunter.modules.hunting.etcd import EtcdRemoteAccess, EtcdRemoteAccessActive
 from kube_hunter.modules.hunting.kubelet import (
     ProveAnonymousAuth,
@@ -76,8 +74,6 @@
 ACTIVE_HUNTERS = {
     ProveAzureSpnExposure,
     AccessApiServerActive,
-    ArpSpoofHunter,
-    DnsSpoofHunter,
     EtcdRemoteAccessActive,
     ProveRunHandler,
     ProveContainerLogsHandler,