Kubernetes NGINX WAF (Part 1) - Ingress Hardening with Mod_Security and OWASP CRS

How to increase the security of your Kubernetes ingress with a web application firewall (mod_security) and the OWASP Core Rule Set.

Kubernetes NGINX WAF (Part 1) - Ingress Hardening with Mod_Security and OWASP CRS

“Kubernetes Ingress with mod_security and OWASP” – We show what all this means in today’s blog post.

In today’s blog post, we’ll show you a way to keep malicious traffic off your Kubernetes cluster. We grab a topic from the technical magic box of the “Zero Trust” and immediately disenchant the technical jargon.

The goal is to setup Nginx Ingress and WAF properly in order to protect all web services
opensight.ch – roman hüsler
Image – Goal of this blog. A cyber security center for Kubernetes NGINX Controller WAF. Dashboard in Kibana

Mod_Security is an open source web application firewall (WAF) that is supported by various web servers (NGINX, Apache, IIS) and has existed since 2002. The OWASP organization provides a corresponding Core Rule Set (CRS) for the firewall, which keeps all kinds of malicious traffic out.

Terms

Kubernetes (also “K8s”) is an open source contrainducer orchestration engine originally developed by Google.

Here is an example of a simplified reference architecture, which is often found in a similar form – with deviations depending on the cloud provider. Incoming traffic is first routed via a load balancer (in our bare metal test cluster “MetalLB”) to one of the two Kubernetes nodes shown. An “NGINX Ingress Controller” ensures that an NGINX service (container) is run on each Kubernetes node, which acts as SSL termination and reverse proxy and then ultimately forwards the traffic to the correct container via a so-called “Kubernetes Service”. The web services / micro services are executed on the container. These micro services make sensitive data available and we therefore do not want to expose them to unfiltered web traffic – zero trust.

We would therefore like to start today with the NGINX service (in green) and examine the incoming traffic using a Web Application Firewall (WAF) in order to increase general security in the cluster. We are using the open source WAF called “mod_security” and will be using the Open Web Application Security Project (OWASP) Core Ruleset (CRS) against which we will inspect incoming traffic.

Incidentally, in the case of Microsoft Azure, the “Azure Web Application Firewall” service is offered, which is also based on the OWASP rulesets described in this blog. The pricing of the Azure Service can be found on the linked website.

Open Web Application Security Project (OWASP)

The OWASP ModSecurity Core Rule Set (CRS) is a freely accessible collection of “Detection Rules” – i.e. rules that can be used to examine incoming traffic. These rules can then be used in combination with a compatible web application firewall such as Mod_Security.

The “Core Rule Set” was developed with the aim of protecting web applications from a wide range of known attacks, including the “OWASP Top Ten“. This is a top 10 list of the most frequently occurring security risks and security gaps in web applications, which is redefined every 3 years.
The core rule set currently contains rules that protect our web services from the following risks:

  • SQL Injection (SQLi)
  • Cross Site Scripting (XSS)
  • Local File Inclusion (LFI)
  • Remote File Inclusion (RFI)
  • PHP Code Injection
  • Java Code Injection HTTPoxy
  • Shellshock
  • Unix/Windows Shell Injection
  • Session Fixation
  • Scripting/Scanner/Bot Detection
  • Metadata/Error Leakages

Houston, we have a problem

First of all, as a test, we send an HTTP request to one of our test web services. We design the request in such a way that it clearly looks like an SQL injection attack. You can also test this yourself with one of your own existing web services – we’ll just pretend that our micro service has a “users” endpoint and send an example SQL injection (“ExampleSQLInjection’–“). For this we use the well-known tool “Postman”. As you can see, we get a Swagger document from the Micro Service in response – so the traffic was sent unfiltered to the Micro Service – Houston, we have a problem.

Image - Test SQL Injection Attack with Postman

Beam me up, Scotty

To increase security, we are now making a few changes to the NGINX ingress controller in Kubernetes.
We edit the config map of our NGINX Ingress Controller in Kubernetes and activate “mod_security”, as well as the OWASP CRS (Open Web Application Security Project – Core Rule Set). According to the documentation, with the help of the “modsecurity-snippet” line, we can write a few lines in the nginx.conf (“modsecurity_rule”) so that the engine is actually activated. (By default, the engine otherwise only runs in “DetectionOnly” mode).

kubectl edit configmap openzilla-ingress-ingress-nginx-controller -n ingress-nginx
...
#
apiVersion: v1
data:
  enable-modsecurity: "true"
  enable-owasp-modsecurity-crs: "true"
  modsecurity-snippet: |-
    SecRuleEngine On
    SecRequestBodyAccess On
    SecAuditLog /var/log/modsecurity_audit.log
    SecAuditLogParts ABCIJDEFHZ
    SecAuditEngine RelevantOnly
kind: ConfigMap
metadata:
  annotations:
....
Kubernetes Configmap for nginx ingress controller

PS: If desired, you can also define your own Mod_Security Rules in the ConfigMap, such as whitelisting an IP address you know: “SecRule REMOTE_ADDR “@streq 192.168.254.1” \allow,phase:1,nolog” or deactivate existing rules .

If we now connect to one of our NGINX Ingress Controller Pods in Kubernetes, we will find the core rule set under “/etc/nginx/owasp-modsecurity-crs” (here the corresponding GIT repository). In the nginx.conf we see that the corresponding config file has also been included:

...
modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;
...
Image - modsecurity in nginx ingress container

That looks good – now let’s run the above test again with Postman.
The traffic to the web service has now already been stopped by NGINX Ingress and Mod_Security – beautiful!

If we check the Mod_Security log file, we see that the request was blocked because an SQL injection was detected according to rule “942100” from the CRS (REQUEST-942-APPLICATION-ATTACK-SQLI.conf).

That was the basic config of the Kubernetes NGINX Ingress Controller. More configurations for Log Ingestion into Elasticsearch and Dashboard Creation in our next post.