Secure web proxy with Symfony

For the past few months I got caught up into puppet, monitoring and other devops stuff. Wether or not security is part of devops (honestly I don’t care as long as security is taken into mind when developing) I was also tasked with securing some backend systems for the company that I work for as part of ISO 27001 certification. One of them was a PHP based application which had a code base, so old, so spaghetti bolognese that it could wake you up in the middle of night soaking in sweat when thinking about its security design. Nevertheless it was a critical application, that couldn’t be merged easily to a new code base like Symfony or another tool. So how to improve its security?

If it was built in Symfony, I could easily setup a firewall, add NelmioSecurityBundle and maybe add a 2-factor bundle and get on with it. But yeah, it wasn’t. Maybe I could just go into the spaghetti and implement some meatballs with composer and make the best of it? Meh…. There will always be the risk of open holes, maybe a “require ‘check_login.php’;” is forgotten, or login method might be vulnerable from a good old SQL injection. So this was not an option.

The app was used publicly by some of our customers, so IP whitelisting was no option. It just needed public protection from vulnerability scanners, So I wanted it to be wrapped in a secure package. More like a portal. What if I wrapped the entire application into a secured Symfony environment? But that would incur another session_start from the old application. So it needed to more separated than that. And at that point the idea of a Symfony web proxy was born. The Symfony layer would handle all the security, after which every request is proxied to the old PHP application. So the requirements would be

  • A symfony application @ my.symfony.proxy which functions as login portal
  • After logging in, every request is ported to an another site. Something like https://my.symfony.proxy —> http://old_application_at_private_location:8080

Here’s how with Symfony 4.x (using flex) on PHP 7.2.

Setting it up

First we create a new project and install and setup some needed libraries. I mentioned them here below

Now that we installed everything we needed we can configure our application.


Lets start with my favourite and most complex part of our application (now we’re still sharp). First we configure our security.yaml

Now comes the interesting part. I wanted to use the same user and password database provided by the old native PHP app. So I need to create an entity that respects the existing table, and add this as a user provider in the security.yaml.

Because the old app uses plain md5 hashing for the password without any salt or iterations I needed to change the encoder to some lower standards, so it integrates seamlessly with the old standard. Obviously this is not recommended security. If this is your exact same case, and would like to enhance this security. Then I recommend you to add an extra salt column, and rehash the password on login with some salt and iterations with the default encoder. On the login event you only need to check if there is already salt or not to pick the right encoder.

Now we can configure the firewall, wich is somewhat standard. Change according to your needs. Don’t forget to name the right provider.

Last but not least, add the access control

User Entity

In my case I wanted to reuse an existing user database (within the old application), which is served under MySQL. So I created an entity which reflects this table to be able to reuse this data. This is how my entity looks like:


We need a few methods; first the login and logout method, which are pretty straight forward.

Then finally the core of this whole blog, a catchall controller. This method is called upon every other request (catchall magic is handled in the routing part further on). It just reads the current request, and passes everything within a curl request (Guzzle) to the old application that needs to be protected. In my case I placed the application in nginx under port 8080, which is shielded by a firewall and only accessible from localhost. Change the URL to your own “old application”

So now we basically created a proxy application. Now you can serve every existing site with your own custom domain (don’t use this for bad stuff, mkay?).

Security listener

Underneath all of this, we still need to add a little more custom logic to take over the login process. Instead of logging in directly with the original login of the application, I wanted to use symfony login. This is done with a security listener. Be sure that you change the code to an actual working login.


There are four routes needed for the controller. Besides the security related routes there is one route which is particularly interesting. This is the catchall route which should be named lastly to catch all other routes that are not matched by the fixed security related routes. This is done by providing a regex with just .* to match anything.


The template is a somewhat basic login template based on a simple twitter bootstrap theme. Placed under security/login.html.twig

Wrapping it up

To conclude; it’s relatively easy to setup a web proxy with modern security standards to protect your old (irreplaceable) spaghetti app. With Symfony at its base, some configuration and the usage of the right libraries, we only need a few files with satisfactional result.

I created a repository which contains all of the above, which you can use out of the box. This is found at my github account @

CopperheadOS review

Sadly CopperheadOS died (at least for me it did). The director of CopperheadOS found himself way to important with his dick move to seize ownership of the entire company, and left the other 50% owner (the main author behind CopperheadOS) empty handed.

Goodbye from CopperheadOS

I guess the following still applies for other ROMS. Just like Michael Micay advised, just use plain AOSP without gapps. For me this is CarbonROM with F-Droid and Yalp, while waiting for a more security and privacy centered ROM.

