I was trying to find a simple way to secure my PHP Web App when I realized how difficult it could be. Securing it the easy way cost more money than I’m willing to spend, so I decided to build my own solution.
Compiling nginx with ModSecurity isn’t easy, and I don’t think your WAF (Web Application Firewall) should be tied into your web server. If you want to simplify things, you could use Cloudflare or Sucuri, but that can be expensive. While Cloudflare works great and is fast, shouldn’t you have your own WAF? These services do offer more than just a WAF, so be sure to do your own research before committing to any one solution.
I’m writing my PHP WAF in Go. The criteria I set for this project is fairly simple.
Two weeks ago I sketched the idea out on the back of an envelope. If nginx could talk to my Go service, and my Go service could talk to PHP-FPM, then this might be a pretty easy solution. I know that nginx has the
proxy_pass config option and that Go can handle HTTP traffic. But how can Go talk to PHP-FPM? I did some research and tried out a few different FastCGI client packages for Go until I found one that suited my needs. Now I have two ends of the stick figured out, but I’ve yet to even think about what happens in the middle.
I ended up finding a Go package that does an excellent job at filtering XSS. I then wrote some middleware for HTTP and used that Go package to filter any requests that contain an XSS attempt.
But what about SQL injection? Well, I found some regular expressions that match common SQL injection and implemented those into my HTTP Request analyzer. If any SQL injection is detected, it kills the request and your PHP Web App never sees it. At the time of writing this, I still need to implement more security measures.
I’ve also built a Docker container that runs this Go app as a service and is pretty easy to set up. While I haven’t used this for anything in production, I have tested it and it was able to handle several thousand requests a second.
This code should actually work with any language that can use FastCGI as a means of communication, but I haven’t tested it. I’m looking for people to help me finish this project since I’m just now learning Go. Please feel free to fork my repo if you can contribute in any way.