WAF (OSS) ModSecurity Plugin example

Last updated: 3 minutes read.

Use Case

Traditionally, a Web Application Firewall (WAF) would be the first layer requests would hit, before reaching the API gateway. This is not possible if the Gateway has to terminate SSL, for things such as mTLS.

So what do you do if you still want to run your requests through a WAF to automatically scan for malicious action? We incorporate a WAF as part of the request lifecycle by using Tyk’s plugin architecture.

Prerequisites

  • Already running Tyk - Community Edition or Pro
  • Docker, to run the WAF

Disclaimer

This is NOT a production ready plugin because

  • The JavaScript plugin creates a new connection with the WAF for every request
  • The request is not sent over SSL
  • The WAF is only sent the query params for inspection.

For higher performance, the plugin could be written in Golang, and a connection pool would be opened and maintained over SSL

Install Steps

1. Turn JSVM on your tyk.conf at the root level:

Turn on JSVM interpreter to allow Tyk to run JavaScript plugins.

Copy code
"enable_jsvm": true

2. Place the JavaScript plugin on Tyk file system

Copy the JS Plugin as a local .js file to the Gateway’s file system.

From the Gateway root, this will download the plugin called waf.js into the middleware directory:

Copy code
curl https://raw.githubusercontent.com/TykTechnologies/custom-plugins/master/plugins/js-pre-post-waf/waf.js | cat > middleware/waf.js

(Instructions) If you are running Tyk in Docker, you can get into Tyk Gateway with docker exec

Copy code
$ docker ps | grep gateway 670039a3e0b8 tykio/tyk-gateway:latest "./entrypoint.sh" 14 minutes ago Up 14 minutes 0.0.0.0:8080->8080/tcp tyk-demo_tyk-gateway_1 ## copy container name or ID $ docker exec -it 670039a3e0b8 bash ## Now SSH'd into Tyk Gateway container and can perform curl root@670039a3e0b8:/opt/tyk-gateway# ls apps entrypoint.sh install middleware templates tyk-gateway.pid tyk.conf.example coprocess event_handlers js policies tyk tyk.conf utils ## Download the plugin root@670039a3e0b8:/opt/tyk-gateway# curl https://raw.githubusercontent.com/TykTechnologies/custom-plugins/master/plugins/js-pre-post-waf/waf.js | cat > middleware/waf.js % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1125 100 1125 0 0 3906 0 --:--:-- --:--:-- --:--:-- 3975

waf.js source

3. Import API definition into Tyk

Copy the following Tyk API definition and import it into your environment.

API Definition JSON

Here’s the important section which adds the plugin to the request lifecycle for this API:

Copy code
"custom_middleware": { "pre": [ { "name": "Waf", "path": "./middleware/waf.js" } ],
How to Import?

Tyk Pro

Tyk CE

4. Run WAF ModSecurity Using Docker

First run ModSecurity with the popular Core RuleSet in Docker

Copy code
$ docker run -ti -p 80:80 -e PARANOIA=1 --rm owasp/modsecurity-crs:v3.0

Open a second terminal and curl it

Copy code
$ curl localhost hello world

We should see the request show in the WAF server:

Copy code
172.17.0.1 - - [30/Jun/2020:00:56:42 +0000] "GET / HTTP/1.1" 200 12

Now try a dirty payload:

Copy code
$ curl 'localhost/?param="><script>alert(1);</script>' <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access / on this server.<br /> </p> </body></html>

Our WAF catches the response and returns a 403.

Now we try through Tyk.

Copy code
## Clean requests, should get response from upstream's IP endpoint $ curl localhost:8080/waf/ip { "origin": "172.30.0.1, 147.253.129.30" } ## WAF will detect malicious payload and instruct Tyk to deny $ curl 'localhost:8080/waf/ip?param="><script>alert(1);</script> { "error": "Bad request!" }