Unlike many, who apparently got nothing to hide (, I’m a bit keen on my privacy and security. This has probably something to do with my daily job as a DevOps engineer, but should nevertheless be interesting for anyone who wants to be back in control of their data. This CopperheadOS review is about taking that control.

One approach on security is to know where your weak spots are. For me this was my Android phone. It seems like everyone is downloading all kinds of binary apps, and are trusting them blindly. This feels likes the Window 95-98 era where many would just download and run any *.exe without hesitation. Another argument was the obscure Google Play services, not knowing what it does send back to Google and what doesn’t. And even when I do know, I don’t have any reasonable opt-out possibility for sending any data. In my quest of searching for alternative ROM for better security and privacy I found CopperheadOS. Which I’ll be reviewing here.

CopperheadOS is a plain AOSP with additional hardening and focus on open source apps, without any binary sending my data to the cloud. This was somewhat a leap of faith, as I would be obliged to part from some binary apps I rely on in my daily life (altough not entirely true, but read along). But as it turned out there are lots of open source alternatives which offer same or nearly same functionality.

App repository

Because CopperheadOS is stripped from the Google Play Framwork (hooray!) it comes with F-droid as app installer. With F-droid you can find only open source apps, so this is my primary source of finding new apps before switching to an alternative.

Binary apps

My main focus is to stay functional, not becoming some paranoid hermit with a tin foil hat. With a healthy feeling of unwillingness I had to install Whatsapp to stay connected with family and friends. I could’t convince them to use Conversations (which requires registering a jabber account). And some banking apps don’t come open source either. This is why I installed aptoide to be able to install trusted binary apps. You need to (must actually) only install trusted apps. Altough I think Aptoids’ malware checking flow could be better concerning the signature checking. Checking signature against other marketplaces is kind of vague for me. So be on your guard here.


Already mentioned above, I’d like to use Conversations. It offers same functionality as whatsapp, but offers great encryption on a federated network. Which is IMHO the best kind of privacy AND security you can get nowadays without compromise. A jabber account is free for registration (e.g. Once you have registered a jabber account and installed conversations, switch over to OMEMO encrypted messaging.


CopperheadOS comes with Chromium as default browser. Although I like Chromium very much at my desktop (not to be confused with closed source Chrome). It doesnt allow extensions on Android. Therefore I switched to Firefox to be able to install an adblocker (ublock origin) and a cookie wall (self destructing cookies for inactive tabs).

Search engine

Sorry to say Google; you gave me great search results but I don’t want to live in your filter bubble anymore. After a period of time I started to trust the quality of search results from DuckDuckGo. I’m not saying this company is great for total anonymity, but it is far more better than Google. And in combination with self destructing cookies, searching becomes even more anonymous.


Another great thing of CopperheadOS is it’s SMS app Silence, it offers a standard SMS app with the possibility of encrypting your messages. Before first usage a key needs to be exchanged with someone who also runs Silence, after which all text messages are encrypted from that point forward.

Cloud backup

Another Google thing that needed to be untied was the backup procedure. For this I installed a Nextcloud server on a VPS and the DavDroid app on Android which syncs my contacts, agenda and tasks to NextCloud. Another nice feature is the automatic backup of newly created photo’s.

Other open source apps and alternatives

CSipSimple: Excellent VOIP client
DavDroid: Syncs my contacts, calendar and tasks with my NextCloud server
OpenVPN for android: Which I use on public wifi hotspots
OSMAnd~: Excellent navigation app based on open street maps



Nothing in the world comes for free, Google needs to earn some to be able to provide all the services the offer. Altough I don’t want this to be a Google rant, the ties between stock Android and the Google cloud is becoming very diffuse, and gave me an itchy feeling about it. This is why I wanted a clear cut between my data and Google, instead of paying with my privacy and not knowing how much I’ll be paying in the end. With CopperheadOS you can make a clear cut, just to be back in control of your own data without any significant compromise. Installation was pretty straigh forward on a Nexus, so it’s easy to just give it a try I’m sure that (if you have the same considerations I have) you won’t be disappointed.

WordPress CVE scanner using

In my previous posts I already wrote about a WordPress CVE scanner (part 1, part 2). It kept haunting me with failures and disappointment. It began with blackbox scanning (slow and performance killing) which moved to whitebox scanning with Wordstress which proved to be buggy. So it needed to be addressed one more time (hopefully).


A whitebox WordPress vulnerability scanner getting its CVE’s from, which is simple to use… I decided to write my own in WP-CLI.


WP-CLI is an awesome tool to manage your WordPress installation from the command line, and it recently started supporting extensions. So I created one, and wrote some documentation for it. Installation is done with:

Documentation can be found at

It doesn’t need to be more complex than this.

Wordstress a whitebox CVE scanner for WordPress

a better whitebox scanner is found in a more recent post of mine

A.k.a. WordPress security monitoring 2. In my previous article about worpress vulnerability monitoring the tool wpscan was used. This tool is a black box scanner, which gave us too much false positives and generated a great deal of load on our server which is somewhat a waste of resources. So I went searching for a whitebox scanner to have better results and to make more efficient use of server resources. In this quest I stumbled upon Wordstress.

It came to me as a surprise that this tool isn’t actively used or downloaded. Which is a pity. I think Wordstress is greatly undervalued, because it adresses some issues which are fundamental if you take WordPress security seriously. Let me explain why by explaining the architecture, which will imply the benefits.

The Wordstress project consists of two parts:

– A WordPress plugin which exposes versions for (core, plugins and themes). Only viewable with a certain key through a GET request.
– The Wordstress Ruby gem, wich fetches all versions from the installed plugin (so you can scan remotely). The found versions are checked against the online WordPress CVE database (

Console output of the ruby gem:

If you cron the check, and report the output (mail, monitoring tool, chat), you’re automatically reported of new vulnerabilities in your site. We added our output to a Grafana dashboard, displaying the numer of vulnerabilitis for every of our WordPress setup.

Recently I forked the gem and updated it to use the new API v2 from and implemented some extra output methods (like Nagios with appropiate exit codes). Also did some bugfixes which adds https support and improvements on error messaging. Adding new features wasn’t that hard, so please commit your missing features as a PR’s to Paolo will be happy to merge them.

I don’t have exact numbers here, but the majority of hacks worldwide are due to outdated software. This is why Wordstress is so important, which adresses this problem. Instead many people prefer to use only a WAF plugin like Sucuri or Ithemes. Don’t get me wrong, these tools are very helpful, and I think you should use a WAF in some way, but it doesn’t address the core problem. Good security always starts with updating software.

WordPress vulnerability monitoring

Due to recurring security issues with WordPress I wanted a some kind of wordpress vulnerability monitoring for our Wordpress implementations. The current monitoring setup is implemented with good old fossil Nagios. Despite of many better alternatives, Nagios still does a great job in alerting me through the aNag app. In this post I’ll describe a simple Nagios setup for continuously monitoring WordPress vulnerabilities.  It’s pretty straightforward if you already know Nagios. Nevertheless the scripts I wrote to wrap things around should be re-usable (more or less) to be used in any other setup (ELK?).

Scanning WordPress is done with the wpscan tool, which can be downloaded from . Output of this tool is stored, transformed and displayed in the Nagios way of doing this. As a prerequisite you need to install this tool on your server (hint; use the RVM method) and have PHP/MySQL installed for different subcommands that will be called.

Nagios configuration

First we’re going to write the command, service and service template in Nagios. Check interval is set to once every 24 hours. And by using a parent service (template), you can easily create more checks for other WordPress instances. I copied the configuration from my generated config, which is created by Nconf, but shouldn’t make any difference in directly using this config.

The actual command(s)

When you look closely at the configured command you will see a lot of piping.  I could have put all into one command, but that wouldn’t be re-usable in a future possible ELK setup. It’s also a bit easier to change these scripts to your needs, as its purpose is more obvious.

The actual scanning is done with /opt/wpscan/wpscan.rb –update -u $ARG1$. The output of wpscan is intended to be read by humans, so we need to convert this into something that Nagios understands. Note that this feature should be released in the future as it is announced in the 3.0 release of wpscan ( Until then we use our own filter for transforming which is defined in $USER1$/wpsecurity_filter . This filter will process the wpscan output to a JSON string which is passed to $USER1$/wpsecurity_message that will exit for your with the right exit code and message for Nagios. See gists below for this filtering and messaging to Nagios:

If you’ve read closely, you might already noticed a missing command, namely $USER1$/wpsecurity_store $HOSTNAME$ $SERVICEDESC$. Reason to name this separately is because it is optional. From the outside it just moves STDIN to STDOUT, seemingly doing nothing. In its internals, it stores the output in a MySQL database, which can be accessed with a custom PHP script from the Nagios dashboard (by using the “notes_url” configuration directive). See gist below for this storage:

By using different subcommands we can easily replace the filter later on when wpscan 3.0 is released, also the wpsecurity_store is optional as it outputs exactly what it receives (so you can leave that out if you don’t want storage; also remove the notes_url from Nagios config if you do so).

Vulnerabilities overview

In the Nagios dashboard there is only room for just one sentence for the state of that service. Just naming the number of found vulnerabilities isn’t enough. That’s why we stored the output in MySQL. With a notes_url config we can redirect to a separate PHP file which will display the output generated by wpscan. Please adjust to your needs 🙂 as it is just bare minimum. In the example below are 2 PHP includes which can be downloaded from the SensioLabs repo

Nagios dashboard

If all went well (see /var/log/nagios/nagios.log for errors), you should be seeing something like screenshot below. Watch for the the document icon right from the service description. This link will lead you to the next screenshot.



wordpress vulnerability monitoring