Shopware on fast lane - secure operation using ModSecurity with Elastic and Kubernetes
Learn in this article how your data and your customers' data can be securely protected with an internal Web Application Firewall (WAF) and why this makes sense. We show you code excerpts within a short guide with tips and tricks.
4 min read

Setup
In the scenario shown here, we used the following components:
Shopware
NGINX web server
ModSecurity v3
Managed Kubernetes (Openstack by OVHcloud)
ELK Stack
The particular challenge here lies in separating the logs, since standard logging works purely via stdout.
Why a web application firewall makes sense and what it actually does
The Open Web Application Security Project (OWASP) categorises the biggest threats on the internet each year, with the aim of improving security in applications and services on the World Wide Web
The current OWASP Top 10 consists of the following risk sources:
Injection
Broken authentication
Exposure of sensitive data
External XML entities (XXE)
Broken access control
Misconfiguration
Cross-site scripting
Insecure deserialisation
Use of components with known vulnerabilities
Insufficient logging and monitoring
A Verizon study highlights an increase in attacks on web applications from 48% to 80% between 2020 and 2021. The trend for 2022 is rising.
For this reason, securing your e-commerce platform is essential for data security. The following diagram illustrates this protection with a two-stage WAF. The diagram shows, by way of example, the traffic from genuine users and attack scenarios, and the protection provided by a Web Application Firewall.

Configuration Modsecurity
A real user reaches the shop system via your domain. A hack attack can take place either via the domain URL or the IP range of the hosting provider. It is therefore advisable to run a two-tier WAF concept. One external (e.g. With Cloudflare) and one internal, within the LAN in front of the application (with modsecurity).
In this case we use ModSecurity as our internal WAF. ModSecurity is a rule-based engine that filters web requests using a rule set. If the check succeeds, the HTTP request is forwarded to the shop. If it fails, it blocks the request.
The following vulnerabilities can be monitored via the rule set:
SQL injection and Blind SQL injection.
Cross-site scripting (XSS).
OS command injection and remote command access.
File name injection.
ColdFusion, PHP and ASP injection.
Email Injection
HTTP Response Splitting.
Universal PDF XSS.
Trojans & Backdoors Detection
The external WAF, which is usually managed by a provider, would also mean enhanced protection, allowing zero-day attacks, for example, to be blocked at an early stage.
But what's needed to set up the internal web application firewall? Below we show you how to implement it!
Modsecurity configuration
For simple transmission, ModSecurity was configured so that entries are stored in JSON format. This greatly simplifies the subsequent transformation into ELK Stack objects.
The following annotations must be added to the Ingress for Modsecurity to be activated:
ModSecurity config:
Modsecurity Config
To simplify transmission, ModSecurity has been configured to save entries in JSON format. This greatly simplifies the subsequent transformation into ELK Stack objects.
The following annotations must be added to the Ingress to enable ModSecurity:
Modsecurity Config:

Furthermore, the Ingress Controller must be adjusted so that it distinguishes between plain NGINX logs and those from Modsecurity. For this, the following excerpt must be integrated.
An additional container is added to the pod, which separates the ModSecurity logs:

Configuration Filebeat
Filebeat configuration
There are two options for transferring log entries from the modsecurity audit log.
Elastic Agent: ModSecurity audit log
File Beat
Since implementation via File Beat is better suited for Kubernetes, we'll cover this variant going forward.
To transfer the previously separated logs into the ELK Stack, we use the filebeat.autodiscover function.
We separate the logs via the label "kubernetes.container.name". This is necessary because otherwise the audit file would be processed with the current standard NGINX pipeline from elastic, and this is automatically overwritten with every new release. So that we can better separate the messages from each other, we have also, as described above, added the extension "mod-security-logger" to Modsecurity in Kubernetes.

Configuration Elastic Pipeline
Since, as described above, we transmit JSON formats, the pipeline in Elastic is limited solely to transforming this object. For this purpose, Elastic provides a predefined method called “json.” This method must be executed twice in a row to perform an automatic transformation. Please don't ask why that is ;).

Shown below is an example attack that attempts to open the ".env" file.
{"transaction":{"client_ip":"5.147.64.XXX","time_stamp":"Tue Jun 28 20:47:07 2022","server_id":"ffbd70bb61277107b0608c3d2be5824751fecdce","client_port":58758,"host_ip":"10.2.0.XXX","host_port":443,"unique_id":"70b0ae977efcb4521a4795c94bc87c9b","request":{"method":"GET","http_version":2.0,"uri":"/Products/RNA-Extraction/.env"},"response":{"http_code":403},"producer":{"modsecurity":"ModSecurity v3.0.5 (Linux)","connector":"ModSecurity-nginx v1.0.2","secrules_engine":"Enabled","components":["OWASP_CRS/3.3.2\""]},"messages":[{"message":"Restricted File Access Attempt","details":{"match":"Matched \"Operator `PmFromFile' with parameter `restricted-files.data' against variable `REQUEST_FILENAME' (Value: `/Products/RNA-Extraction/.env' )","reference":"o24,5v4,29t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase","ruleId":"930130","file":"/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf","lineNumber":"105","data":"Matched Data: /.env found within REQUEST_FILENAME: /products/rna-extraction/.env","severity":"2","ver":"OWASP_CRS/3.3.2","rev":"","tags":["application-multi","language-multi","platform-multi","attack-lfi","paranoia-level/1","OWASP_CRS","capec/1000/255/153/126","PCI/6.5.4"],"maturity":"0","accuracy":"0"}},{"message":"Inbound Anomaly Score Exceeded (Total Score: 5)","details":{"match":"Matched \"Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' )","reference":"","ruleId":"949110","file":"/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf","lineNumber":"80","data":"","severity":"2","ver":"OWASP_CRS/3.3.2","rev":"","tags":["application-multi","language-multi","platform-multi","attack-generic"],"maturity":"0","accuracy":"0"}}]}}
From this JSON array, the following attributes are particularly important for further analysis:
modsecurity.transaction.client_ip - attacker ip
modsecurity.transaction.messages.details.file - Attacker Name
modsecurity.transaction.messages.details.ruleId <- modsecurity rule
modsecurity.transaction.messages.details.match: detailed information
modsecurity.transaction.request.uri - URL call
Add exceptions
After activating the WAF, some intended requests may be blocked.
These differ depending on the application and extensions used and must therefore be determined individually.
If you want to add exceptions for this access, do the following:
modsecurity.transaction.messages.details.ruleId - this field can be used to get the rule ID. Example: "932115"
Now add following entry below "nginx.ingress.kubernetes.io/modsecurity-snippet: |":
SecRuleRemoveById 932115
Configuration of Elastic Kibana dashboard
For processing the logs in the ELK stack, we provide the following dashboard we've defined: it shows a grouping of attackers by time, attack type, attack region and the actual attacks.

- Marc Achsnich
Team Leadsynaigy
Show email address
Subscribe to the blog now and never miss any news
✔️free of charge ✔️weekly news ✔️expert knowledge
Please accept the corresponding cookies to view this embedded content.
