18 months ago, I reviewed two versions of Police CyberAlarm; their pre-release "development tool" and a production variant.

After many hours of reviewing some of the worst code I'd seen in quite a while, I reached two conclusions.

1) cyberAlarm is woefully insecure
2) Pervade, the developer responsible, were incompetent

If you've followed this saga, you may recall I responsibly disclosed everything to the NPCC and Pervade.  However, their responses were both defensive & dismissive; to the extent of telling the public I'd reviewed the wrong product entirely and my claims were "completely untrue"

Until recently, that was the official line to anyone who raised my initial review during webinars/support calls.

Thankfully, that ends today.

Over the last 18 months, I've received a steady stream of emails/DMs from users/EDUs/firms, many of whom were rightly concerned about what they'd read.

In February, a network admin from a local School reached out, asking me to audit cyberAlarm again.  Unfortunately, time & COVID had other ideas... forcing us to wait until March 16th before we could exchange files/details.

March 16th 3.15PM

I received the files and fired up the virtual machine.

Once again, the files are Ioncube encoded to "hide" the contents - which took all of an hour to reverse.  I began looking through the decoded files, instantly spotting several critical flaws.

Over the next couple of hours, I created a list of serious issues which Pervade, Prism Infosec & Arcanum Cyber Security have supposedly missed.

Let's dive in.

Insecure Passwords

You may recall that I notified NPCC/Pervade back in 2020 that SHA256 wasn't secure or appropriate for password storage.

So, 18 months later... is it any better?

Well, locally stored passwords are still hashed with unsalted SHA256... but incredibly, Pervade have actually made it worse.

A logic flaw in "index.php" means passwords are actually sent to AND RETURNED FROM the central API in plain text!  This isn't an API running on the data collector either - it's centrally operated at https://collectors.cyberalarm.police.uk/OPVIEW/API

Above is a response from an API call to fetch a user's details.  You're not obliged to set a password on the data collector, but even if you do, an attacker can simply request it from the API.

Insecure Session Tokens

Before a cyberAlarm data collector carries out any request, it checks to see if a session variable exists... called "token".

If it doesn't exist, it creates one and attaches it to the user's session.  Here's the snippet of code responsible...

The token is created using two PHP functions.

1)  "time" returns the number of seconds since the Unix Epoch (Jan 1 1970)
2) "rand" returns a random number between & including 1000 and 9999

Spotted the problem yet?

Any attacker can remotely control the box if they know the current time and can count to 9,000! Must. Not. Insert. Meme.


… and so on.  As with password brute force attacks, we rarely need to search the entire space for the correct token.  In reality, we often see a successful response after just 50% or 4,500 requests.  To a local endpoint, this takes around 2.5 seconds to complete.

The logic which checks the token's validity looks like so...

So if the token doesn't exist or doesn't match, "exit" the PHP application immediately.  Don't worry about writing it to a log or limiting further requests... just abort and let the attacker try again. Sigh.

In short, cyberAlarm can withstand an attack for a maximum of 5 seconds.

But who's got 5 seconds to XSRF a data collector, I hear you cry?  Ain't nobody got time for that.

Let's just ask the API to do it instead!

Unauthenticated API

You read that right.

The central API has no authentication whatsoever!

Want a customer's records? Sure.

Make a GET request with the data collector's ID and it just hands it over.


Names, email addresses, the aforementioned plain-text password, telephone numbers, timestamps, which IPs they scan, how often they're scanned... basically everything you've entered into the data collector.

But that's a GET request... what if we POST with the same JSON?  Surely we can't update a record without authentication?!

Of course we can!  Give it the data collector's ID (it's the primary key, for those who understand databases) and the central API updates the record.

To make matters worse, these changes are then sent to the data collector (including the password!).

So, what can we do with such limitless access?

1) Redirect monthly vulnerability reports to the attacker
An attacker can now set the "reportingEmail" address, so if cyberAlarm does detect a 0 day, the attacker is the first to know.

2) Set someone else's scan IP!
An attacker can also manipulate which IPs are scanned for vulns.  That'll make for an awkward discussion when an NPCC/Pervade server starts scanning another gov't agency ;)

What's stopping an attacker from entering your competitors IP instead?  NPCC/Pervade will almost certainly breach the Computer Misuse Act by actively testing for 0 days without consent of the owner... and the data collector's admin isn't the owner.

