In this universe of ever-changing landscapes and unlimited hackers, defenders are searching for a hero to help defend the Kubernetes universe. To paraphrase Nick Fury, we need to assemble a group of remarkable tools who can work together to fight battles the vulnerable apps can’t. In this blog post, we are going to assemble our own Avengers team using Cilium and Tetragon to defend the Damn Vulnerable Web Application (DVWA) against the unearthly invaders, rendering it almost unhackable. Tetragon + Cilium will provide process, file, HTTP, and network-based defenses to thwart the known evil OWASP’s top 10. DVWA is a web app that was intentionally designed to be vulnerable to OWASP’s top 10 as a training resource. Lastly, I will end with a director’s commentary on my opinions to integrate Cilium + Tetragon in an enterprise and some ideas to close the gap between developers and security.
DISCLAIMERS
DISCLAIMERS
Goals
- Install/Setup k3s
- Install Cilium on k3s
- Install Tetragon on k3s
- Deploy DVWA on k3s
- Apply Cilium and Tetragon policies to mitigate DVWA vulnerabilities
Background
What is eBPF?
eBPF is a revolutionary technology with origins in the Linux kernel that can run sandboxed programs in a privileged context such as the operating system kernel. It is used to safely and efficiently extend the capabilities of the kernel without requiring to change kernel source code or load kernel modules.
Historically, the operating system has always been an ideal place to implement observability, security, and networking functionality due to the kernel’s privileged ability to oversee and control the entire system. At the same time, an operating system kernel is hard to evolve due to its central role and high requirement towards stability and security. The rate of innovation at the operating system level has thus traditionally been lower compared to functionality implemented outside of the operating system. Below is a list of resources I recommend to learn more about eBPF.
- Youtube: Tutorial: Getting Started with eBPF – Liz Rice, Isovalent
- PDF Book: O’Reilly – Learning eBPF
- Detection and Blocking with BPF via YAML
- Isovalent FREE Training: Getting started with eBPF
- Isovalent FREE Training: Getting started with Tetragon
- Isovalent FREE Training: Getting started with Cilium
- Blog post: The eBPF – 2
What is DVWA?
Damn Vulnerable Web Application (DVWA) is a PHP/MySQL web application that is damn vulnerable. Its main goal is to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and to aid both students & teachers to learn about web application security in a controlled classroom environment.
The aim of DVWA is to practice some of the most common web vulnerabilities, with various levels of difficulty, with a simple straightforward interface. Please note, there are both documented and undocumented vulnerabilities with this software. This is intentional. You are encouraged to try and discover as many issues as possible.
What is Kubernetes?
Kubernetes (k8s) is an open-source container-orchestration system for automating application deployment, scaling, and management. It was originally designed by Google, and is now maintained by the Cloud Native Computing Foundation. It aims to provide a “platform for automating deployment, scaling, and operations of application containers across clusters of hosts”. It works with a range of container tools, including Docker. Many cloud services offer a Kubernetes-based platform or infrastructure as a service (PaaS or IaaS) on which Kubernetes can be deployed as a platform-providing service. Many vendors also provide their own branded Kubernetes distributions.
What is Cilium?
Cilium is an open source, cloud native solution for providing, securing, and observing network connectivity between workloads, fueled by the revolutionary Kernel technology eBPF
What is Teragon?
Tetragon is a flexible Kubernetes-aware security observability and runtime enforcement tool that applies policy and filtering directly with eBPF, allowing for reduced observation overhead, tracking of any process, and real-time enforcement of policies.
Install/Setup k3s, Cilium, Tetragon, Kubectl
Install/Setup k3s
- ssh to Ubuntu VM
sudo su
- Curl automated script to install k3s:
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC='--flannel-backend=none --disable-network-policy' sh -
- By default K3s install includes flannel as the CNI and enables certain network policies, per the documentation we need to disable those
- Copy
/etc/rancher/k3s/k3s.yaml
to local machine to access Kubernetes (k8s) viakubectl
- Allow access to k8s API via UFW:
ufw allow 6443/tcp
- Allow k8s network communication:
ufw allow from 10.42.0.0/16
- Allow k8s network communication:
ufw allow from 10.43.0.0/16
exit
Setup kubectl
- Install Kubectl on local machine
- Pull kubectl config from k3s:
scp <username>@<k3s IP addr>:/etc/rancher/k3s/k3s.yaml ~/.kube/config
- Replace localhost IP addr:
cat /etc/rancher/k3s/k3s.yaml | sed 's#127.0.0.1#<k3s IP addr>#g'
- Verify config is working:
kubectl get pods -n kube-system
Install/Setup MetalLB
git clone https://github.com/CptOfEvilMinions/BlogProjects
cd BlogProjects/k8s-dvwa-cilium
- Install MetalLB:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml
vim conf/k3s/metallb-ip-pool.yaml
and set IP range
--- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: default namespace: metallb-system spec: addresses: - <start IP addr>-<end IP addr> autoAssign: true
kubectl apply -f conf/k3s/metallb-ip-pool.yaml
Install/Setup Cilium
- Install Cilium via Helm:
cilium install --version 1.15.5 --set=ipam.operator.clusterPoolIPv4PodCIDRList="10.42.0.0/16"
- Install Cilium CLI on your local machine
- Enable Cilium Hubble:
cilium hubble enable --ui
- Wait until everything turns green:
cilium status --wait
Install/Setup Tetragon on k3s
- Install Tetragon with Helm:
helm install tetragon cilium/tetragon -n kube-system
- Install Tetragon CLI
- Create a tunnel to tetragon service:
kubectl port-forward -n kube-system ds/tetragon 54321:54321
- Get status:
tetra status
Deploy DVWA to k3s with Helm
cd ../k8s-dvwa
- Create namespace:
kubectl create ns dvwa
- Generate passwords for MySQL:
kubectl create secret generic -n dvwa mysql --from-literal=mysql-root-password=$(openssl rand -hex 20) --from-literal=mysql-replication-password=$(openssl rand -hex 20) --from-literal=mysql-password=$(openssl rand -hex 20)
- Deploy DVWA:
helm install dvwa . -n dvwa -f values.yaml
- Create k8s load balancer:
kubectl apply -f conf/dvwa/load-balancer.yaml
- Wait two minutes for MySQL to start and initialize
- Get IP addr of k8s load balancer:
kubectl get svc -n dvwa dvwa-load-balancer-external-access
- Open browser to
http://<DVWA IP addr>/login.php
- Login
- Username:
admin
- Password:
password
- Username:
- Select “Create / Reset Database”
- Re-login
Command injection
The optimal solution would be to have this capability rewritten using a PHP library to perform this action. However, a quick Google search didn’t yield any libraries to support this functionality without calling the ping command. Assuming the business wants to keep the capability as is, we can use Tetragon and Cilium to mitigate this vulnerability. Tetragon provides the ability to monitor and block processes, and Cilium provides the ability to monitor and block network connections. We will also assume for this exercise that the web app is used internally by engineers to test if an internal or external machine is alive via an ICMP ping request.
Cilium
--- apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: dvwa-allow-external-ingress namespace: dvwa spec: endpointSelector: matchLabels: app.kubernetes.io/instance: dvwa app.kubernetes.io/name: dvwa ingress: - fromEntities: - world ... ... ... egress: # Allow ICMP egress # https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml # ICMP type 8 is Echo - icmps: - fields: - type: 8 family: IPv4 - type: 8 family: IPv6
To block this malicious activity from the network perspective we are going to use a CiliumNetworkPolicy
to restrict egress from the DVWA web app. Cilium based network policies will default to blocking if a rule is not specified. Our policy has a rule to specifically allow outbound (egress) ICMP requests of type 8 which are PING echo requests to ask if a host is alive. This will prevent the following attacker vector but not limited to: CURLing a random HTTP endpoint for a malicious script to execute or write to disk.
- Browse to
http://<DVWA IP addr>/vulnerabilities/exec/#
- Enter
8.8.8.8;curl http://ifconfig.me
into “Enter an IP address” - Select “Submit”
kubectl apply -f conf/tetragon/networkpolicy.yaml
- Enter
8.8.8.8;curl http://ifconfig.me
into “Enter an IP address” - Select “Submit”
- Open a new terminal tab
- Open Hubble via command line:
cilium hubble ui
- Select the dvwa namespace
Validating Cilium policy
kubectl exec --stdin=true --tty=true -n dvwa svc/dvwa -- bash
ping 8.8.8.8
curl http://ifconfig.me
Tetragon
--- apiVersion: cilium.io/v1alpha1 kind: TracingPolicyNamespaced metadata: name: "command-line-injection" namespace: "dvwa" spec: podSelector: matchLabels: app.kubernetes.io/instance: dvwa app.kubernetes.io/name: dvwa kprobes: - call: "sys_execve" syscall: true return: true args: - index: 0 type: "string" # file path returnArg: index: 0 type: "int" returnArgAction: "Post" selectors: - matchPIDs: - operator: In followForks: true isNamespacePID: true values: - 1 # Apache root matchArgs: - index: 0 operator: "NotEqual" values: - "/usr/bin/ping" - "/bin/sh" matchActions: - action: Override argError: -1 - action: Post
To block the actual vulnerability, which is command line injection, we are going to use a Tetragon TracingPolicy
with pod label selectors set to the DVWA pod. The tracing policy above will monitor all syscalls using the execve method. The execve method can take in several arguments, but we are going to monitor the file argument, which contains a file path to an executable. Additionally, we specify that we want to override the return argument by using returnArg
. If execve is called successfully, it will simply return an int set to zero for success. To prevent the syscall, we are going to override the return value by returning a non-zero value if the syscall matches our criteria. Our criteria is to monitor all execve syscalls performed by the PID of 1, which in our case is Apache and any child processes spawned by it (followForks
). If Apache does make an execve syscall but the first argument doesn’t match anything in the following list ["/usr/bin/ping", "/bin/sh"]
it will return a non-zero. The non-zero return will indicate to the application making the call that the operation was unsuccessful, thus preventing command line injection.
- Browse to
http://<DVWA IP addr>/vulnerabilities/exec/#
- Enter
8.8.8.8;whoami
into “Enter an IP address” - Select “Submit”
kubectl apply -f conf/tetragon/command-line-injection.yaml
- Enter
8.8.8.8;whoami
into “Enter an IP address” - Select “Submit”
Validating Tetragon policy
We are going to prove that Tetragon is actually intercepting the syscall to prevent execution and not just returning an error. The test below uses the command cp
, which is not on the approved list. After the command has been submitted, we are going to look for the existence of /tmp/passwd
.
- Browse to
http://<DVWA IP addr>/vulnerabilities/exec/#
- Enter
8.8.8.8;cp /etc/passwd /tmp/passwd
into “Enter an IP address” kubectl exec --stdin=true --tty=true -n dvwa svc/dvwa -- bash
File Inclusion
- Youtube: Restrict Access to Secure Files with Tetragon | eBPF Runtime Enforcement
- File Monitoring with eBPF and Tetragon (Part 1)
Tetragon
--- apiVersion: cilium.io/v1alpha1 kind: TracingPolicyNamespaced metadata: name: "block-non-var-www-file-access" namespace: "dvwa" spec: podSelector: matchLabels: app.kubernetes.io/instance: dvwa app.kubernetes.io/name: dvwa kprobes: - call: "security_file_open" syscall: false return: true args: - index: 0 type: "file" # (struct file *) used for getting the path returnArg: index: 0 type: "int" returnArgAction: "Post" selectors: - matchPIDs: - operator: In followForks: true isNamespacePID: true values: - 1 # Apache root # - matchBinaries: # - operator: "In" # values: # - "/usr/sbin/apache2" matchArgs: - index: 0 operator: "NotPrefix" values: - "/var/www/html/" - "/tmp/sess_" matchActions: - action: Override argError: -2 - action: Post
The DVWA web app file inclusion vulnerability allows the web app to read any file on disk, including files such as /etc/passwd
. The web app only needs to read files located in /var/www/html/
and sessions stored at /tmp/sess_*
for normal operations. Therefore, we will use a Tetragon TracingPolicyNamespaced
to monitor security_file_permission
calls. Per the Tetragon documentation, “hook into the security_file_permission
function which is called on every file access.” The policy we will apply will allow PID 1 (Apache) to access files located in /var/www/html/
or /tmp/sess_*
. If a file open request is made by Apache for a file outside of these locations, Tetragon will override the return arg for security_file_permission
by returning a -2
, which means there was error opening the file.
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/fi/?page=../../../../../../etc/passwd
kubectl apply -f conf/tetragon/file-inclusion-blocking.yaml
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/fi/?page=../../../../../../etc/passwd
Cilium
As we can see in the screenshots above the Tetragon policy works as expected at blocking Apache from reading /etc/passwd
. While the above will prevent the web vulnerability in the web app, we can also go one step further with a control-in-depth approach. First, revert the Tetragon policy and apply a CiliumNetworkPolicy
to enforce HTTP-based rules on requests made via the Cilium load balancer. The HTTP rule below only allows GET requests matching the URL path regex pattern (Regex101 screenshot). As a side note, I have generated Regex101 links for each regex created for the HTTP rules. Regex101 is a great tool to build regexes and will help you take these example rules to implement in your own environment.
########## File inclusion ########## # Good: /vulnerabilities/fi/?page=file1.php # Bad: /vulnerabilities/fi/?page=../../../../../../etc/passwd # Bad: /vulnerabilities/fi/?page=/etc/passwd # Regex101: https://regex101.com/r/aM1H9R/1 - method: "GET" path: /vulnerabilities\/fi\/\?page=\w+\.php$
- Delete the Tetragon policy:
kubectl delete -f conf/tetragon/file-inclusion-blocking.yaml
- Apply network policy:
kubectl apply -f conf/cilium/dvwa-networkpolicy.yaml
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/fi/?page=../../../../../../etc/passwd
File upload
The DVWA web app file upload feature allows users to upload files to this web app. This capability is not inherently a vulnerability, but it can allow other vulnerabilities to be exploited. For example, an attacker could upload a PHP web shell or use the upload feature to host malicious code. Hosting malicious code allows for further attacks such as bypassing CSRF and CSP controls. We can use Tetragon to prevent file upload based on file attributes and Cilium can enforce specific file types. Below, I am going to demonstrate the Tetragon and Cilium policies but also demonstrate how all the policies applied to this point neuter a common web shell.
Tetragon
--- apiVersion: cilium.io/v1alpha1 kind: TracingPolicyNamespaced metadata: name: "block-uploading-files-with-php-extension" namespace: "dvwa" spec: podSelector: matchLabels: app.kubernetes.io/instance: dvwa app.kubernetes.io/name: dvwa kprobes: - call: "do_renameat2" syscall: false return: true args: - index: 0 type: int - index: 1 type: "filename" # old path - index: 2 type: int - index: 3 type: "filename" # new path returnArg: index: 0 type: "int" returnArgAction: "Post" selectors: - matchPIDs: - operator: In followForks: true isNamespacePID: true values: - 1 - matchArgs: - index: 1 operator: "Prefix" values: - "../../hackable/uploads" - index: 1 operator: "Postfix" values: - ".php" - matchActions: - action: Override argError: -1 - action: Post
It should be noted that this tracing policy can easily be bypassed with ease. The intention is to demonstrate the capabilities of Tetragon in this blog post. Additionally, this technique could be used in an incident scenario as a temporary patch until better controls can be implemented. When an upload is performed via this web app, the contents of the upload are written to /tmp
and then moved to the appropriate location. It should be noted that really a move is actually just renaming the file. The rename syscall takes in two parameters which are the old/current file path and the new filename/new file path. Additionally, the reason we are specifying a relative path for the new is because the context of the web app is being executed from the following directory location: /var/www/html/vulnerabilities/upload
. Thus, the app provides a relative path to move the file to and the path is not resolved.
The policy above will monitor all rename syscalls performed by Apache (PID 1). If the new file location is the relative path for file uploads and the new file name ends with .php
, we should return an error code. This will terminate the rename/move call to stop the temporary file from being placed in the proper location for file uploads. While this isn’t perfect because it still wastes disk space, this was a fun journey of tracking down how the web app works.
- Browse to
http://<DVWA IP addr>/vulnerabilities/uploads
- Select a PHP file
- Select “Upload”
kubectl apply -f conf/tetragon/file-uploads.yaml
Cilium
At the Cilium level we can enforce that the file uploads set the Content-Type
header to an approved file type. Since this field is controlled by the user, it can be modified to an approved value.
########## File upload ########## # Allow GET requests to the webpage - method: GET path: "/vulnerabilities/upload$" # Allow JPEG uploads - method: POST path: "/vulnerabilities/upload$" headers: - 'Content-Type: image/jpeg' # Allow PNG uploads - method: POST path: "/vulnerabilities/upload$" headers: - 'Content-Type: image/png'
- Browse to
http://<DVWA IP addr>/vulnerabilities/uploads
- Select a PHP file
- Select “Upload”
PHP web shell
In this section, we are going to demonstrate using web shells as an attack vector. One type of web shells is some malicious PHP code that will create a reverse shell back to an attacker-owned machine. We can mitigate this attack path using the CiliumNetworkPolicy
from the “Command injection” section above to restrict egress from the DVWA web app. Another form of a web shell is one that allows an attacker to run malicious actions using a web shell like C99Shell-PHP8. Again, if we apply the Tetragon TracingPolicy
from the “Command injection” section we can prevent malicious commands from being executed. If we apply the Tetragon TracingPolicy
to monitor security_file_permission
from the “File inclusion” section we can prevent the web shell from reading files outside the defined scope. Unfortunately, one downfall is an attacker could still access uploads from other users because it’s within the allowed scope. The goal here was to demonstrate that a small amount of well defined policies can prevent a multitude of vulnerabilities and attack vectors. Unfortunately, we were not able to prevent the use of the C99 webshell but it is essentially neutered.
- Upload a web shell to the web app
- Browse to
http://<DVWA IP addr>/hackable/uploads/c99.php
- If we enter whoami into Command execute section
- Select “Execute”
- Select the home icon in top left
kubectl apply -f conf/tetragon/command-line-injection.yaml
- RE-run the same command
- Select the home icon in top left
- Use the folder browser to access
/etc/passwd
with the text editor - Select the home icon in top left
kubectl apply -f conf/tetragon/file-inclusion-blocking.yaml
- Unable to browse to
/etc/
SQL injection
This feature of the web app allows a user to look up other users by a user ID (uid). When a user submits the UID, it is added to the URL as a parameter that is then passed to the MySQL engine. Therefore, we can implement a Cilium Network Policy that enforces a regex and anything that doesn’t match it will be denied. This same approach can be applied to the SQL injection (blind) example as well.
########## SQL injection ########## - method: "GET" path: /vulnerabilities/(sqli|sqli_blind)/\?id=\d+&Submit=Submit(#)?$
It should be noted that I spent an extensive amount of time trying to determine if there was a syscall I could hook to prevent SQL injection within the kernel. The only information I could find was using user statically defined tracing (USDT) to track MySQL queries. However, I think this analysis is generated AFTER the query has been executed because it generates stats such as how long each query takes to execute. Therefore, it’s likely this method can’t be used to prevent SQL injection before the query is executed. I also found that uprobe may be able to could hook a function call within an application but there wasn’t enough information to implement this.
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/sqli/?id=1&Submit=Submit#
- Enter
1' OR '1'='1'#
to text box and hit “Submit” - Copy the URL which encoded the payload
- Apply network policy:
kubectl apply -f conf/cilium/dvwa-networkpolicy.yaml
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/sqli/?id=1'+OR+'1'%3D'1'%23&Submit=Submit#
XSS
Reflected
This feature of the web app allows the user to enter their name and have it be reflected back to them. The name submitted is appended to the URL as a parameter. For our use case, we are going to assume that a valid name would be someone’s first name that ONLY contains alphabetic characters. Therefore, we will use a Cilium Network policy to define a valid regex for the URL to prevent this vulnerability. The policy allows HTTP GET
requests and the URL parameter name
must specify a word (alphabetic characters).
########## XSS ########## # Good: /vulnerabilities/xss_r/?name=bob# # Bad: /vulnerabilities/xss_r/?name=<script>alert("xss")<%2Fscript># # Regex101: https://regex101.com/r/OT3gFy/1 - method: "GET" path: /vulnerabilities\/xss_r\/\?name=\w+(#)?$
- Browse to
http://<DVWA IP addr>/vulnerabilities/xss_r/
- Enter
<script>alert("xss")</script>
into the name input - Select “Submit”
- Copy the encoded URL
kubectl apply -f conf/cilium/networkpolicy.yaml
- RE-run the above
DOM
This feature of the web app allows the user to select a preferred language. The language selected is submitted by appending the selection to the URL as a parameter. For our use case, we are going to assume that a valid language would be a single word containing only alphabetic characters. Therefore, we will use a Cilium Network policy to define a valid regex for the URL to prevent this vulnerability. The policy allows HTTP GET
requests and the URL parameter default
must specify a word (alphabet characters).
# Good: /vulnerabilities/xss_d/?default=English # Bad: /vulnerabilities/xss_d/?default=<script>alert("xss")<%2Fscript># # Regex101: https://regex101.com/r/TEVesk/1 - method: "GET" path: /vulnerabilities\/xss_d\/\?default=\w+(#)?$
- Browse to
http://<DVWA IP addr>/vulnerabilities/xss_d/
- Select a language from the drop down menu and select “Submit”
- Copy the URL
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/xss_d/?default=<script>alert(1)</script>
kubectl apply -f conf/cilium/networkpolicy.yaml
- RE-run the above, we can see that we get access denied because the URL doesn’t match regex.
Stored
This feature of the web app attempts to simulate a guestbook. Like a guestbook, the web app allows the user to digitally sign by providing their name and a custom message as input. When this information is submitted, it’s stored by the application to keep a record of guests. The app reflects the user’s payload back to the user upon submission. A more typical example is a user web forum that allows users to have conversations by submitting comments. If the web app is not sanitizing input from users and is not wrapping input from user’s when rendering it can lead to exploitation. Since the malicious payload is submitted via the HTTP body, this is not something Cilium can inspect and thus we can’t prevent it.
Open HTTP Redirect
An open HTTP redirect attack occurs when a web application allows an external user to specify a URL as a parameter in a redirect link. This redirect link can be used to transfer the user to the malicious link. The term “open” in this context means that the redirection is not restricted to a specific domain or a set of trusted destinations. Below we specify the re-direct URL to https://github.com
which the browser happily redirects too. To prevent a malicious redirect we are going to use a CiliumNetworkPolicy
to restrict valid URLs. DVWA provides redirects to itself but we are going to expand this capability to allow redirects to auth portals like Okta.
# Allow DNS - toEndpoints: - matchLabels: "k8s:io.kubernetes.pod.namespace": kube-system "k8s:k8s-app": kube-dns toPorts: - ports: - port: "53" protocol: UDP rules: dns: - matchPattern: '*.dvwa.svc.cluster.local'
- Make the following GET request:
http://<DVWA IP addr>/vulnerabilities/open_redirect/source/low.php?redirect=https://github.com?id=1
kubectl apply -f conf/cilium/networkpolicy.yaml
Make the following GET request: http://<DVWA IP addr>/vulnerabilities/open_redirect/source/low.php?redirect=https://github.com?id=1
Make the following GET request: http://<DVWA IP addr>/vulnerabilities/open_redirect/source/low.php?redirect=https://dev-123456.okta.com?id=1
Brute forcing
The DVWA web app is susceptible to a brute force attack to enumerate valid username and password combinations. To combat brute force attacks, one mitigation is to implement rate limiting on API endpoints such as the /login
endpoint. For example, if a user has ten consecutive failed logins (401 Unauthorized) within a ten minute period then, that IP address should be temporarily blocked for an hour. While this won’t eliminate the brute force vulnerability entirely, it significantly increases the amount of time needed to perform this attack. Under the hood, Cilium uses Envoy to implement the load balancing and HTTP rule capabilities. Cilium also supports a custom Envoy config that uses Envoy extensions, such as the built-in rate limiting extension. Configuring Envoy to perform rate limiting is outside the scope of this blog post, but it is doable. Below I have listed some resources if you want to implement this.
- Cilium: L7 Traffic Shifting
- Youtube: Envoy + Rate Limiting
- SRE: Resiliency: Bolt on Rate Limiting using Envoy
- Using Hydra on Login pages with a right method: dvwa training
“The ALMOST”
We finally arrive at the vulnerabilities that we can’t prevent in this web app with Cilium or Tetragon: CSRF, Weak Session IDs, CSP, Javascript, and Authorisation Bypass. These specific vulnerabilities can only be remediated by fixing the logic of the web app.
Closing the gap between security and developers
This blog post demonstrates the power of Cilium and Tetragon to protect an enterprise if an application contains a vulnerability. However, there is still a gap between security and developers. To implement these controls, developers would need to learn Cilium and Tetragon to create policies. Additionally, every time the application is updated, changes will need to be made to ensure that the changes are not blocked.
In my opinion, Cilium and Tetragon policy generation could be streamlined by creating a tool like aa-easyprof
. AppArmor comes with a command line tool called aa-easyprof to generate profiles based on actions by an application. Cilium and Tetragon could use the observability data recorded by Hubble to generate profiles for developers. In theory, a developer could create or update an application and then push the changes to QA. Allow the application some time to bake. Once the bake period is complete, a profile is generated based on the events in Hubble for a human to review. Lastly, a tool that could ingest an API spec such as OpenAPIv3 and generate a Cilium network policy with strict HTTP rules. As seen above, having strict HTTP rules can prevent a vulnerability from being exploited.
Lessons learned
Web application security 101
I am a huge proponent if you don’t use your knowledge to keep it fresh, ya lose it. My current role nor my personal projects have been focused on web app security, so it was really nice to do a project to refresh all this knowledge for this problem space.
TracingPolicy vs. TracingPolicyNamespaced
The default documentation for policies is kind: TracingPolicy
which applies the policy to the ENTIRE HOST. For example when testing, I wrote a policy to prevent access to /etc/passwd
, not knowing it would block ALL requests including requests from the bare metal host. In one swift policy, I borked my entire test k8s instance because the bare-metal host needed access to this file to operate. So while I did secure my web app…. I also made the host unusable. My takeaway from this is that while Tetragon was created to target Kubernetes and containers, eBPF works at the kernel level. Thus a poorly written blocking policy will affect everything running on that kernel. Unless you need to prevent an action fleet-wide, I would limit the blast radius to specific pod namespaces.
Furthermore, even when using a TracingPolicyNamespaced
policy havoc can still ensue. This policy will affect ALL pods in the namespace. For example, when creating the command line injection policy, I put a block in place to prevent access to all binaries except ping
by Apache. Consequently, the MySQL pod was not able to start itself. In addition to using the right kind, I also recommend supplying podSelectors
with the appropriate labels to target specific pods.
Sigkill vs. blocking
Tetragon provides two methods to prevent a malicious action from being executed which are blocking and sigkill. With blocking we force Tetragon to override the return with an error typically by returning a non-zero int. Sigkill will terminate the process that is attempting to perform the malicious action. It should be noted that sigkill is the nuclear option. Imagine you have 10 users on your web app and one of those user’s is a bug bounty hunter; they could essentially kill the web app with their testing. Additionally, a malicious actor could also continuously trigger a policy with a malicious request that would kill the application, thus making it unreachable. Lastly, I recommend using the blocking action as the primary method to block a malicious action and only use sigkill when appropriate.
References
- Damn Vulnerable Web Application (DVWA): Command Injection
- Writeups for Damn Vulnerable Web Application (DVWA)
- How to create an AppArmor Profile
- Install K3s with Cilium single-node cluster on Debian
- Cilium Quick Installation
- BlogProjects/k8s-dvwa
- helm/cilium/tetragon
- helm/cilium/cilium
- How to install K3s Kubernetes on Ubuntu
- Quick-Start Guide
- syscall – sys_close
- MicroK8s Addon: Hostpath Storage
- syscall – dup
- syscall – clone
- Detection and Blocking with BPF via YAML
- Tetragon Demo Fileless
- syscall – execve
- Can sys_execve() still return with error after begin_new_exec() returns zero?
- syscall – execve
- Google Cloud Logging and Cloud Monitoring example with Tetragon
- The Difference Between fork(), vfork(), exec() and clone()
- Dockerhub – php:8-apache
- DVWA/Dockerfile
- syscall – write
- The eBPF – 2
- Quick Exploration of Tetragon — A Security Observability and Execution Tool Based on eBPF
- Tetragon – Documentation/Concepts/Tracing Policy/Selectors
- Tetragon – Documentation/Concepts/Tracing Policy/Hook points
- Tetragon – Documentation/Getting Started/Policy Enforcement
- Tetragon Observability Policies
- Policy Enforcement
- CptOfEvilMinions/BlogProjects/tree/main/k8s-dvwa
- Damn Vulnerable Web Application (DVWA): Command Injection
- Writeups for Damn Vulnerable Web Application (DVWA)
- SQL Injection Prevention Cheat Sheet
- Cilium/Overview of Network Policy/Layer 3 Examples
- Tetragone: A Lesson in Security Fundamentals
- File Monitoring with eBPF and Tetragon (Part 1)
- tetragon: Add support to override security_ functions #1609
- syscall – openat
- Using bcc-tools for anomaly detection, performance analysis, troubleshooting and observability of the Linux kernel and user-space applications
- BPF Compiler Collection (BCC)
- tools/filetop.py
- pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml
- Isovalent Enterprise for Tetragon: Deeper Host Network Observability with eBPF
- Exploring Tetragon – A Security Observability Tool for Kubernetes, Docker, and Linux
- helm/cilium/tetragon
- Tetragon – Documentation/Getting Started/Execution Monitoring/Execution Monitoring
- Layer 3 Examples
- 3-node K3S cluster with etcd and MetalLB on bare-metal systems
- Installation Using K3s
- Service Map & Hubble UI
- User Story 4 – Frontend Accepts World Ingress Traffic via TCP Only
- Exploring Network Policies with Cilium
- Mastering Kubernetes with Cilium: Empowering L7 Traffic Control
- Securing Your Kubernetes Cluster: Cilium and Network Policies
- DNS for Services and Pods
- Kubernetes Network Policies Using Cilium – Controlling Ingress/Egress from Namespaces
- examples/tracingpolicy/open_kill.yaml
- Tutorial: Cilium Network Policy in Practice (Part 2)
- How to hide your actions when every step is being monitored
- Mastering Web Security: Testing OWASP Top 10 with DVWA
- DVWA SQL INJECTION
- Understanding File Inclusion Attack using DVWA web application
- Strengthen your system with Tetragon’s eBPF-based Security Observability and Runtime Enforcement capabilities
- What Are Kubernetes Endpoints?
- DVWA Vulnerability: File Upload
- WhiteWinterWolf/wwwolf-php-webshell
- HolyOne/C99Shell-PHP8
- Dvwa File Upload Vulnerabilities
- Linux MySQL Slow Query Tracing with bcc/BPF
- Exploring Function Tracing with eBPF and Uprobes – Episode 1
- mysql_send_query
- Tracing and Profiling MySQL
- Hook points
- Cross Site Scripting(XSS) | DVWA(Damn Vulnerable Web Applications)
- DVWA CSP Bypass
- DVWA Javascript attacks
- DVWA Command Execution solutions (Low,Medium,High)
- k3s requirements
- renameat(2) – Linux man page
- fs/namei.c
- rename
- rename(2) — Linux manual page