Merge branch 'master' into refactor_host_discovery

This commit is contained in:
danielsagi
2019-12-01 00:45:07 +02:00
committed by GitHub
21 changed files with 63 additions and 30 deletions
+1
View File
@@ -4,6 +4,7 @@
*aqua*
venv/
.vscode
.coverage
.idea
# Directory Cache Files
+3
View File
@@ -14,8 +14,11 @@ before_script:
- flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- pip install pytest coverage pytest-cov
script:
- python runtest.py
after_success:
- bash <(curl -s https://codecov.io/bash)
notifications:
on_success: change
on_failure: change # `always` will be the setting once code changes slow down
+6 -1
View File
@@ -1,14 +1,18 @@
![kube-hunter](https://github.com/aquasecurity/kube-hunter/blob/master/kube-hunter.png)
[![Build Status](https://travis-ci.org/aquasecurity/kube-hunter.svg?branch=master)](https://travis-ci.org/aquasecurity/kube-hunter)
[![codecov](https://codecov.io/gh/aquasecurity/kube-hunter/branch/master/graph/badge.svg)](https://codecov.io/gh/aquasecurity/kube-hunter)
[![License](https://img.shields.io/github/license/aquasecurity/kube-hunter)](https://github.com/aquasecurity/kube-hunter/blob/master/LICENSE)
[![Docker image](https://images.microbadger.com/badges/image/aquasec/kube-hunter.svg)](https://microbadger.com/images/aquasec/kube-hunter "Get your own image badge on microbadger.com")
kube-hunter hunts for security weaknesses in Kubernetes clusters. The tool was developed to increase awareness and visibility for security issues in Kubernetes environments. **You should NOT run kube-hunter on a Kubernetes cluster that you don't own!**
**Run kube-hunter**: kube-hunter is available as a container (aquasec/kube-hunter), and we also offer a web site at [kube-hunter.aquasec.com](https://kube-hunter.aquasec.com) where you can register online to receive a token allowing you to see and share the results online. You can also run the Python code yourself as described below.
**Explore vulnerabilities**: The kube-hunter knowledge base includes articles about discoverable vulnerabilities and issues. When kube-hunter reports an issue, it will show its VID (Vulnerability ID) so you can look it up in the KB at https://aquasecurity.github.io/kube-hunter/
**Contribute**: We welcome contributions, especially new hunter modules that perform additional tests. If you would like to develop your modules please read [Guidelines For Developing Your First kube-hunter Module](src/README.md).
[![kube-hunter demo video](https://github.com/aquasecurity/kube-hunter/blob/master/kube-hunter-screenshot.png)](https://youtu.be/s2-6rTkH8a8?t=57s)
@@ -146,7 +150,8 @@ By default, kube-hunter runs in interactive mode. You can also specify the scann
### Pod
This option lets you discover what running a malicious container can do/discover on your cluster. This gives a perspective on what an attacker could do if they were able to compromise a pod, perhaps through a software vulnerability. This may reveal significantly more vulnerabilities.
The `job.yaml` file defines a Job that will run kube-hunter in a pod, using default Kubernetes pod access settings.
The example `job.yaml` file defines a Job that will run kube-hunter in a pod, using default Kubernetes pod access settings. (You may wish to modify this definition, for example to run as a non-root user, or to run in a different namespace.)
* Run the job with `kubectl create -f ./job.yaml`
* Find the pod name with `kubectl describe job kube-hunter`
* View the test results with `kubectl logs <pod name>`
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Information Disclosure]
## Issue description
The kubelet is is leaking container logs via the `/containerLogs` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
The kubelet is leaking container logs via the `/containerLogs` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Information Disclosure]
## Issue description
The kubelet is is leaking information about runnig pods via the `/runningpods` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
The kubelet is leaking information about running pods via the `/runningpods` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Remote Code Execution]
## Issue description
An attacker could run arbitrary commands on a container via the the kubelet's `/exec` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
An attacker could run arbitrary commands on a container via the kubelet's `/exec` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Remote Code Execution]
## Issue description
An attacker could run arbitrary commands on a container via the the kubelet's `/run` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
An attacker could run arbitrary commands on a container via the kubelet's `/run` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Remote Code Execution]
## Issue description
An attacker could read and write data from a pod via the the kubelet's `/portForward` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
An attacker could read and write data from a pod via the kubelet's `/portForward` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Remote Code Execution]
## Issue description
An attacker could attach to a running container via a websocket on the the the kubelet's `/attach` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
An attacker could attach to a running container via a websocket on the kubelet's `/attach` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Information Disclosure]
## Issue description
The kubelet is is leaking it's health information, which may contain sensitive information, via the `/healthz` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
The kubelet is leaking it's health information, which may contain sensitive information, via the `/healthz` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Information Disclosure]
## Issue description
The kubelet is is leaking system logs via the `/logs` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
The kubelet is leaking system logs via the `/logs` endpoint. This endpoint is exposed as part of the kubelet's debug handlers.
## Remediation
+1 -1
View File
@@ -8,7 +8,7 @@ categories: [Information Disclosure]
## Issue description
An open kubectl proxy was detected. `kubectl proxy` is a convenient tool to connent from a local machine into an application running in Kubernetes or to the Kubernetes API. This is common practice to browse for example the Kubernetes dashboard. Leaving an open proxy can be exploited by an attacker to gain access into your entire cluster.
An open kubectl proxy was detected. `kubectl proxy` is a convenient tool to connect from a local machine into an application running in Kubernetes or to the Kubernetes API. This is common practice to browse for example the Kubernetes dashboard. Leaving an open proxy can be exploited by an attacker to gain access into your entire cluster.
## Remediation
+1 -1
View File
@@ -9,7 +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('--include-patched-versions', action="store_true", help="Don't skip patched versions when scanning")
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")
+1 -1
View File
@@ -1,5 +1,5 @@
import logging
# Supress logging from scapy
# Suppress logging from scapy
logging.getLogger("scapy.runtime").setLevel(logging.CRITICAL)
logging.getLogger("scapy.loading").setLevel(logging.CRITICAL)
+1 -1
View File
@@ -6,7 +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('--include-patched-versions', action="store_true", help="Don't skip patched versions when scanning")
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")
+33
View File
@@ -0,0 +1,33 @@
[aliases]
test=pytest
# PyTest
[tool:pytest]
minversion = 2.9.1
norecursedirs = .venv .vscode
addopts = --cov=src
testpaths = tests
console_output_style = progress
python_classes = Test*
python_files = test_*.py
python_functions = test_*
filterwarnings = ignore::DeprecationWarning
# Coverage
[coverage:report]
# show missing lines numbers
show_missing = True
# Regexes for lines to exclude from consideration
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover
# Don't complain about missing debug-only code:
def __repr__
if self\.debug
# Don't complain if tests don't hit defensive
# assertion code:
raise AssertionError
raise NotImplementedError
# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
+1 -1
View File
@@ -25,7 +25,7 @@ When you write your module, you can decide on which Event to subscribe to, meani
-----------------------
### Hunter Types
There are three hunter types which you can implement: a `Hunter`, `ActiveHunter` and `Discovery`. Hunters just probe the state of a cluster, whereas ActiveHunter modules can attempt operations that could change the state of the cluster. Discovery is Hunter for discovery purposes only.
There are three hunter types which you can implement: a `Hunter`, `ActiveHunter` and `Discovery`. Hunters just probe the state of a cluster, whereas ActiveHunter modules can attempt operations that could change the state of the cluster. Discovery is Hunter for discovery purposes only.
##### Hunter
Example:
~~~python
+3 -3
View File
@@ -27,7 +27,7 @@ class Event(object):
# Event's logical location to be used mainly for reports.
# If event don't implement it check previous event
# This is because events are composed (previous -> previous ...)
# and not inheritted
# and not inherited
def location(self):
location = None
if self.previous:
@@ -77,7 +77,7 @@ class Vulnerability(object):
UnauthenticatedAccess: "low"
})
# TODO: make vid mandatry once migration is done
# TODO: make vid mandatory once migration is done
def __init__(self, component, name, category=None, vid=None):
self.vid = vid
self.component = component
@@ -154,7 +154,7 @@ class ReportDispatched(Event):
pass
""" Core Vulnerabilites """
""" Core Vulnerabilities """
class K8sVersionDisclosure(Vulnerability, Event):
"""The kubernetes version could be obtained from the {} endpoint """
def __init__(self, version, from_endpoint, extra_info=""):
+1 -1
View File
@@ -26,7 +26,7 @@ class ArpSpoofHunter(ActiveHunter):
return ans[ARP].hwsrc if ans else None
def detect_l3_on_host(self, arp_responses):
""" returns True for an existance of an L3 network plugin """
""" returns True for an existence of an L3 network plugin """
logging.debug("Attempting to detect L3 network plugin using ARP")
unique_macs = list(set(response[ARP].hwsrc for _, response in arp_responses))
+2 -2
View File
@@ -154,7 +154,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, config.ignore_downstream):
if CveUtils.is_vulnerable(fix_versions, self.event.version, not config.include_patched_versions):
self.publish_event(vulnerability(self.event.version))
@@ -173,5 +173,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, config.ignore_downstream):
if CveUtils.is_vulnerable(fix_versions, self.event.version, not config.include_patched_versions):
self.publish_event(vulnerability(binary_version=self.event.version))
+1 -10
View File
@@ -20,16 +20,7 @@ def test_K8sCveHunter():
assert cve_counter == 2
cve_counter = 0
# test complex version
e = K8sVersionDisclosure(version="1.10.1-gke-1", from_endpoint="/version")
h = K8sClusterCveHunter(e)
h.execute()
time.sleep(0.01)
assert cve_counter == 2
cve_counter = 0
# test complex version
# test patched version
e = K8sVersionDisclosure(version="v1.13.6-gke.13", from_endpoint="/version")
h = K8sClusterCveHunter(e)
h.execute()