3) Download any/all reports
Somewhat unsurprisingly at this point, it's also possible to download any PDF report for any data collector, without authentication.

What better way to increase your risk significantly than to hand your attackers a list of vulnerabilities!

No XSRF protection

Echoing my 2020 article, cyberAlarm still has no adequate XSRF protection... allowing an attacker to remotely breach/control any CA installation.

Of course, nobody is likely to bother with this slightly more difficult attack while the API is so willing to comply... but after 18 months, I hoped it'd be safer now.

Passwords aren't timing safe

At this point, any hopes of a safe & secure authentication scheme are long gone.

However, if you're going to compare two password hashes, it's vital to compare them using a timing-sensitive comparison.

Rookie mistake #3,251,901.

As Pervade use a direct string comparison, it's possible to leverage the metadata of a failure (here, the time it takes to fail) to work your way closer to the real credential.  PHP created "hash_equals" for a reason.

Broken crypto, AGAIN!

Here's a code snippet showing how Pervade "encrypt" your data.

If you understand cryptography, you're likely shaking your head in disbelief right now.

You see, Pervade's limited grasp of security/cryptography throughout the entire app leads us to an inevitable issue here.  The use of AES-256-CBC isn't an issue in itself; it's entirely possible to deploy CBC safely & effectively.

Unfortunately, Pervade has made a complete hash of it.

After you've encrypted your super sensitive message, it's absolutely imperative to add an HMAC or Hash-based Message Authentication Code.  The HMAC allows the recipient (the central collector, in this context) to verify the authenticity of the message, as it's possible to manipulate ciphertext whilst in transit.  This is a well-known/understood attack called CBC bit flipping.  Without it, you can't rely on the authenticity of the data and as such, it should be discarded.

It's 2022.  It's reasonable to expect Pervade to have use a modern AEAD cipher; something which supports authenticity checks natively... but for whatever reason (lack of knowledge, perhaps?), they've tried to roll their own crypto; breaking the cardinal rule of cryptography.

There are only two possible outcomes here. Broken... and very broken.  Guess which category Pervade's code falls into? ;)

Rolled their own? They've used PHP functions!

At first glance, you might think that's a reasonable counter-argument... but let me explain why it's not.

There are countless crypto libraries out there... many peer-reviewed & trusted.  Pervade may have used the same underlying functions, but they've done so in a way which falls right into the hands of an attacker.

The devil is in the detail.

This line sets the initialisation vector - a crucial step in the encryption process.

There are two functions, one nested.

1) openssl_cipher_iv_length
2) openssl_random_pseudo_bytes

#1 returns the length (in bytes) for the given cipher, or false
#2 returns random bytes of the given length, or false

I emphasise "or false" because it's equally vital to ensure the data is as you expect.  Whilst #1 can fatally fail (resulting in a crash here), #2 can fail with a warning (which are turned off) but PHP still encrypts the value... with the $iv as false.

What happens when the $iv is false?  Every single record is encrypted using a static key and no IV! Great!

Introducing OWASP - The Open Web Application Security Project

Web developers often build applications mindful of the OWASP Top 10 - a list of common vulnerabilities collected from multiple sources.

For 2021, the top 10 looked like this...

Keep in mind the scale of the cyberAlarm's data collector.

It's a single HTML form "protected" by a login page, with a spec-driven data collector bolted on.  It's about as simple as it gets.  Almost incredibly, Pervade has managed a solid 9/10 categories - and a straight 10 if we include flaws from 18 months ago.

In my view, there are only two ways to describe such an app.  Woefully insecure... or a CTF competition.  Seriously, this would make a great capture the flag application for rookies looking to cut their teeth.  I make that distinction for a reason; these really are rookie-level issues made by a firm I can demonstrate are devoid of a clue.

Speaking of CTFs

It's all well & good endlessly parroting that Pervade are clueless, but that's an opinion based on their code.  So, I set out to prove myself wrong.  I joined their Cyber Wales CTF Cluster webinar, hosted by John & Jason of Pervade.

This webinar from April 2021 is intended to teach viewers how to defeat XSS attacks.  Unfortunately, it's one of the most tortuous & mind-numbingly misinformed webinars I've ever witnessed.

It's an hour and 15 minutes long but it really is hand-bitingly awful to watch; demonstrating a total lack of understanding of XSS and various other bits.

