mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-02-14 18:09:56 +00:00
Add Knowledge Base for reported vulnerabilities (#188)
This commit is contained in:
1
docs/.gitignore
vendored
Normal file
1
docs/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
_site
|
||||
2
docs/Gemfile
Normal file
2
docs/Gemfile
Normal file
@@ -0,0 +1,2 @@
|
||||
source 'https://rubygems.org'
|
||||
gem 'github-pages', group: :jekyll_plugins
|
||||
249
docs/Gemfile.lock
Normal file
249
docs/Gemfile.lock
Normal file
@@ -0,0 +1,249 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (4.2.11.1)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.11.1)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.17.13)
|
||||
ruby-enum (~> 0.5)
|
||||
concurrent-ruby (1.1.5)
|
||||
dnsruby (1.61.3)
|
||||
addressable (~> 2.5)
|
||||
em-websocket (0.5.1)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
ethon (0.12.0)
|
||||
ffi (>= 1.3.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.7.0)
|
||||
faraday (0.15.4)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.11.1)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.1)
|
||||
github-pages (200)
|
||||
activesupport (= 4.2.11.1)
|
||||
github-pages-health-check (= 1.16.1)
|
||||
jekyll (= 3.8.5)
|
||||
jekyll-avatar (= 0.6.0)
|
||||
jekyll-coffeescript (= 1.1.1)
|
||||
jekyll-commonmark-ghpages (= 0.1.5)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.11.0)
|
||||
jekyll-gist (= 1.5.0)
|
||||
jekyll-github-metadata (= 2.12.1)
|
||||
jekyll-mentions (= 1.4.1)
|
||||
jekyll-optional-front-matter (= 0.3.0)
|
||||
jekyll-paginate (= 1.1.0)
|
||||
jekyll-readme-index (= 0.2.0)
|
||||
jekyll-redirect-from (= 0.14.0)
|
||||
jekyll-relative-links (= 0.6.0)
|
||||
jekyll-remote-theme (= 0.4.0)
|
||||
jekyll-sass-converter (= 1.5.2)
|
||||
jekyll-seo-tag (= 2.5.0)
|
||||
jekyll-sitemap (= 1.2.0)
|
||||
jekyll-swiss (= 0.4.0)
|
||||
jekyll-theme-architect (= 0.1.1)
|
||||
jekyll-theme-cayman (= 0.1.1)
|
||||
jekyll-theme-dinky (= 0.1.1)
|
||||
jekyll-theme-hacker (= 0.1.1)
|
||||
jekyll-theme-leap-day (= 0.1.1)
|
||||
jekyll-theme-merlot (= 0.1.1)
|
||||
jekyll-theme-midnight (= 0.1.1)
|
||||
jekyll-theme-minimal (= 0.1.1)
|
||||
jekyll-theme-modernist (= 0.1.1)
|
||||
jekyll-theme-primer (= 0.5.3)
|
||||
jekyll-theme-slate (= 0.1.1)
|
||||
jekyll-theme-tactile (= 0.1.1)
|
||||
jekyll-theme-time-machine (= 0.1.1)
|
||||
jekyll-titles-from-headings (= 0.5.1)
|
||||
jemoji (= 0.10.2)
|
||||
kramdown (= 1.17.0)
|
||||
liquid (= 4.0.0)
|
||||
listen (= 3.1.5)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.5.0)
|
||||
nokogiri (>= 1.10.4, < 2.0)
|
||||
rouge (= 2.2.1)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.16.1)
|
||||
addressable (~> 2.3)
|
||||
dnsruby (~> 1.60)
|
||||
octokit (~> 4.0)
|
||||
public_suffix (~> 3.0)
|
||||
typhoeus (~> 1.3)
|
||||
html-pipeline (2.12.0)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
http_parser.rb (0.6.0)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (3.8.5)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 0.7)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (~> 1.14)
|
||||
liquid (~> 4.0)
|
||||
mercenary (~> 0.3.3)
|
||||
pathutil (~> 0.9)
|
||||
rouge (>= 1.7, < 4)
|
||||
safe_yaml (~> 1.0)
|
||||
jekyll-avatar (0.6.0)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-coffeescript (1.1.1)
|
||||
coffee-script (~> 2.2)
|
||||
coffee-script-source (~> 1.11.1)
|
||||
jekyll-commonmark (1.3.1)
|
||||
commonmarker (~> 0.14)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-commonmark-ghpages (0.1.5)
|
||||
commonmarker (~> 0.17.6)
|
||||
jekyll-commonmark (~> 1)
|
||||
rouge (~> 2)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-feed (0.11.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-gist (1.5.0)
|
||||
octokit (~> 4.2)
|
||||
jekyll-github-metadata (2.12.1)
|
||||
jekyll (~> 3.4)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
jekyll-mentions (1.4.1)
|
||||
html-pipeline (~> 2.3)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-optional-front-matter (0.3.0)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-readme-index (0.2.0)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-redirect-from (0.14.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-relative-links (0.6.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-remote-theme (0.4.0)
|
||||
addressable (~> 2.0)
|
||||
jekyll (~> 3.5)
|
||||
rubyzip (>= 1.2.1, < 3.0)
|
||||
jekyll-sass-converter (1.5.2)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.5.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sitemap (1.2.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-swiss (0.4.0)
|
||||
jekyll-theme-architect (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-cayman (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-dinky (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-hacker (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-leap-day (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-merlot (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-midnight (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-minimal (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-modernist (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-primer (0.5.3)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-github-metadata (~> 2.9)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-slate (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-tactile (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-time-machine (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-titles-from-headings (0.5.1)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
jemoji (0.10.2)
|
||||
gemoji (~> 3.0)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (~> 3.0)
|
||||
kramdown (1.17.0)
|
||||
liquid (4.0.0)
|
||||
listen (3.1.5)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
ruby_dep (~> 1.2)
|
||||
mercenary (0.3.6)
|
||||
mini_portile2 (2.4.0)
|
||||
minima (2.5.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-feed (~> 0.9)
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.11.3)
|
||||
multipart-post (2.1.1)
|
||||
nokogiri (1.10.4)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
octokit (4.14.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (3.1.1)
|
||||
rb-fsevent (0.10.3)
|
||||
rb-inotify (0.10.0)
|
||||
ffi (~> 1.0)
|
||||
rouge (2.2.1)
|
||||
ruby-enum (0.7.2)
|
||||
i18n
|
||||
ruby_dep (1.5.0)
|
||||
rubyzip (1.2.4)
|
||||
safe_yaml (1.0.5)
|
||||
sass (3.7.4)
|
||||
sass-listen (~> 4.0.0)
|
||||
sass-listen (4.0.0)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
sawyer (0.8.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (> 0.8, < 2.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
typhoeus (1.3.1)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
unicode-display_width (1.6.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
github-pages
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.2
|
||||
6
docs/_config.yml
Normal file
6
docs/_config.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
title: kube-hunter
|
||||
description: Kube-hunter hunts for security weaknesses in Kubernetes clusters
|
||||
logo: https://raw.githubusercontent.com/aquasecurity/kube-hunter/master/kube-hunter.png
|
||||
show_downloads: false
|
||||
google_analytics: UA-63272154-1
|
||||
theme: jekyll-theme-minimal
|
||||
98
docs/_layouts/default.html
Normal file
98
docs/_layouts/default.html
Normal file
@@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% seo %}
|
||||
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<header>
|
||||
<h1><a href="{{ "/" | absolute_url }}">
|
||||
{% if site.logo %}
|
||||
<img src="{{site.logo | relative_url}}" alt="Logo" />
|
||||
{% else %}
|
||||
{{ site.title | default: site.github.repository_name }}
|
||||
{% endif %}
|
||||
</a></h1>
|
||||
|
||||
<p>{{ site.description | default: site.github.project_tagline }}</p>
|
||||
|
||||
{% if site.github.is_project_page %}
|
||||
<p class="view"><a href="{{ site.github.repository_url }}">View the Project on GitHub <small>{{ site.github.repository_nwo }}</small></a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if site.github.is_user_page %}
|
||||
<p class="view"><a href="{{ site.github.owner_url }}">View My GitHub Profile</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if site.show_downloads %}
|
||||
<ul class="downloads">
|
||||
<li><a href="{{ site.github.zip_url }}">Download <strong>ZIP File</strong></a></li>
|
||||
<li><a href="{{ site.github.tar_url }}">Download <strong>TAR Ball</strong></a></li>
|
||||
<li><a href="{{ site.github.repository_url }}">View On <strong>GitHub</strong></a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<input type="text" id="searchInput" placeholder="Find vulnerability by id">
|
||||
<button id="searchButton" class="searchButton">Go</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<section>
|
||||
|
||||
{{ content }}
|
||||
|
||||
</section>
|
||||
<footer>
|
||||
{% if site.github.is_project_page %}
|
||||
<p>This project is maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
|
||||
{% endif %}
|
||||
<p><small>Hosted on GitHub Pages — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{ "/assets/js/scale.fix.js" | relative_url }}"></script>
|
||||
<script type="text/javascript">
|
||||
var articleUrlPrefix = "{{ site.url }}/kb/";
|
||||
var searchInput = document.getElementById("searchInput");
|
||||
var searchButton = document.getElementById("searchButton");
|
||||
searchInput.addEventListener("keyup", function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
doSearch();
|
||||
}
|
||||
});
|
||||
searchButton.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
doSearch();
|
||||
});
|
||||
function doSearch() {
|
||||
var searchTerm = searchInput.value;
|
||||
searchTerm = searchTerm.toUpperCase();
|
||||
if (!searchTerm.startsWith("KHV")) {
|
||||
searchTerm = "KHV" + searchTerm;
|
||||
}
|
||||
window.location = articleUrlPrefix + searchTerm;
|
||||
}
|
||||
</script>
|
||||
{% if site.google_analytics %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', '{{ site.google_analytics }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
120
docs/index.md
Normal file
120
docs/index.md
Normal file
@@ -0,0 +1,120 @@
|
||||
---
|
||||
---
|
||||
# Welcome to kube-hunter documentation
|
||||
|
||||
## Documentation for vulnerabilities
|
||||
|
||||
For information about a specific vulnerability reported by kube-hunter, enter its 'VID' (e.g. KHV004) in the search box to the left, to get to the vulnerability article.
|
||||
|
||||
## Getting started
|
||||
|
||||
### Where should I run kube-hunter?
|
||||
Run kube-hunter on any machine (including your laptop), select Remote scanning and give the IP address or domain name of your Kubernetes cluster. This will give you an attackers-eye-view of your Kubernetes setup.
|
||||
|
||||
You can run kube-hunter directly on a machine in the cluster, and select the option to probe all the local network interfaces.
|
||||
|
||||
You can also run kube-hunter in a pod within the cluster. This gives an indication of how exposed your cluster would be in the event that one of your application pods is compromised (through a software vulnerability, for example).
|
||||
|
||||
### Scanning options
|
||||
|
||||
By default, kube-hunter will open an interactive session, in which you will be able to select one of the following scan options. You can also specify the scan option manually from the command line. These are your options:
|
||||
|
||||
1. **Remote scanning**
|
||||
To specify remote machines for hunting, select option 1 or use the `--remote` option. Example:
|
||||
`./kube-hunter.py --remote some.node.com`
|
||||
|
||||
2. **interface scanning**
|
||||
To specify interface scanning, you can use the `--interface` option. (this will scan all of the machine's network interfaces) Example:
|
||||
`./kube-hunter.py --interface`
|
||||
|
||||
3. **Network scanning**
|
||||
To specify a specific CIDR to scan, use the `--cidr` option. Example:
|
||||
`./kube-hunter.py --cidr 192.168.0.0/24`
|
||||
|
||||
### Active Hunting
|
||||
|
||||
Active hunting is an option in which kube-hunter will exploit vulnerabilities it finds, in order to explore for further vulnerabilities.
|
||||
The main difference between normal and active hunting is that a normal hunt will never change state of the cluster, while active hunting can potentially do state-changing operations on the cluster, **which could be harmful**.
|
||||
|
||||
By default, kube-hunter does not do active hunting. To active hunt a cluster, use the `--active` flag. Example:
|
||||
`./kube-hunter.py --remote some.domain.com --active`
|
||||
|
||||
### List of tests
|
||||
You can see the list of tests with the `--list` option: Example:
|
||||
`./kube-hunter.py --list`
|
||||
|
||||
To see active hunting tests as well as passive:
|
||||
`./kube-hunter.py --list --active`
|
||||
|
||||
### Nodes Mapping
|
||||
To see only a mapping of your nodes network, run with `--mapping` option. Example:
|
||||
`./kube-hunter.py --cidr 192.168.0.0/24 --mapping`
|
||||
This will output all the Kubernetes nodes kube-hunter has found.
|
||||
|
||||
### Output
|
||||
To control logging, you can specify a log level, using the `--log` option. Example:
|
||||
`./kube-hunter.py --active --log WARNING`
|
||||
Available log levels are:
|
||||
|
||||
* DEBUG
|
||||
* INFO (default)
|
||||
* WARNING
|
||||
|
||||
### Dispatching
|
||||
By default, the report will be dispatched to `stdout`, but you can specify different methods, by using the `--dispatch` option. Example:
|
||||
`./kube-hunter.py --report json --dispatch http`
|
||||
Available dispatch methods are:
|
||||
|
||||
* stdout (default)
|
||||
* http (to configure, set the following environment variables:)
|
||||
* KUBEHUNTER_HTTP_DISPATCH_URL (defaults to: https://localhost)
|
||||
* KUBEHUNTER_HTTP_DISPATCH_METHOD (defaults to: POST)
|
||||
|
||||
## Deployment
|
||||
There are three methods for deploying kube-hunter:
|
||||
|
||||
### On Machine
|
||||
|
||||
You can run the kube-hunter python code directly on your machine.
|
||||
#### Prerequisites
|
||||
|
||||
You will need the following installed:
|
||||
* python 3.x
|
||||
* pip
|
||||
|
||||
Clone the repository:
|
||||
~~~
|
||||
git clone https://github.com/aquasecurity/kube-hunter.git
|
||||
~~~
|
||||
|
||||
Install module dependencies:
|
||||
~~~
|
||||
cd ./kube-hunter
|
||||
pip install -r requirements.txt
|
||||
~~~
|
||||
|
||||
Run:
|
||||
`./kube-hunter.py`
|
||||
|
||||
_If you want to use pyinstaller/py2exe you need to first run the install_imports.py script._
|
||||
### Container
|
||||
Aqua Security maintains a containerised version of kube-hunter at `aquasec/kube-hunter`. This container includes this source code, plus an additional (closed source) reporting plugin for uploading results into a report that can be viewed at [kube-hunter.aquasec.com](https://kube-hunter.aquasec.com). Please note that running the `aquasec/kube-hunter` container and uploading reports data are subject to additional [terms and conditions](https://kube-hunter.aquasec.com/eula.html).
|
||||
|
||||
The Dockerfile in this repository allows you to build a containerised version without the reporting plugin.
|
||||
|
||||
If you run the kube-hunter container with the host network it will be able to probe all the interfaces on the host:
|
||||
|
||||
`docker run -it --rm --network host aquasec/kube-hunter`
|
||||
|
||||
_Note for Docker for Mac/Windows:_ Be aware that the "host" for Docker for Mac or Windows is the VM which Docker runs containers within. Therefore specifying `--network host` allows kube-hunter access to the network interfaces of that VM, rather than those of your machine.
|
||||
By default kube-hunter runs in interactive mode. You can also specify the scanning option with the parameters described above e.g.
|
||||
|
||||
`docker run --rm aquasec/kube-hunter --cidr 192.168.0.0/24`
|
||||
|
||||
### 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.
|
||||
* Run the job with `kubectl create` with that yaml file.
|
||||
* Find the pod name with `kubectl describe job kube-hunter`
|
||||
* View the test results with `kubectl logs <pod name>`
|
||||
12
docs/kb/KHV002.md
Normal file
12
docs/kb/KHV002.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
id: KHV002
|
||||
title: Kubernetes version disclosure
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV002 - Kubernetes version disclosure
|
||||
|
||||
## Issue description
|
||||
|
||||
The fact that your infrastructure is using Kubernetes, and the specific version of Kubernetes used is publicly available, and could be used by an attacker to target your environment with known vulnerabilities in the specific version of Kubernetes you are using.
|
||||
|
||||
20
docs/kb/KHV003.md
Normal file
20
docs/kb/KHV003.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV003
|
||||
title: Azure Metadata Exposure
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV003 - Azure Metadata Exposure
|
||||
|
||||
## Issue description
|
||||
|
||||
Microsoft Azure provides an internal HTTP endpoint that exposes information from the cloud platform to workloads running in a VM. The endoint is accessible to every workload running in the VM. An attacker that is able to execute a pod in the cluster may be able to query the metadata service and discover additional information about the environment.
|
||||
|
||||
## Remediation
|
||||
|
||||
Consider using AAD Pod Identity. A Microsoft project that allows scoping the identity of workloads to Kubernetes Pods instead of VMs (instances).
|
||||
|
||||
## References
|
||||
|
||||
- [Azure Instance Metadata service](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service)
|
||||
- [AAD Pod Identity](https://github.com/Azure/aad-pod-identity#demo)
|
||||
24
docs/kb/KHV004.md
Normal file
24
docs/kb/KHV004.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
id: KHV004
|
||||
title: Azure SPN Exposure
|
||||
categories: [Identity Theft]
|
||||
---
|
||||
|
||||
# KHV004 - Azure SPN Exposure
|
||||
|
||||
## Issue description
|
||||
|
||||
Kubernetes has native integration with Microsoft Azure, for that a Kubernetes installation on Azure will require API access to manage the cluster's resources in Azure (for example, to create a cloud load balancer). Some installations of Kubernetes on Azure rely on a shared file on the node that contains credentials to the Azure API under `/etc/kubernetes/azure.json`. A Pod with access to this file may become a gateway for an attacker to control your Azure environment.
|
||||
|
||||
## Remediation
|
||||
|
||||
The better solution would be to use Azure Managed Identities instead of a static SPN. However this functionality is not mature yet, and is currently available in alpha stage only for aks-engine (non-managed Kubernetes).
|
||||
|
||||
You can update or rotate the cluster SPN credentials, in order to prevent leaked credentials to persist over time.
|
||||
|
||||
## References
|
||||
|
||||
- [Service principals with Azure Kubernetes Service (AKS)](https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/aks/kubernetes-service-principal.md)
|
||||
- [What is managed identities for Azure resources?](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
|
||||
- [aks-engine Features - Managed Identity](https://github.com/Azure/aks-engine/blob/master/docs/topics/features.md#managed-identity)
|
||||
- [Update or rotate the credentials for a service principal in Azure Kubernetes Service (AKS)](https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/aks/update-credentials.md)
|
||||
24
docs/kb/KHV005.md
Normal file
24
docs/kb/KHV005.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
id: KHV005
|
||||
title: Access to Kubernetes API
|
||||
categories: [Information Disclosure, Unauthenticated Access]
|
||||
---
|
||||
|
||||
# KHV005 - Access to Kubernetes API
|
||||
|
||||
## Issue description
|
||||
|
||||
Kubernetes API was accessed with Pod Service Account or without Authentication (see report message for details).
|
||||
|
||||
## Remediation
|
||||
|
||||
Secure acess to your Kubernetes API.
|
||||
|
||||
It is recommended to explicitly specify a Service Account for all of your workloads (`serviceAccountName` in `Pod.Spec`), and manage their permissions according to the least privilege principal.
|
||||
|
||||
Consider opting out automatic mounting of SA token using `automountServiceAccountToken: false` on `ServiceAccount` resource or `Pod.spec`.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
- [Configure Service Accounts for Pods](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
|
||||
23
docs/kb/KHV006.md
Normal file
23
docs/kb/KHV006.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
id: KHV006
|
||||
title: Insecure (HTTP) access to Kubernetes API
|
||||
categories: [Unauthenticated Access]
|
||||
---
|
||||
|
||||
# KHV006 - Insecure (HTTP) access to Kubernetes API
|
||||
|
||||
## Issue description
|
||||
|
||||
The API Server port is accessible over plain HTTP, and therefore unencrypted and potentially insecured.
|
||||
|
||||
## Remediation
|
||||
|
||||
Ensure your setup is exposing kube-api only on an HTTPS port.
|
||||
|
||||
Do not enable kube-api's `--insecure-port` flag in production.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
- [API Server Ports and IPs](https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/#api-server-ports-and-ips)
|
||||
- [kube-apiserver command reference](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)
|
||||
20
docs/kb/KHV020.md
Normal file
20
docs/kb/KHV020.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV020
|
||||
title: Possible Arp Spoof
|
||||
categories: [IdentityTheft]
|
||||
---
|
||||
|
||||
# KHV020 - Possible ARP Spoof
|
||||
|
||||
## Issue description
|
||||
|
||||
When using a basic (but common) container networking in the cluster, containers on the same host are bridged togeather to form a virtual layer 2 network. This setup, which is also common for Kubernetes installations. What's also common in Kubernetes installations, is that the `NET_RAW` capability is granted to Pods, allowing them low level access to network interactions. By pairing these two issues together, a malicious Pod running on the cluster could abusing the ARP protocol (used to discover MAC address by IP) in order to spoof the IP address of another pod on same node, thus making other pods on the node talk to the attacker's Pod instead of the legitimate Pod.
|
||||
|
||||
## Remediation
|
||||
|
||||
Consider dropping the `NET_RAW` capability from your pods using `Pod.spec.securityContext.capabilities`
|
||||
|
||||
## References
|
||||
|
||||
- [DNS Spoofing on Kubernetes Clusters](https://blog.aquasec.com/dns-spoofing-kubernetes-clusters)
|
||||
- [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
15
docs/kb/KHV021.md
Normal file
15
docs/kb/KHV021.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
id: KHV021
|
||||
title: Certificate Includes Email Address
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV021 - Certificate Includes Email Address
|
||||
|
||||
## Issue description
|
||||
|
||||
The Kubernetes API Server advertises a public certificate for TLS. This certificate includes an email address, that may provide additional information for an attacker on your organization, or be abused for further email based attacks.
|
||||
|
||||
## Remediation
|
||||
|
||||
Do not include email address in the Kubernetes API server certificate. (You should continue to use certificates to secure the API Server!)
|
||||
19
docs/kb/KHV022.md
Normal file
19
docs/kb/KHV022.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
id: KHV022
|
||||
title: Critical Privilege Escalation CVE
|
||||
categories: [Privilege Escalation]
|
||||
---
|
||||
|
||||
# KHV022 - Critical Privilege Escalation CVE
|
||||
|
||||
## Issue description
|
||||
|
||||
Cluster is found to be vulnerable to CVE-2018-1002105. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [Severe Privilege Escalation Vulnerability in Kubernetes (CVE-2018-1002105)](https://blog.aquasec.com/kubernetes-security-cve-2018-1002105)
|
||||
19
docs/kb/KHV023.md
Normal file
19
docs/kb/KHV023.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
id: KHV023
|
||||
title: Denial of Service to Kubernetes API Server
|
||||
categories: [Denial Of Service]
|
||||
---
|
||||
|
||||
# KHV022 - Denial of Service to Kubernetes API Server
|
||||
|
||||
## Issue description
|
||||
|
||||
Cluster is found to be vulnerable to CVE-2019-1002100. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [Kubernetes API Server Patch DoS Vulnerability (CVE-2019-1002100)](https://blog.aquasec.com/kubernetes-vulnerability-cve-2019-1002100)
|
||||
20
docs/kb/KHV024.md
Normal file
20
docs/kb/KHV024.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV024
|
||||
title: Possible Ping Flood Attack
|
||||
categories: [Denial Of Service]
|
||||
---
|
||||
|
||||
# KHV024 - Possible Ping Flood Attack
|
||||
|
||||
## Issue description
|
||||
|
||||
Cluster is found to be vulnerable to CVE-2019-9512. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [HTTP/2 Denial of Service Advisory](https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-002.md)
|
||||
- [CVE-2019-9512](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9512)
|
||||
20
docs/kb/KHV025.md
Normal file
20
docs/kb/KHV025.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV025
|
||||
title: Possible Reset Flood Attack
|
||||
categories: [Denial Of Service]
|
||||
---
|
||||
|
||||
# KHV025 - Possible Reset Flood Attack
|
||||
|
||||
## Issue description
|
||||
|
||||
Cluster is found to be vulnerable to CVE-2019-9514. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [HTTP/2 Denial of Service Advisory](https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-002.md)
|
||||
- [CVE-2019-9514](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9514)
|
||||
20
docs/kb/KHV026.md
Normal file
20
docs/kb/KHV026.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV026
|
||||
title: Arbitrary Access To Cluster Scoped Resources
|
||||
categories: [PrivilegeEscalation]
|
||||
---
|
||||
|
||||
# KHV026 - Arbitrary Access To Cluster Scoped Resources
|
||||
|
||||
## Issue description
|
||||
|
||||
Cluster is found to be vulnerable to CVE-2019-11247. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [CVE-2019-11247: API server allows access to custom resources via wrong scope](https://github.com/kubernetes/kubernetes/issues/80983)
|
||||
- [CVE-2019-11247](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11247)
|
||||
19
docs/kb/KHV027.md
Normal file
19
docs/kb/KHV027.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
id: KHV027
|
||||
title: Kubectl Vulnerable To CVE-2019-11246
|
||||
categories: [Remote Code Execution]
|
||||
---
|
||||
|
||||
# KHV027 - Kubectl Vulnerable To CVE-2019-11246
|
||||
|
||||
## Issue description
|
||||
|
||||
Kubectl is found to be vulnerable to CVE-2019-11246. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [CVE-2019-11246: Another kubectl Path Traversal Vulnerability Disclosed](https://blog.aquasec.com/kubernetes-security-kubectl-cve-2019-11246)
|
||||
20
docs/kb/KHV028.md
Normal file
20
docs/kb/KHV028.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV028
|
||||
title: Kubectl Vulnerable To CVE-2019-1002101
|
||||
categories: [Remote Code Execution]
|
||||
---
|
||||
|
||||
# KHV028 - Kubectl Vulnerable To CVE-2019-1002101
|
||||
|
||||
## Issue description
|
||||
|
||||
Kubectl is found to be vulnerable to CVE-2019-1002101. Please see the Vulnerability description for additional information.
|
||||
|
||||
## Remediation
|
||||
|
||||
Please see the Vulnerability description for remediation.
|
||||
|
||||
## References
|
||||
|
||||
- [CVE-2019-1002101](https://nvd.nist.gov/vuln/detail/CVE-2019-1002101)
|
||||
- [Another kubectl Path Traversal Vulnerability Disclosed](https://blog.aquasec.com/kubernetes-security-kubectl-cve-2019-11246)
|
||||
15
docs/kb/KHV029.md
Normal file
15
docs/kb/KHV029.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
id: KHV029
|
||||
title: Dashboard Exposed
|
||||
categories: [Remote Code Execution]
|
||||
---
|
||||
|
||||
# KHV029 - Dashboard Exposed
|
||||
|
||||
## Issue description
|
||||
|
||||
An open Kubernetes Dashboard was detected. The Kubernetes Dashboard can be used by an attacker to learn about the cluster and potentially to create new resources.
|
||||
|
||||
## Remediation
|
||||
|
||||
Do not leave the Dashboard insecured.
|
||||
20
docs/kb/KHV031.md
Normal file
20
docs/kb/KHV031.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV031
|
||||
title: Etcd Remote Write Access Event
|
||||
categories: [Remote Code Execution]
|
||||
---
|
||||
|
||||
# KHV031 - Etcd Remote Write Access Event
|
||||
|
||||
## Issue description
|
||||
|
||||
Etcd (Kubernetes' Database) is writable without authentication. This gives full control of your Kubernetes cluster to an attacker with access to etcd.
|
||||
|
||||
## Remediation
|
||||
|
||||
Ensure your etcd is accepting connections only from the Kubernetes API, using the `--trusted-ca-file` etcd flag. This is usually done by the installer, or cloud platform.
|
||||
|
||||
## References
|
||||
|
||||
- [etcd - Transport security model](https://etcd.io/docs/v3.4.0/op-guide/security/)
|
||||
- [Operating etcd clusters for Kubernetes - Securing etcd clusters](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#securing-etcd-clusters)
|
||||
20
docs/kb/KHV032.md
Normal file
20
docs/kb/KHV032.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV032
|
||||
title: Etcd Remote Read Access Event
|
||||
categories: [Access Risk]
|
||||
---
|
||||
|
||||
# KHV032 - Etcd Remote Read Access Event
|
||||
|
||||
## Issue description
|
||||
|
||||
Etcd (Kubernetes' Database) is accessible without authentication. This exposes the entire state of your Kubernetes cluster to the reader.
|
||||
|
||||
## Remediation
|
||||
|
||||
Ensure your etcd is accepting connections only from the Kubernetes API, using the `--trusted-ca-file` etcd flag. This is usually done by the installer, or cloud platform.
|
||||
|
||||
## References
|
||||
|
||||
- [etcd - Transport security model](https://etcd.io/docs/v3.4.0/op-guide/security/)
|
||||
- [Operating etcd clusters for Kubernetes - Securing etcd clusters](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#securing-etcd-clusters)
|
||||
12
docs/kb/KHV033.md
Normal file
12
docs/kb/KHV033.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
id: KHV033
|
||||
title: Etcd Remote version disclosure
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV033 - Etcd Remote version disclosure
|
||||
|
||||
## Issue description
|
||||
|
||||
The fact that your infrastructure is using etcd, and the specific version of etcd used is publicly available, and could be used by an attacker to target your environment with known vulnerabilities in the specific version of etcd you are using.
|
||||
|
||||
20
docs/kb/KHV034.md
Normal file
20
docs/kb/KHV034.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV034
|
||||
title: Etcd is accessible using insecure connection (HTTP)
|
||||
categories: [Unauthenticated Access]
|
||||
---
|
||||
|
||||
# KHV034 - Etcd is accessible using insecure connection (HTTP)
|
||||
|
||||
## Issue description
|
||||
|
||||
The etcd server (Kubernetes database) port is accessible over plain HTTP, and therefore unencrypted and potentially insecured.
|
||||
|
||||
## Remediation
|
||||
|
||||
Ensure your setup is exposing etcd only on an HTTPS port by using the etcd flags `--key-file` and `--cert-file`.
|
||||
|
||||
## References
|
||||
|
||||
- [etcd - Transport security model](https://etcd.io/docs/v3.4.0/op-guide/security/)
|
||||
- [Operating etcd clusters for Kubernetes - Securing etcd clusters](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#securing-etcd-clusters)
|
||||
19
docs/kb/KHV036.md
Normal file
19
docs/kb/KHV036.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
id: KHV036
|
||||
title: Anonymous Authentication
|
||||
categories: [Remote Code Execution]
|
||||
---
|
||||
|
||||
# KHV036 - Anonymous Authentication
|
||||
|
||||
## Issue description
|
||||
|
||||
The kubelet is configured to allow anonymous (unauthenticated) requests to it's HTTP api. This may expose certein information, and capabilities to an attacker with access to the kubelet API.
|
||||
|
||||
## Remediation
|
||||
|
||||
Ensure kubelet is protected using `--anonymous-auth=false` kubelet flag. Allow only legitimate users using `--client-ca-file` or `--authentication-token-webhook` kubelet flags. This is usually done by the installer or cloud provider.
|
||||
|
||||
## References
|
||||
|
||||
- [Kubelet authentication/authorization](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/)
|
||||
22
docs/kb/KHV044.md
Normal file
22
docs/kb/KHV044.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
id: KHV044
|
||||
title: Privileged Container
|
||||
categories: [Access Risk]
|
||||
---
|
||||
|
||||
# KHV044 - Privileged Container
|
||||
|
||||
## Issue description
|
||||
|
||||
Privilged containers are given access to all devices on the host and can work at the kernel level. It is declared using the `Pod.spec.containers[].securityContext.privileged` attribute. This may be useful for infrastructure containers that does setup work on the host, but is a dengerous attack vector.
|
||||
|
||||
## Remediation
|
||||
|
||||
Minimize the use of privileged containers.
|
||||
|
||||
Use Pod Security Policies to enforce using `privileged: false` policy.
|
||||
|
||||
## References
|
||||
|
||||
- [Privileged mode for pod containers](https://kubernetes.io/docs/concepts/workloads/pods/pod/#privileged-mode-for-pod-containers)
|
||||
- [Pod Security Policies - Privileged](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privileged)
|
||||
20
docs/kb/KHV045.md
Normal file
20
docs/kb/KHV045.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV045
|
||||
title: Exposed System Logs
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV045 - Exposed System Logs
|
||||
|
||||
## Issue description
|
||||
|
||||
When the Kubelet is run in debug mode, a Pod running in the cluster can able to access the Kubelet's `/logs` endpoint and read system logs.
|
||||
|
||||
## Remediation
|
||||
|
||||
Disable `--enable-debugging-handlers` kubelet flag.
|
||||
|
||||
## References
|
||||
|
||||
- [logs handler in Kubelet code](https://github.com/kubernetes/kubernetes/blob/4a6935b31fcc4d1498c977d90387e02b6b93288f/pkg/kubelet/server/server.go#L302)
|
||||
- [Kubelet - options](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#options)
|
||||
20
docs/kb/KHV046.md
Normal file
20
docs/kb/KHV046.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
id: KHV046
|
||||
title: Exposed Kubelet Cmdline
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV046 - Exposed Kubelet Cmdline
|
||||
|
||||
## Issue description
|
||||
|
||||
When the Kubelet is run in debug mode, a Pod running in the cluster is able to access the Kubelet's `debug/pprof/cmdline` endpoint and examine how the kubelet was executed on the node, specifically the command line flags that were used, which tells the attacker about what capabilities the kubelet has which might be exploited.
|
||||
|
||||
## Remediation
|
||||
|
||||
Disable `--enable-debugging-handlers` kubelet flag.
|
||||
|
||||
## References
|
||||
|
||||
- [cmdline handler in Kubelet code](https://github.com/kubernetes/kubernetes/blob/4a6935b31fcc4d1498c977d90387e02b6b93288f/pkg/kubelet/server/server.go#L327)
|
||||
- [Kubelet - options](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#options)
|
||||
27
docs/kb/KHV047.md
Normal file
27
docs/kb/KHV047.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
id: KHV047
|
||||
title: Pod With Mount To /var/log
|
||||
categories: [Privilege Escalation]
|
||||
---
|
||||
|
||||
# KHV047 - Pod With Mount To /var/log
|
||||
|
||||
## Issue description
|
||||
|
||||
Kubernetes uses `/var/log/pods` on nodes to store Pods log files. When running `kubectl logs` the kubelet is fetching the pod logs from that directory. If a container has write access to `/var/log` it can create arbitrary files, or symlink to other files on the host. Those would be read by the kubelet when a user executes `kubectl logs`.
|
||||
|
||||
## Remediation
|
||||
|
||||
Consider disallowing running as root:
|
||||
Using Kubernetes Pod Security Policies with `MustRunAsNonRoot` policy.
|
||||
Aqua users can use a Runtime Policy with `Volume Blacklist`.
|
||||
|
||||
Consider disallowing writable host mounts to `/var/log`:
|
||||
Using Kubernetes Pod Security Policies with `AllowedHostPaths` policy.
|
||||
Aqua users can use a Runtime Policy with `Blacklisted OS Users and Groups`.
|
||||
|
||||
## References
|
||||
|
||||
- [Kubernetes Pod Escape Using Log Mounts](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts)
|
||||
- [Pod Security Policies - Volumes and file systems](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems)
|
||||
- [Pod Security Policies - Users and groups](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#users-and-groups)
|
||||
21
docs/kb/KHV049.md
Normal file
21
docs/kb/KHV049.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
id: KHV049
|
||||
title: kubectl proxy Exposed
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# KHV049 - kubectl proxy Exposed
|
||||
|
||||
## 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.
|
||||
|
||||
## Remediation
|
||||
|
||||
Expose your applications in a permanent, legitimate way, such as via Ingress.
|
||||
|
||||
Close open proxies immediately after use.
|
||||
|
||||
## References
|
||||
|
||||
- [Accessing Clusters - Using kubectl proxy](https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#using-kubectl-proxy)
|
||||
22
docs/kb/KHV050.md
Normal file
22
docs/kb/KHV050.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
id: KHV050
|
||||
title: Read access to Pod service account token
|
||||
categories: [Access Risk]
|
||||
---
|
||||
|
||||
# KHV050 - Read access to Pod service account token
|
||||
|
||||
## Issue description
|
||||
|
||||
Every Pod in Kubernetes is associated with a Service Account which by default has access to the Kubernetes API. This access is made available to Pods by an auto-generated token that is made available to the Pod by Kubernetes. An attacker with access to a Pod can read the token and access the Kubernetes API.
|
||||
|
||||
## Remediation
|
||||
|
||||
It is recommended to explicitly specify a Service Account for all of your workloads (`serviceAccountName` in `Pod.Spec`), and manage their permissions according to the least privilege principal.
|
||||
|
||||
Consider opting out automatic mounting of SA token using `automountServiceAccountToken: false` on `ServiceAccount` resource or `Pod.spec`.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
- [Configure Service Accounts for Pods](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
|
||||
@@ -80,13 +80,18 @@ class Vulnerability(object):
|
||||
UnauthenticatedAccess: "low"
|
||||
})
|
||||
|
||||
def __init__(self, component, name, category=None):
|
||||
# TODO: make vid mandatry once migration is done
|
||||
def __init__(self, component, name, category=None, vid=None):
|
||||
self.vid = vid
|
||||
self.component = component
|
||||
self.category = category
|
||||
self.name = name
|
||||
self.evidence = ""
|
||||
self.role = "Node"
|
||||
|
||||
def get_vid(self):
|
||||
return self.vid
|
||||
|
||||
def get_category(self):
|
||||
if self.category:
|
||||
return self.category.name
|
||||
@@ -156,7 +161,7 @@ class ReportDispatched(Event):
|
||||
class K8sVersionDisclosure(Vulnerability, Event):
|
||||
"""The kubernetes version could be obtained from the {} endpoint """
|
||||
def __init__(self, version, from_endpoint, extra_info=""):
|
||||
Vulnerability.__init__(self, KubernetesCluster, "K8s Version Disclosure", category=InformationDisclosure)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "K8s Version Disclosure", category=InformationDisclosure, vid="KHV002")
|
||||
self.version = version
|
||||
self.from_endpoint = from_endpoint
|
||||
self.extra_info = extra_info
|
||||
|
||||
@@ -42,7 +42,7 @@ class RunningAsPodEvent(Event):
|
||||
class AzureMetadataApi(Vulnerability, Event):
|
||||
"""Access to the Azure Metadata API exposes information about the machines associated with the cluster"""
|
||||
def __init__(self, cidr):
|
||||
Vulnerability.__init__(self, Azure, "Azure Metadata Exposure", category=InformationDisclosure)
|
||||
Vulnerability.__init__(self, Azure, "Azure Metadata Exposure", category=InformationDisclosure, vid="KHV003")
|
||||
self.cidr = cidr
|
||||
self.evidence = "cidr: {}".format(cidr)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from ...core.types import Hunter, ActiveHunter, IdentityTheft, Azure
|
||||
class AzureSpnExposure(Vulnerability, Event):
|
||||
"""The SPN is exposed, potentially allowing an attacker to gain access to the Azure subscription"""
|
||||
def __init__(self, container):
|
||||
Vulnerability.__init__(self, Azure, "Azure SPN Exposure", category=IdentityTheft)
|
||||
Vulnerability.__init__(self, Azure, "Azure SPN Exposure", category=IdentityTheft, vid="KHV004")
|
||||
self.container = container
|
||||
|
||||
@handler.subscribe(ExposedRunHandler, predicate=lambda x: x.cloud=="Azure")
|
||||
|
||||
@@ -23,7 +23,7 @@ class ServerApiAccess(Vulnerability, Event):
|
||||
else:
|
||||
name = "Unauthenticated access to API"
|
||||
category = UnauthenticatedAccess
|
||||
Vulnerability.__init__(self, KubernetesCluster, name=name, category=category)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name=name, category=category, vid="KHV005")
|
||||
self.evidence = evidence
|
||||
|
||||
class ServerApiHTTPAccess(Vulnerability, Event):
|
||||
@@ -32,7 +32,7 @@ class ServerApiHTTPAccess(Vulnerability, Event):
|
||||
def __init__(self, evidence):
|
||||
name = "Insecure (HTTP) access to API"
|
||||
category = UnauthenticatedAccess
|
||||
Vulnerability.__init__(self, KubernetesCluster, name=name, category=category)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name=name, category=category, vid="KHV006")
|
||||
self.evidence = evidence
|
||||
|
||||
class ApiInfoDisclosure(Vulnerability, Event):
|
||||
|
||||
@@ -11,7 +11,7 @@ from scapy.all import ARP, IP, ICMP, Ether, sr1, srp
|
||||
class PossibleArpSpoofing(Vulnerability, Event):
|
||||
"""A malicous 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=IdentityTheft)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Possible Arp Spoof", category=IdentityTheft,vid="KHV020")
|
||||
|
||||
@handler.subscribe(CapNetRawEnabled)
|
||||
class ArpSpoofHunter(ActiveHunter):
|
||||
|
||||
@@ -14,7 +14,7 @@ email_pattern = re.compile(r"([a-z0-9]+@[a-z0-9]+\.[a-z0-9]+)")
|
||||
class CertificateEmail(Vulnerability, Event):
|
||||
"""Certificate includes an email address"""
|
||||
def __init__(self, email):
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Certificate Includes Email Address", category=InformationDisclosure)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Certificate Includes Email Address", category=InformationDisclosure,khv="KHV021")
|
||||
self.email = email
|
||||
self.evidence = "email: {}".format(self.email)
|
||||
|
||||
|
||||
@@ -16,31 +16,31 @@ from packaging import version
|
||||
class ServerApiVersionEndPointAccessPE(Vulnerability, Event):
|
||||
"""Node is vulnerable to critical CVE-2018-1002105"""
|
||||
def __init__(self, evidence):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Critical Privilege Escalation CVE", category=PrivilegeEscalation)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Critical Privilege Escalation CVE", category=PrivilegeEscalation, vid="KHV022")
|
||||
self.evidence = evidence
|
||||
|
||||
class ServerApiVersionEndPointAccessDos(Vulnerability, Event):
|
||||
"""Node not patched for CVE-2019-1002100. Depending on your RBAC settings, a crafted json-patch could cause a Denial of Service."""
|
||||
def __init__(self, evidence):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Denial of Service to Kubernetes API Server", category=DenialOfService)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Denial of Service to Kubernetes API Server", category=DenialOfService, vid="KHV023")
|
||||
self.evidence = evidence
|
||||
|
||||
class PingFloodHttp2Implementation(Vulnerability, Event):
|
||||
"""Node not patched for CVE-2019-9512. an attacker could cause a Denial of Service by sending specially crafted HTTP requests."""
|
||||
def __init__(self, evidence):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Possible Ping Flood Attack", category=DenialOfService)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Possible Ping Flood Attack", category=DenialOfService, vid="KHV024")
|
||||
self.evidence = evidence
|
||||
|
||||
class ResetFloodHttp2Implementation(Vulnerability, Event):
|
||||
"""Node not patched for CVE-2019-9514. an attacker could cause a Denial of Service by sending specially crafted HTTP requests."""
|
||||
def __init__(self, evidence):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Possible Reset Flood Attack", category=DenialOfService)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Possible Reset Flood Attack", category=DenialOfService, vid="KHV025")
|
||||
self.evidence = evidence
|
||||
|
||||
class ServerApiClusterScopedResourcesAccess(Vulnerability, Event):
|
||||
"""Api Server not patched for CVE-2019-11247. API server allows access to custom resources via wrong scope"""
|
||||
def __init__(self, evidence):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Arbitrary Access To Cluster Scoped Resources", category=PrivilegeEscalation)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Arbitrary Access To Cluster Scoped Resources", category=PrivilegeEscalation, vid="KHV026")
|
||||
self.evidence = evidence
|
||||
|
||||
|
||||
@@ -49,14 +49,14 @@ class ServerApiClusterScopedResourcesAccess(Vulnerability, Event):
|
||||
class IncompleteFixToKubectlCpVulnerability(Vulnerability, Event):
|
||||
"""The kubectl client is vulnerable to CVE-2019-11246, an attacker could potentially execute arbitrary code on the client's machine"""
|
||||
def __init__(self, binary_version):
|
||||
Vulnerability.__init__(self, KubectlClient, "Kubectl Vulnerable To CVE-2019-11246", category=RemoteCodeExec)
|
||||
Vulnerability.__init__(self, KubectlClient, "Kubectl Vulnerable To CVE-2019-11246", category=RemoteCodeExec, vid="KHV027")
|
||||
self.binary_version = binary_version
|
||||
self.evidence = "kubectl version: {}".format(self.binary_version)
|
||||
|
||||
class KubectlCpVulnerability(Vulnerability, Event):
|
||||
"""The kubectl client is vulnerable to CVE-2019-1002101, an attacker could potentially execute arbitrary code on the client's machine"""
|
||||
def __init__(self, binary_version):
|
||||
Vulnerability.__init__(self, KubectlClient, "Kubectl Vulnerable To CVE-2019-1002101", category=RemoteCodeExec)
|
||||
Vulnerability.__init__(self, KubectlClient, "Kubectl Vulnerable To CVE-2019-1002101", category=RemoteCodeExec, vid="KHV028")
|
||||
self.binary_version = binary_version
|
||||
self.evidence = "kubectl version: {}".format(self.binary_version)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from ..discovery.dashboard import KubeDashboardEvent
|
||||
class DashboardExposed(Vulnerability, Event):
|
||||
"""All oprations on the cluster are exposed"""
|
||||
def __init__(self, nodes):
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Dashboard Exposed", category=RemoteCodeExec)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Dashboard Exposed", category=RemoteCodeExec, vid="KHV029")
|
||||
self.evidence = "nodes: {}".format(' '.join(nodes)) if nodes else None
|
||||
|
||||
@handler.subscribe(KubeDashboardEvent)
|
||||
|
||||
@@ -13,7 +13,7 @@ class EtcdRemoteWriteAccessEvent(Vulnerability, Event):
|
||||
"""Remote write access might grant an attacker full control over the kubernetes cluster"""
|
||||
|
||||
def __init__(self, write_res):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote Write Access Event", category=RemoteCodeExec)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote Write Access Event", category=RemoteCodeExec, vid="KHV031")
|
||||
self.evidence = write_res
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class EtcdRemoteReadAccessEvent(Vulnerability, Event):
|
||||
"""Remote read access might expose to an attacker cluster's possible exploits, secrets and more."""
|
||||
|
||||
def __init__(self, keys):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote Read Access Event", category=AccessRisk)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote Read Access Event", category=AccessRisk, vid="KHV032")
|
||||
self.evidence = keys
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class EtcdRemoteVersionDisclosureEvent(Vulnerability, Event):
|
||||
def __init__(self, version):
|
||||
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote version disclosure",
|
||||
category=InformationDisclosure)
|
||||
category=InformationDisclosure, vid="KHV033")
|
||||
self.evidence = version
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class EtcdAccessEnabledWithoutAuthEvent(Vulnerability, Event):
|
||||
|
||||
def __init__(self, version):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd is accessible using insecure connection (HTTP)",
|
||||
category=UnauthenticatedAccess)
|
||||
category=UnauthenticatedAccess, vid="KHV034")
|
||||
self.evidence = version
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class ExposedPodsHandler(Vulnerability, Event):
|
||||
class AnonymousAuthEnabled(Vulnerability, Event):
|
||||
"""The kubelet is misconfigured, potentially allowing secure access to all requests on the kubelet, without the need to authenticate"""
|
||||
def __init__(self):
|
||||
Vulnerability.__init__(self, Kubelet, "Anonymous Authentication", category=RemoteCodeExec)
|
||||
Vulnerability.__init__(self, Kubelet, "Anonymous Authentication", category=RemoteCodeExec, vid="KHV036")
|
||||
|
||||
|
||||
class ExposedContainerLogsHandler(Vulnerability, Event):
|
||||
@@ -78,7 +78,7 @@ class ExposedHealthzHandler(Vulnerability, Event):
|
||||
class PrivilegedContainers(Vulnerability, Event):
|
||||
"""A Privileged container exist on a node. could expose the node/cluster to unwanted root operations"""
|
||||
def __init__(self, containers):
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Privileged Container", category=AccessRisk)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Privileged Container", category=AccessRisk, vid="KHV044")
|
||||
self.containers = containers
|
||||
self.evidence = "pod: {}, container: {}, count: {}".format(containers[0][0], containers[0][1], len(containers))
|
||||
|
||||
@@ -86,13 +86,13 @@ class PrivilegedContainers(Vulnerability, Event):
|
||||
class ExposedSystemLogs(Vulnerability, Event):
|
||||
"""System logs are exposed from the /logs endpoint on the kubelet"""
|
||||
def __init__(self):
|
||||
Vulnerability.__init__(self, Kubelet, "Exposed System Logs", category=InformationDisclosure)
|
||||
Vulnerability.__init__(self, Kubelet, "Exposed System Logs", category=InformationDisclosure, vid="KHV045")
|
||||
|
||||
|
||||
class ExposedKubeletCmdline(Vulnerability, Event):
|
||||
"""Commandline flags that were passed to the kubelet can be obtained from the pprof endpoints"""
|
||||
def __init__(self, cmdline):
|
||||
Vulnerability.__init__(self, Kubelet, "Exposed Kubelet Cmdline", category=InformationDisclosure)
|
||||
Vulnerability.__init__(self, Kubelet, "Exposed Kubelet Cmdline", category=InformationDisclosure, vid="KHV046")
|
||||
self.cmdline = cmdline
|
||||
self.evidence = "cmdline: {}".format(self.cmdline)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from .kubelet import ExposedPodsHandler, ExposedRunHandler, KubeletHandlers
|
||||
class WriteMountToVarLog(Vulnerability, Event):
|
||||
"""A pod can create symlinks in the /var/log directory on the host, which can lead to a root directory traveral"""
|
||||
def __init__(self, pods):
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Pod With Mount To /var/log", category=PrivilegeEscalation)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Pod With Mount To /var/log", category=PrivilegeEscalation, vid="KHV047")
|
||||
self.pods = pods
|
||||
self.evidence = "pods: {}".format(', '.join((pod["metadata"]["name"] for pod in self.pods)))
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ from ..discovery.proxy import KubeProxyEvent
|
||||
class KubeProxyExposed(Vulnerability, Event):
|
||||
"""All oprations on the cluster are exposed"""
|
||||
def __init__(self):
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Proxy Exposed", category=InformationDisclosure)
|
||||
Vulnerability.__init__(self, KubernetesCluster, "Proxy Exposed", category=InformationDisclosure, vid="KHV049")
|
||||
|
||||
class Service(Enum):
|
||||
DASHBOARD = "kubernetes-dashboard"
|
||||
|
||||
@@ -16,7 +16,7 @@ class ServiceAccountTokenAccess(Vulnerability, Event):
|
||||
|
||||
def __init__(self, evidence):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Read access to pod's service account token",
|
||||
category=AccessRisk)
|
||||
category=AccessRisk, vid="KHV050")
|
||||
self.evidence = evidence
|
||||
|
||||
class SecretsAccess(Vulnerability, Event):
|
||||
|
||||
@@ -26,6 +26,7 @@ class BaseReporter(object):
|
||||
def get_vulnerabilities(self):
|
||||
vulnerabilities_lock.acquire()
|
||||
vulnerabilities_data = [{"location": vuln.location(),
|
||||
"vid": vuln.get_vid(),
|
||||
"category": vuln.category.name,
|
||||
"severity": vuln.get_severity(),
|
||||
"vulnerability": vuln.get_name(),
|
||||
|
||||
@@ -8,6 +8,7 @@ from .base import BaseReporter
|
||||
|
||||
EVIDENCE_PREVIEW = 40
|
||||
MAX_TABLE_WIDTH = 20
|
||||
KB_LINK = "https://github.com/aquasecurity/kube-hunter/tree/master/docs/kb"
|
||||
|
||||
|
||||
class PlainReporter(BaseReporter):
|
||||
@@ -81,7 +82,7 @@ class PlainReporter(BaseReporter):
|
||||
return detected_services_ret
|
||||
|
||||
def vulns_table(self):
|
||||
column_names = ["Location", "Category", "Vulnerability", "Description", "Evidence"]
|
||||
column_names = ["ID", "Location", "Category", "Vulnerability", "Description", "Evidence"]
|
||||
vuln_table = PrettyTable(column_names, hrules=ALL)
|
||||
vuln_table.align = "l"
|
||||
vuln_table.max_width = MAX_TABLE_WIDTH
|
||||
@@ -92,12 +93,11 @@ class PlainReporter(BaseReporter):
|
||||
|
||||
vulnerabilities_lock.acquire()
|
||||
for vuln in vulnerabilities:
|
||||
row = [vuln.location(), vuln.category.name, vuln.get_name(), vuln.explain()]
|
||||
evidence = str(vuln.evidence)[:EVIDENCE_PREVIEW] + "..." if len(str(vuln.evidence)) > EVIDENCE_PREVIEW else str(vuln.evidence)
|
||||
row.append(evidence)
|
||||
row = [vuln.get_vid(), vuln.location(), vuln.category.name, vuln.get_name(), vuln.explain(), evidence]
|
||||
vuln_table.add_row(row)
|
||||
vulnerabilities_lock.release()
|
||||
return "\nVulnerabilities\n{}\n".format(vuln_table)
|
||||
return "\nVulnerabilities\nFor further information about a vulnerability, search its ID in: \n{}\n{}\n".format(KB_LINK, vuln_table)
|
||||
|
||||
def hunters_table(self):
|
||||
column_names = ["Name", "Description", "Vulnerabilities"]
|
||||
|
||||
Reference in New Issue
Block a user