mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-08-23 22:26:23 +00:00
Ignore downstream version flag (#181)
* Ignore downstream version flag This commit adds `--ignore-downstream` flag to kube-hunter. Enabling the flag will make kube-hunter considering patched versions as not vulnerable. Resolves #179 * Add test cases and refine argument description
This commit is contained in:
committed by
danielsagi
parent
c4e1e1e48c
commit
a1feb06ec7
@@ -9,6 +9,7 @@ parser.add_argument('--list', action="store_true", help="displays all tests in k
|
||||
parser.add_argument('--interface', action="store_true", help="set hunting of all network interfaces")
|
||||
parser.add_argument('--pod', action="store_true", help="set hunter as an insider pod")
|
||||
parser.add_argument('--quick', action="store_true", help="Prefer quick scan (subnet 24)")
|
||||
parser.add_argument('--ignore-downstream', action="store_true", help="Ignore patched kubernetes versions")
|
||||
parser.add_argument('--cidr', type=str, help="set an ip range to scan, example: 192.168.0.0/16")
|
||||
parser.add_argument('--mapping', action="store_true", help="outputs only a mapping of the cluster's nodes")
|
||||
parser.add_argument('--remote', nargs='+', metavar="HOST", default=list(), help="one or more remote ip/dns to hunt")
|
||||
|
||||
@@ -6,6 +6,7 @@ parser.add_argument('--list', action="store_true", help="displays all tests in k
|
||||
parser.add_argument('--interface', action="store_true", help="set hunting of all interface network interfaces")
|
||||
parser.add_argument('--pod', action="store_true", help="set hunter as an insider pod")
|
||||
parser.add_argument('--quick', action="store_true", help="Prefer quick scan (subnet 24)")
|
||||
parser.add_argument('--ignore-downstream', action="store_true", help="Ignore patched kubernetes versions")
|
||||
parser.add_argument('--cidr', type=str, help="set an ip range to scan, example: 192.168.0.0/16")
|
||||
parser.add_argument('--mapping', action="store_true", help="outputs only a mapping of the cluster's nodes")
|
||||
parser.add_argument('--remote', nargs='+', metavar="HOST", default=list(), help="one or more remote ip/dns to hunt")
|
||||
|
||||
@@ -2,6 +2,8 @@ import logging
|
||||
import json
|
||||
import requests
|
||||
|
||||
from __main__ import config
|
||||
|
||||
from ...core.events import handler
|
||||
from ...core.events.types import Vulnerability, Event, K8sVersionDisclosure
|
||||
from ...core.types import Hunter, ActiveHunter, KubernetesCluster, RemoteCodeExec, AccessRisk, InformationDisclosure, \
|
||||
@@ -95,8 +97,15 @@ class CveUtils:
|
||||
return (v1>v2)-(v1<v2)
|
||||
|
||||
@staticmethod
|
||||
def is_vulnerable(fix_versions, check_version):
|
||||
def is_downstream_version(version):
|
||||
return any(c in version for c in '+-~')
|
||||
|
||||
@staticmethod
|
||||
def is_vulnerable(fix_versions, check_version, ignore_downstream=False):
|
||||
"""Function determines if a version is vulnerable, by comparing to given fix versions by base release"""
|
||||
if ignore_downstream and CveUtils.is_downstream_version(check_version):
|
||||
return False
|
||||
|
||||
vulnerable = False
|
||||
check_v = version.parse(check_version)
|
||||
base_check_v = CveUtils.get_base_release(check_v)
|
||||
@@ -146,7 +155,7 @@ class K8sClusterCveHunter(Hunter):
|
||||
ServerApiClusterScopedResourcesAccess: ["1.13.9", "1.14.5", "1.15.2"]
|
||||
}
|
||||
for vulnerability, fix_versions in cve_mapping.items():
|
||||
if CveUtils.is_vulnerable(fix_versions, self.event.version):
|
||||
if CveUtils.is_vulnerable(fix_versions, self.event.version, config.ignore_downstream):
|
||||
self.publish_event(vulnerability(self.event.version))
|
||||
|
||||
|
||||
@@ -165,5 +174,5 @@ class KubectlCVEHunter(Hunter):
|
||||
}
|
||||
logging.debug('Kubectl Cve Hunter determining vulnerable version: {}'.format(self.event.version))
|
||||
for vulnerability, fix_versions in cve_mapping.items():
|
||||
if CveUtils.is_vulnerable(fix_versions, self.event.version):
|
||||
if CveUtils.is_vulnerable(fix_versions, self.event.version, config.ignore_downstream):
|
||||
self.publish_event(vulnerability(binary_version=self.event.version))
|
||||
|
||||
@@ -3,7 +3,7 @@ import requests_mock
|
||||
|
||||
from src.core.events import handler
|
||||
from src.core.events.types import K8sVersionDisclosure
|
||||
from src.modules.hunting.cves import K8sClusterCveHunter, ServerApiVersionEndPointAccessPE, ServerApiVersionEndPointAccessDos
|
||||
from src.modules.hunting.cves import K8sClusterCveHunter, ServerApiVersionEndPointAccessPE, ServerApiVersionEndPointAccessDos, CveUtils
|
||||
|
||||
cve_counter = 0
|
||||
|
||||
@@ -49,4 +49,41 @@ class test_CVE_2018_1002105(object):
|
||||
class test_CVE_2019_1002100(object):
|
||||
def __init__(self, event):
|
||||
global cve_counter
|
||||
cve_counter += 1
|
||||
cve_counter += 1
|
||||
|
||||
class test_CveUtils(object):
|
||||
def test_is_downstream():
|
||||
test_cases = (
|
||||
('1', False),
|
||||
('1.2', False),
|
||||
('1.2-3', True),
|
||||
('1.2-r3', True),
|
||||
('1.2+3', True),
|
||||
('1.2~3', True),
|
||||
('1.2+a3f5cb2', True),
|
||||
('1.2-9287543', True),
|
||||
('v1', False),
|
||||
('v1.2', False),
|
||||
('v1.2-3', True),
|
||||
('v1.2-r3', True),
|
||||
('v1.2+3', True),
|
||||
('v1.2~3', True),
|
||||
('v1.2+a3f5cb2', True),
|
||||
('v1.2-9287543', True),
|
||||
('v1.13.9-gke.3', True)
|
||||
)
|
||||
|
||||
for version, expected in test_cases:
|
||||
actual = CveUtils.is_downstream_version(version)
|
||||
assert actual == expected
|
||||
|
||||
def test_ignore_downstream():
|
||||
test_cases = (
|
||||
('v2.2-abcd', ['v1.1', 'v2.3'], False),
|
||||
('v2.2-abcd', ['v1.1', 'v2.2'], False),
|
||||
('v1.13.9-gke.3', ['v1.14.8'], False)
|
||||
)
|
||||
|
||||
for check_version, fix_versions, expected in test_cases:
|
||||
actual = CveUtils.is_vulnerable(check_version, fix_versions, True)
|
||||
assert actual == expected
|
||||
|
||||
Reference in New Issue
Block a user