Once a security bug exists in your customer's networks, preventing a security breach involves a lot of moving parts, but most importantly:
- Identifying the security bugs before criminals do.
- Fixing the security bugs you've identified.
- Getting the patch deployed in all of your customer's networks.
Consider the timeline below:
The time between point 0 and point 1 might be years. For the Linux kernel, it's about 5 years on average. There are a lot of ways to reduce this number, and most of them involve automated testing and manual code review from security experts.
The time between point 1 and point 2 might be weeks or months. Our average vulnerability identified-to-fixed time window is less than 24 hours. Most organizations do not enjoy the same agility or expertise.
Most development teams have no control over the time between points 2 and 3 -- the amount of time it take for the fix to be applied (and the vulnerability to be neutralized) after the update is available.
By making updates manual rather than automatic, you're forcing your customers to take all the responsibility for making sure that your mistakes don't hurt their business. Only a very small minority of your customers might prefer the responsibility of verifying and applying each update themselves.
By and large, most people do not have the security awareness, time management, and discipline to undertake this responsibility 24/7/365.
Automatic security updates reduce the interval between points 2 and 3 from possibly infinite to nearly zero. That's clearly a meaningful improvement over manual patch management.
What's the Practical Risk in Outdated Software?
The problem of outdated software is well-studied by the information security industry. According to Verizon's 2015 Data Breach Investigations Report (PDF), for example, when a software vulnerability was used...
99.9% of the exploited vulnerabilities were compromised more than a year after the CVE was published.
In 2016, Wombat Security reflected on similar studies in an article titled Out-of-Date Software and Plug-ins Compound End-User Risk. An article on Help Net Security examines findings from F-Secure and echoes the problem of companies relying on out-dated software and putting their users at risk.
The danger of outdated software is supported by both the data and by simple logic: If criminals are aware of a specific vulnerability in a software product, it doesn't matter that the vendor published a security patch if most of the companies that use their product will remain vulnerable when criminals want to exploit it.
It Seems So Obvious, But...
If 99.9% of real-world software exploits are preventable by keeping software up-to-date, and the danger of unpatched vulnerabilities is well-known among security professionals, the obvious question is, "Why doesn't everything update itself automatically?"
Implementing a secure automatic update mechanism is a nontrivial engineering feat that most programmers don't even know where to begin addressing. And often the ones that think they do are uninformed about the risks and complexity.
Simple and Secure Automatic Software Updates
First, make sure your deliverables are reproducible from the source code. If you're working with scripting languages that are never compiled into binary code, this merely requires your software be open source.
Second, use an update framework (i.e The Update Framework) that enforces code signing. This means that your update files must be signed by a private key controlled only by you, but can be verified by anyone with your public key.
If you don't understand what "private key" or "public key" means, our other dev.to article is an approachable introduction to cryptography terms and concepts and will shed some light on the matter.
Finally, run a Chronicle instance. Every time you release an update, publish the new release information to your Chronicle. Make your code that interfaces with The Update Framework verify that the release you're seeing is also published in the Chronicle (or, especially for enterprise customers, their own replica of your Chronicle that resides on the corporate network).
That's it. The Update Framework (or a similar implementation relevant to your stack) and Chronicle are all you need (as far as tooling goes). Make your software open source, and your builds reproducible, and you'll drastically reduce your customer's attack surface in terms of both space and time.
Secure Automatic Software Updates in PHP
There isn't currently a PHP implementation of The Update Framework. If there's enough community interest, we may commit to building one in the future. However, that might not be necessary.
If you're developing modern PHP, you're almost certainly using Composer and Packagist. If not, it's highly recommended that you learn it ASAP.
In 2017, I opened a proposal to the Packagist team to run their own Chronicle instance, which would be used to publish information about software releases in real time. We're working on other proposals to enforce signature validation and solve the Public Key Infrastructure (PKI) problems.
In other words: If you're using Composer, then in the near future this may already be a solved problem for you.
Secure Automatic Updates for Embedded Devices and the Internet of Things (IoT)
Embedded development faces unique challenges and there hasn't been a lot of guidance on implementing secure automatic update protocols, especially for so-called "smart devices". Due to low memory or power usage requirements, it's often not feasible to just staple cryptography onto your product design without using up your entire power or memory budget.
For extremely constrained devices, libhydrogen is an attractive option. It's very lightweight, and the current implementation uses only two primitives to provide a full-featured cryptography library: the Gimli permutation and Curve25519.