When an organization has a breach, you would like to imagine that the attacker crafted a new exploit, leveraging a zero-day vulnerability that no one has any protection against. However, It is far more likely that the attacker exploited well-known vulnerabilities that may have been residing within their systems for months, if not years. Attackers run automated scripts to probe web apps for known vulnerabilities and then exploit the weaknesses discovered. A vast majority of attackers are not going to invest the time and effort to design a custom exploit to break into your systems. Especially if they can find security flaws within one of your applications or application’s dependencies easily. Using components with known vulnerabilities has been the cause of some of the most significant breaches to date, and it’s long-term status on the OWASP Top 10 list reflects this.
One of the most prevalent threats to the organization is not the unknown weakness, but the complexity of the web application itself. Most of the code in a modern web application is not original or built in-house. It is a loose collection of third party built and packaged parts cobbled together: APIs, microservices, libraries, open source & legacy code. Each one of those components are also systems with various subcomponents that need to be maintained in order to keep the whole web application functional and complete. Many security flaws originate through ancillary software dependencies with known issues that are overlooked, accepted as a risk, or not properly maintained. Often, these vulnerabilities are other OWASP Top 10 issues such as, Cross Site Scripting and Injection.
We typically view web applications as harbingers of the modern era. We view digital products and services as shiny, new and complete machines. The problem is these machines actually resemble a used pickup truck. There are holes in the upholstery, frequent engine troubles and many components are rusted over. If you want to get a better picture of web applications, imagine that several parts of this pickup machine rust, wear down, and break at different rates. Some of these parts weaken slowly over time, other parts lose their usefulness instantaneously. You frequently have to replace parts of it, otherwise it won’t function properly. It is the same with software in that it needs to be maintained to keep working as expected. Functional software is available, maintains the integrity of its data, and keeps private information confidential. By making applications more secure, you are making them more functional.
How to fix it
The resolution is to direct time and focus into a vulnerability management process. The first thing you need to do is gain a detailed understanding of the web apps you do have, what they do, how do they communicate with each other, and what libraries they are dependent upon. It is impossible to make large scale security improvements on a web application without a basic understanding of what it does and how information flows through it. You also need to take inventory of every library that is used within an application for both client and server applications.
Now knowing the expected functionality of that application, you’ll need to trim the fat. You need to remove unused dependencies, unnecessary features, unreferenced files, and documentation. This will reduce the attack surface of your application, but it will also make maintaining your application easier. There are a variety of tools available that can help detect this: retire.js, and dependabot are good examples. Many package managers, like npm, also come with the ability to audit dependencies and of course there is plenty of open source tooling in this space as well.
Then you need to continue monitoring your applications for end of life (EOL) software and unmaintained frameworks and libraries. Once detected, these dependencies need to be removed as soon as possible. Now that all the fat has been removed, a process should be created to update the components that are outdated or known to be vulnerable.
Finally, you need to prevent vulnerable components from being integrated into the web application. When you bring in new dependencies, only acquire them from official sources through secure channels. New components should only be included if they truly provide a feature that is not supported by anything else within the application as is. It’s not realistic to never bring in any third party dependencies; by restricting yourself to components written and maintained internally, you’re actually making yourself inefficient and you will lose your competitive edge.
By following these steps, you’ll have a process for removing components with known vulnerabilities from your application. There is also another benefit: If you have this process in place, you have a way to track and resolve all bugs relating to your application. Security vulnerabilities are just bugs that have a negative impact on availability, integrity, or confidentiality of a given system. Security patches are just one type of bugfix. Implementing a solid patch management program will help you maintain a secure and functional web application.