Secure coding

Software dependencies: The silent killer behind the world's biggest attacks

Gilad Maayan
January 11, 2023 by
Gilad Maayan

An application dependency can be described as a technology component, other application or server on which an application depends to perform its functions. Software developers typically have a specific technology stack in mind when building solutions. This can typically include operating systems, database engines and development frameworks such as Node.js, Angular or Spring. In addition, many modern applications use APIs to receive data from external services. All of these are dependencies that the application will require to function correctly. 

Learn Secure Coding

Learn Secure Coding

Build your secure coding skills in C/C++, iOS, Java, .NET, Node.js, PHP and other languages.

Why managing Dependencies is Mandatory 

In the early days of software dependencies, downloading and installing the necessary libraries was daunting. However, in recent years dependency managers like npm in Node.js and Maven in Java have made it much more convenient, allowing developers to include many small software packages in their software projects. Today many software projects include hundreds or even thousands of third-party libraries, all of which become dependencies of the main software program.

However, dependencies create risks that are often overlooked. Using external software as a dependency means relying on its developers to properly write, test and maintain that code. In addition to possible security holes in the dependencies of these programs, they can become outdated, reduce the quality of the software project that uses them, or even result in failure and downtime. The more dependencies are used, the higher the risk faced by the organization that uses them.

To make things worse, many dependencies have additional packages that they depend on, resulting in transitive or chained dependencies. Updating one dependency can break the whole chain and result in unexpected consequences — this is known in developer parlance as “dependency hell.”

Despite these risks, many organizations pay little attention to dependency management. Most dependencies today are third-party open-source libraries with little or no guarantees concerning security or software quality. The first step to addressing this problem is gaining visibility over dependencies used in software projects. Beyond this, organizations must have a strategy to manage these dependencies and ensure they use only high-quality, secure libraries in their projects.

Software dependencies: The silent killer behind the world's biggest attacks 

SolarWinds

The cyberattack against SolarWinds was possibly the first global-scale supply chain attack. It involved a suspected national hacker group, Novellium, who gained access to thousands of networks, systems, and data managed by SolarWinds products. The attack started in 2020 but was discovered only in late 2021. Its breadth was unprecedented.

In this attack, hackers injected malicious code, known as the SUNBURST malware, into SolarWinds Orion system, a popular IT management system used by many large enterprises, including U.S. government agencies. Their approach was not to hack these networks directly but to target Orion — a third party with less stringent security measures, which had access to these large organizations.

Hackers penetrated SolarWinds’ development systems and created a malicious build of the Orion platform, creating a backdoor that allowed hackers to access and impersonate users and accounts of SolarWinds customers. The malware could access system files and infiltrate the legitimate activities of SolarWinds customers without being detected by antivirus software because SolarWinds itself was a trusted software product. 

Log4j 

The Apache Log4j project, one of the most widely distributed open-source software, provides logging capabilities for Java applications.

The Log4j exploit started as a bug but later evolved into a series of security issues with the root cause of the exploit in Log4j’s Java Naming and Directory Interface (JNDI) interfaces.

In 2021, CVE-2021-44228 was discovered — a remote code execution (RCE) vulnerability in several software versions. The RCE flaw is due to how Log4j interacts with JNDI without properly validating all requests. This means attackers who gain access to log messages can inject malicious messages to allow arbitrary code execution on vulnerable systems. 

The NIST National Vulnerability Database rated CVE-2021-44228 as 10.0, the highest possible severity score in the Common Vulnerability Scoring System. Hundreds of thousands of attacks were recorded in the days and weeks following the discovery of the vulnerability. 

Kaseya 

In 2021, many Managed Service Providers (MSPs) and their customers were victims of the REvil Group ransomware attack, resulting in extensive downtime for over 1,000 companies.

The focus of the attack was the Virtual System Manager (VSA), a remote monitoring and management software package developed by Kaseya. An authentication bypass vulnerability in the software could allow attackers to compromise VSA and distribute malicious payloads through a software-controlled host. 

In response, the company shut down its VSA cloud and SaaS servers and issued a security advisory to all customers, including customers using VSA on-premises.

4 Tips for addressing the risk of software dependencies 

Software dependency management recognizes that dependencies are unavoidable but aims to organize them and reduce risk. The software will inevitably have some dependencies — such as operating systems, graphics libraries, databases and other ready-made components. The focus is on identifying these dependencies and trying to minimize dependencies to those that are needed for the software project and do not represent excessive risk.

Here are a few ways to reduce the risk of software dependencies in your software project.

1. Map dependencies

You can only optimize if you know where your dependencies are. There are many tools to help with dependency mapping, including dedicated application dependency management (ADM) solutions and automated build tools. These tools help keep track of software dependencies in detail throughout the build and deployment process. 

Mapping dependencies provides visibility into the presence of vulnerabilities and important insights about where dependencies are used in the code and how and when they are called. This can help you find optimization opportunities. Another impact is on digital forensics efforts - identifying dependencies and their relationships can be critical for understanding and mitigating cyberattacks against complex software systems.

2. Eliminate unnecessary dependencies

It is important to consider how applications use third-party libraries and components. One application might use only a small subset of the functionality or features of an extensive utility library. Another application might include many smaller components. Eliminate any dependencies that are not actively used by the application. For those that are actively used, consider how to consolidate dependencies and avoid including dependencies with additional functionality that is not used by the application.

3. Use established repositories

Some environments, such as Linux, Java, Ruby and Python, have established free/libre and open source components repositories. Examples include npm for JavaScript, Maven for Java and the gem package manager for Ruby. Developers can easily download packages from these repositories and include them in their project builds. 

While this approach can support a more standardized development environment and reduce the impact of missing, outdated or incompatible dependencies, it does not guarantee quality or security. Even established repositories can include out-of-date, vulnerable or even malicious packages.

4. Scan all dependencies

Automated tools can scan third-party dependencies and identify risks, including security and compliance issues. The most common technology used for this purpose is software composition analysis (SCA), which provides a software bill of materials (SBOM) that details exactly what direct and transitive dependencies are included in your code. SCA checks for security issues by checking third-party libraries against publicly available vulnerability databases.

In addition, static application security testing (SAST) can scan the actual source code of third-party libraries for vulnerabilities, alerting you to security and quality issues, even if they are not publicized as vulnerabilities. High-priority alerts from SCA, SAST or similar tools should be taken seriously, and problematic packages should be removed or replaced.

Learn Secure Coding

Learn Secure Coding

Build your secure coding skills in C/C++, iOS, Java, .NET, Node.js, PHP and other languages.

The "silent killer" that is software dependencies

I covered three global-scale cyberattacks that exploited vulnerable dependencies in their victims’ infrastructure. Finally, I provided four tips that can help mitigate the risk and prevent future attacks:

  1. Map dependencies - use automated tools to identify which dependencies exist in your environment and their relationships.
  2. Eliminate unnecessary dependencies - remove dependencies that are not required to reduce the attack surface.
  3. Use established repositories - ensure you obtain dependencies from reputable sources.
  4. Scan all dependencies - before using dependencies in your software, scan them to be aware of security or quality issues.

I hope this will be useful as you better understand the risk of software dependencies and begin to address it in your organization.

Gilad Maayan
Gilad Maayan

Gilad David Maayan is a technology writer who has worked with over 150 technology companies including SAP, Imperva, Samsung NEXT, NetApp and Ixia, producing technical and thought leadership content that elucidates technical solutions for developers and IT leadership. Today he heads Agile SEO, the leading marketing agency in the technology industry.