Don't have an hour?  Let me break it down for you.

12:59 - John (Director at Pervade, "joking" that he'd alter a pen test report so basic flaws like this wouldn't appear - many a true word....)
14:10 - Lacks basic understanding of IFRAMEs.  Tries to load sites on the wrong protocol & sites which expressly prohibit framing with CSP (bbc, google etc).
30:00 - Literally clueless.  Seems to think javascript won't execute after a page has loaded, so "no dynamic stuff".
31:00 - Seems to think this XSS attack is happening "server side" and because it is, we can now "insert code which does something"
31:24 - This isn't being "executed" by the server, what is he talking about?
32:03 - Genuinely believes a client-side language is being executed on the server.  Is PHP node now?
33:25 - Just throw "htmlspecialchars" at everything - job done.  Forget quotes, forget context - but at least he's doing it on output.
34:07 - Immediately renders the fix useless by running it against the inputs, not the output.  This demonstrates a fundamental lack of understanding.
34:33 - Oh good lord, they're using the same technique for SQL injection mitigation!


35:15 - Using regex (preg_match) to find "the bad characters".  Bad characters in what context?  Again, missing the point entirely.
38:10 - "Sanitize our inputs so it can't do anything dangerous to us" - Sigh
38:32 - "We can also replace the bad characters" - This guy is the Director of Pervade, a "professional" company which provides apps for the Police, NHS etc.  Think about that for a moment.
40:15 - Demonstrating a "stored XSS" attack - with fails aplenty.
47:00 - "You can do that on any page on the planet.  There's actually no way for me to stop you doing that" (referring to inline XSS).  Again, fundamental lack of understanding of basic security controls.  A CSP (Content Security Policy) header is literally designed to protect against attacks like this, but it's the same CSP he couldn't figure out whilst trying to embed an IFRAME earlier.
48:55 - Genuinely seems to think he has to alter his code syntax to allow different inputs.
53:28 - Me asking him to demonstrate how to protect against XSS in his own code - he REMOVES THE BAD CHARACTERS! Writes software for Police/NHS remember!
56:13 - "To secure it, once again, it's one word - same as SQL injection" - Christ above.  I give up.
1:05:30 - I ask him to explain how an application which requires characters which allow XSS, can protect against it.  He goes on to explain nested ifs, database calls etc.  An IF statement for every possible input - seems scalable!
1:09:50 - A glimmer of hope - "You can actually do this on the other side" - Referencing output encoding, which is actually how it should have been done an hour ago.

This video (along with several others) is definitive proof, straight from the horses mouth, that Pervade fundamentally do not understand secure coding practices.  The issues I've identified here aren't mistakes - they're the result of a gov't funded team completely out of their depth.

Remember, these guys run the Cyber Essentials platform... oh, the irony.

Responsible Disclosure

After the 2020 debacle, I'd hopefully be forgiven for simply publishing these issues without speaking with NPCC.  After all, my disclosures were discarded as a "waste of public money" and I was accused of operating in bad faith.

However, the goal of disclosures like these is to protect the public - not to put them at direct, demonstrable & increased risk.  That, combined with the severity of the vulnerabilities, left me with little choice but to notify the NPCC again.

However, here's how the story takes an interesting & positive turn.

March 18th 1:40PM

After briefly speaking with Ian Hickling on his mobile earlier in the day, he escalated the matter to Phillip Donnelly, Cyber and Darkweb Technical and Capabilities Lead @ NPCC.

I'd spoken to Ian & Phil back in 2020 and both were polite & helpful, but communications quickly turned sour when Pervade pushed back with lies & misleading statements... leading NPCC to believe my claims were untrue.

I requested a video call with Phil that day and to my surprise, he agreed.

Later that day, Phil and I spent a good hour on a Teams call - during which I explained every issue and demonstrated each attack, live, via screen sharing.  No room for movement or disagreement this time; every attack worked exactly as described.  By the end of the call, it was clear I could control any data collector and the API.  I advised that CA be taken offline immediately, as the risk to the public was/is very high.  Whilst Phil didn't agree/disagree on the call, he later emailed to advise that parts of the API were taken offline and members were notified as such.  In reality, NPCC mitigated several risks within 1hr of our initial call - simply by taking parts of the API offline.  Say what you will, that's impressive.

