Protecting Piler With A Waf

31 Mar 2024 - sj, tags: archiving, insights, news, product

If you use traefik for piler to provide a https certificate, then you are just minutes away to protect piler with a Web Application Firewall (WAF).

Assuming that you already have the above setup running, let extend it to have WAF protection against SQL injection, XSS and other attacks.

Run the WAF in a docker container

Create docker-compose.yaml with the following content:

services:
  waf:
    image: owasp/modsecurity-crs:nginx-alpine
    container_name: waf
    environment:
      - PARANOIA=2
      - ANOMALY_INBOUND=10
      - ANOMALY_OUTBOUND=5
      - BACKEND=http://dummy
    ports:
      - "127.0.0.1:8000:8080"
  dummy:
    image: traefik/whoami
    container_name: dummy

Start the containers

docker compose up -d

Extend traefik.yaml

Add the following blocks to traefik.yaml

The modsecurity plugin

experimental:
  plugins:
    traefik-modsecurity-plugin:
      moduleName: github.com/acouvreur/traefik-modsecurity-plugin
      version: v1.3.0

Middleware to send request to the WAF for inspection

http:
  middlewares:
    waf:
      plugin:
        traefik-modsecurity-plugin:
          modSecurityUrl: http://127.0.0.1:8000
          maxBodySize: 10485760

Update the piler router to use the “waf” middleware as well

  routers:
    piler:
      rule: "Host(`archive.example.com`)"
      service: piler
      middlewares:
        - "piler_headers"
        - "waf"
      tls:
        certResolver: le

Update /etc/systemd/system/traefik.service

You need to specify the WorkingDirectory

[Service]
WorkingDirectory=/usr/local/etc/traefik

Create the plugins-storage directory for traefik

mkdir /usr/local/etc/traefik/plugins-storage
chown www-data /usr/local/etc/traefik/plugins-storage

Reload systemd

systemctl daemon-reload

Restart the traefik service

systemctl restart traefik

Test the WAF

curl https://archive.example.com

The result looks fine:

<!DOCTYPE html>
<html lang="en" data-bs-theme="auto">
<head>
  <title>Login</title>
  <meta charset="utf-8" />
  <meta name="robots" content="none" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="color-scheme" content="dark light">
...

Now let’s try an XSS attempt:

curl "https://archive.example.com/search?waf<script>alert(0)</script>"

The result is a HTTP/403 response, the WAF rejected our attempt:

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

You may check the WAF container’s log to see why it rejected the request.

Note that in the above example we run only the WAF containers in docker, however it’s possible to run all components (traefik, piler, etc) in containers.

For more details and examples visit https://github.com/jsuto/piler-examples/tree/master/examples/waf

Contact

Contact Us