This Week in Security: Ubiquity Update, PHP Backdoor, And Netmask

Back in January, we covered the news that Ubiquiti had a breach of undisclosed severity. One reader pointed out the compromise of a handful of devices as potentially related. With no similar reports out there, I didn’t think too much of it at the time. Now, however, a whistleblower from Ubiquiti has given Krebs the juicy details.

The “third party cloud provider” the original disclosure referred to was Amazon Web Services (AWS). According to the whistleblower, just about everything was accessible, including the keys to log in to any Ubiquiti device on the internet, so long as it was cloud enabled. The attackers installed a couple of backdoors in Ubiquiti’s infrastructure, and sent a 50 bitcoin blackmail threat. To their credit, Ubiquiti ignored the blackmail and cleaned up the mess.

To the claim that there was no evidence attackers had accessed user accounts, it seems that the database in question simply has no logging enabled. There was no evidence, because nothing was watching. So far, I’ve only seen the one report of device compromise that was potentially a result of the attack. If you had a Ubiquiti device go rogue around December 2020 – January 2021, be sure to let us know.

Safe Mode Ransomware

This is a new trick — We usually use safe mode to fix computers, but one strain of malware is abusing it to break them. The idea seems to be that your antivirus probably isn’t running in safe mode, so the encryption process is more likely to succeed. On the other hand, safe mode might mean that your server’s shared folders aren’t accessible, limiting the destruction to a single computer.

The fancy trick to making this work is to put the payload in a RunOnce registry key, and prefix the key’s name with an asterisk. This incantation signals to Windows that it should run even in safe mode. The encryption process delays the launch of explorer.exe, so the machine will seem to hang at the blank “Safe Mode” screen.

PHP Git Breach

A malicious commit was sneaked into PHP’s code on the 27th, and reverted about five hours later. The developer account that pushed the bad code was assumed to be compromised, and access was revoked. A few hours later, the reversion was reverted by a different developer account. This time the bad code was present for less than two hours before it was reverted with the humorous commit message of Revert "Revert "Revert "[skip-ci] Fix typo""" The consensus is that the server hosting the PHP code was likely compromised in some way, and the decision was made to move the PHP development process to GitHub.

The malicious code was quite simple. It checked for a magic string in the useragent header, and executed PHP code from that header if found. If a PHP release had actually shipped with this code intact, the damage would be astounding, as this would be a simple-to-use backdoor in every web service using PHP. It is worth pointing out that the open source nature of the PHP project led to a very rapid discovery of the injected code, and because of that speed, the actual damage from this attack will probably be essentially nil. This doesn’t seem to be a particularly sophisticated attack, and it wasn’t even disguised to look like innocent code. Was it just a test run?

Via Phoronix

OpenSSL Flaws

OpenSSL just fixed a pair of serious bugs in their 1.1.1k release. The first is CVE-2021-3449, which allows a malicious renegotiation request to crash the OpenSSL server. It’s a null pointer dereference, which is notoriously difficult to turn into a full RCE, though not impossible.

The second bug, CVE-2021-3450, is less annoying, but potentially more serious. If OpenSSL is configured to verify a certificate, and a certain strict mode flag is enabled, then a self-signed certificate could be accepted as a signed one. This happens because the strict mode check can overwrite the results of the trusted CA check.

Netmask Woes

There is a little quirk in how IP addresses are written. We normally write an IP in the “dotted decimal” format. Consider the three following IP addresses: 10.0.0.1, 010.0.0.1, and 0x10.0.0.1. The first two are identical and the last one is an invalid address, right? Well, it depends. If you’re sticking to what is considered “standard” dotted-decimal, then yes. But an early BSD implementation of dotted decimal notation also included hexadecimal and octal. This has become something of a competing standard, and pops up from time to time. See the image to the right for a surprising example.

Now, what about a library like NPM’s netmask, which checks whether a given IP address is part of a defined network? Netmask’s .contains function takes a dotted string as input, and returns true or false based on whether the IP is in the given subnet. In versions prior to 2.0.0, it understood decimal notation, and hexadecimal notation, but ignored the leading “0” otherwise. This means that an octal representation would instead be understood as decimal. This is a problem when other parts of your application see the IP as octal. The netmask sanity check thinks the IP is part of the local network (10.0.0.1), when it really belongs to Level 3 Communications (8.0.0.1). The security front-end sees the connection as coming from the local network, when it’s really coming from outside.

This little quirk was discovered by [Victor Viale], and fixed by a cadre of researchers who’s work we’ve looked at before. In fact, it was the earlier fixes to the private-ip package that led to this discovery. That package considers 0127.0.0.1 to be a private address. That’s correct… unless your code understands 0127.0.0.1 to be equivalent to 81.0.0.1. Let’s do a little experiment. Try to navigate to, or ping that IP address with the leading 0. What does your browser or terminal understand it as? The octal format is surprisingly widely accepted.

Now here’s the kicker. How do you fix this? Remember, there isn’t an RFC that explicitly defines how dotted notation of IPs works. I’m confident that some packages on NPM ignore leading zeros in IP addresses, and some OSes likely do the same. If you change netmask to understand octal notation, then those applications are now vulnerable in exactly the way you’re trying to fix. No matter what, something is going to break.

Semantic Versioning helps here, though it isn’t a silver bullet. NPM uses a 3-number system, starting with 1.0.0 for initial releases. For bug fixes that are otherwise backwards compatible, increment the third number. For updates with new features, but that don’t break compatibility, increment the second number. And finally, for major changes that do break backwards compatibility, the first number gets the bump. Netmask is no longer backwards compatible, so the fix was released as 2.0.0. Many applications are written with a flexible dependency section, allowing automatic updating on-the-fly when bug fixes are released, but not automatically switching major versions. It doesn’t automatically fix the problem, but again, that wasn’t really possible.

Ransomware Refund?

Bleeping Computer brings the story of a ransomware campaign that’s doing something unexpected — paying the ransom back to the victims. Well, that is the claim. No bitcoin has been paid back yet. The claim is that the malware authors are afraid of law enforcement action, and plan to become legitimate researchers after paying back the ransom. You’ll excuse me if I’m a bit skeptical, but this sounds too good to be true. Time will tell whether this is a second scam, or a true change of heart.

Researcher Campaign Redux

Remember the North Korean APT that was targeting researchers with a fake security company and malicious links? The folks at Google who keep track of these things, the Threat Actor Group, have warned that this campaign is back under a different name. “SecuriElite” is the new bogus company, and a new gang of fake researchers are active on Twitter and LinkedIn. That is, they were active until Google’s TAG raised the alarm. The attackers will likely go to ground for a week or two, and then pop up somewhere else.