Let me clarify a few things, before I go any further.

Phil's approach both initially and during conversations even now is absolutely spot on.  His candid & measured response makes disclosure much easier.

It has always been my belief that NPCC have been & continue to be misled - even hoodwinked.  Whilst their response to my 2020 review wasn't great, I can somewhat understand & justify it given the information coming from the other side.

Mindful of our previous discussions and how several vulns disappeared despite "never existing in the first place", I took a different approach this time.

Before contacting NPCC, I'd already been in touch with various media outlets & several other security testers, all of which have independently verified these findings.  They may be running the story shortly too.

What next?

Over the coming days, Phil/NPCC realised these issues needed further investigation and clearly weren't willing to trust Pervade or the existing security firms.  Instead, they sought the assistance of another independent security auditing firm.

I won't name them just yet (possibly not at all), but I have absolutely no doubt in their abilities to highlight not only the above, but far more.  Their report is a paid engagement however, so I'd certainly expect better results when compared to my freebie to an EDU.

An email from Phil later requested another video call, this time with the external testing company.

March 25th 10AM

I join a call with Phil & <redacted> from the external security company.

Once again, we go through each & every issue - demonstrating them with proof-of-concept files and providing screenshots showing payloads which were working, prior to the API going partially offline.

I have something of a reputation for telling it like it is; some appreciate it, others (perhaps rightly) see it as slightly unprofessional.  The external company on the other hand... took notes, asked questions and remained professional throughout, refraining from comment until their own research was over.  So far as I'm aware, their investigation is still ongoing and cyberAlarm remains live.

That however, is where we disagree and is the reason this article exists.

My advice, both now and 18 months ago, was to pull cyberAlarm immediately, believing it to be a dangerous application which only increased the risk to anyone who installed it.  Understandably, NPCC's position differs and every effort is being made to patch these issues and keep cyberAlarm going.

During conversations back & forth, NPCC cited a common 90 day period before any disclosure.  They didn't request it, to be clear... but merely referenced it - perhaps hoping I'd refrain from publishing until they'd had time to investigate.  Normally, that's perfectly reasonable.  However, I've been barking about cyberAlarm's vulnerabilities/risks for 18 months... to no avail.  NPCC had the chance, 18 months ago, to do the right thing and pull cyberAlarm from service.  Now, the number of customers has increased and so have the quantity of vulnerabilities.

Now, my position couldn't be clearer.

CyberAlarm is profoundly dangerous.  It's woefully insecure, ill-conceived, poorly written & provides questionable value.

Whilst I welcome the news that NPCC have engaged another security firm, I sincerely hope they take this opportunity to see cyberAlarm/Pervade for what it is; a one-way ticket to a serious breach.

April 14th 11:24AM

I received a reply email from Phil Donnelly at NPCC requesting 90 days before disclosure, citing the need to wait for a report and mitigative action.

I refused on the basis that nearly all of these vulnerabilities existed 18 months ago but were ignored, "never existed" or "weren't a security issue".  Even so, I've given 30 days which I believe is perfectly sufficient given the risk/circumstances and likely far more than any other researcher would provide, given the initial response in 2020.

Phil again cites "I've been assured that several points are not possible due to other checks" but still will not disclose which ones, or why.  I have left no room for argument this time; he's seen every exploit on a Teams call with screen share.


Pervade has had 3 attempts and well over 18 months to develop cyberAlarm into something resembling a decent, secure & deployable application and judging by this latest iteration, it has utterly failed to do so.

Whilst NPCC's response on this occasion has been entirely commendable, their latest communication outlines their need/desire to "get it right", but go on to discuss "mitigation" following the independent report.

In my opinion, the NPCC needs to shutter cyberAlarm at the earliest opportunity and turn their attention to other projects outsourced to Pervade, including the Cyber Essential platform.

I sincerely hope this signals the end of this utterly shambolic debacle.  If pride precedes privacy again, expect another article in a few years.  If NPCC decides to revert to type and tries to refute this article, there's a growing number of media outlets & security researchers ready & waiting to fully disclose; that really won't be pretty.

This article and all findings within are the result of one anonymous network admin who remained open-minded & professional enough to push back against the "official line" and wanted an independent audit before putting his staff/students or network at risk.  If this has helped you, please pass on your thanks in the comments below.

If you're in a similar position, please get in touch.