- Over the past several years, high-profile software supply chain attacks have increased in frequency. These attacks can be difficult to detect and source code repositories became a key focus of this research.
- Developer account takeovers present a substantial risk to the software supply chain because attackers who successfully compromise a developer account could conceal malicious code in software packages used by others.
- Talos analyzed several of the major software repositories to assess the level of developer account security, focusing specifically on whether developer accounts could be recovered by re-registering expired domain names and triggering password resets.
- Many software repositories have already begun taking steps to enhance the security of developer accounts. Talos has identified additional areas where the security of developer accounts could be improved. Talos worked with vulnerable repositories to resolve issues that we found.
Software supply chain attacks, once the exclusive province of sophisticated state-sponsored attackers, have been gaining popularity recently among a broader range of cyber criminals. Attackers everywhere have realized that software supply chain attacks can be very effective, and can result in a large number of compromised victims. Software supply chain attacks more than tripled in 2021 when compared with 2020.
Why are software supply chain attacks so effective? Organizations that possess solid cyber defenses may be difficult to attack directly. However, these same organizations are likely vulnerable to a software supply chain attack because they still regularly run/build software obtained from vendors who are trusted.
Rather than attacking an entire software repository itself, or identifying an unpatched vulnerability in a software package, compromising the software supply chain can be as simple as attacking the accounts of the package developers and maintainers. Most software repositories track the identities of their software developers using those developers' email addresses. If a cybercriminal somehow gains access to a developer's email account, the attacker can theoretically generate password reset emails at these software repositories and take over the account belonging to that developer. Once inside, an attacker could then publish malicious updates to the code maintained by that developer, affecting every other piece of software that uses that library from then on.
Cisco Talos examined several frequently used code repositories. We looked specifically at the security afforded to developer accounts, and how difficult it would be for an attacker to take over a developer account. While some repositories had stringent security in place, others did not. Fortunately, worked with the managers of these repositories to resolve the major issues we found.
Risks in the software supply chain
Re-inventing the wheel is typically not a good idea. This holds true for many things, including developing software. Much software written today depends on third-party packages and software libraries to facilitate necessary functionality contained in the program. Utilizing third-party libraries and packages, especially open source, also speeds up development and lowers costs.
Popular software packages have also become attractive targets for attackers. The more popular a software library is, the more external software will be using that library, and thus, the larger the potential attack surface. Compromising a software library can potentially compromise every other piece of software that relies on that software library for its functionality. This is the risk inherent in the software supply chain.
With the exception of language-agnostic repositories like GitHub, most software repositories tend to be language specific. For example, JavaScript authors rely mostly on NPM, Python developers have PyPI, Perl programmers can often be found using packages obtained via CPAN, and so on. Each software repository sets its own rules when it comes to developers' accounts.
Additionally, as many programmers are aware, some programming languages make a better choice for solving certain types of problems. For example, embedded systems drivers are more commonly written in C instead of Perl, while parsing text is more commonly done in Perl or Python, rather than C. This means that the process of writing programs that integrate third-party libraries into the code will also be different for each language. It is difficult to imagine a developer integrating a third-party library into a system-level driver written in C without carefully reviewing the related code and testing it for speed and functionality. However, when developing a feature-rich Perl proof-of-concept application or a web-based JavaScript application, this might not always be the case. A programmer in those instances might conceivably import a package first and ask questions later. This means some software repositories will carry more risk than others when it comes to malware hiding in the source code.
NPM
Node Package Manager is a JavaScript software repository and has been the subject of some "independent" security audits recently. There has been a lot of discussion online, especially concerning the security of the developer accounts there, and how easy it is to take over these accounts by re-registering expired email domains.
There are more than 2 million packages in the NPM repository. Conveniently, an NPM package called "all-the-package-names" contains a list of all packages in the NPM repository. Each individual package at NPM has associated metadata, such as a text description of the package, a link to the package tarball, and a list of the package maintainers. Most importantly, the list of package maintainers has the developer's username and email address.
Iterating through all the package names, and extracting the email addresses, then further extracting the domain names from those email addresses, provides the raw data necessary to find developer accounts associated with expired domains. Once an expired domain is found, it can be re-registered and theoretically used to take over the NPM developer account. But does it work this way in practice?
Although we found a couple thousand expired developer account domain names, we could not recover the associated developer accounts. It appears the "couple things in place to protect against [account takeover]" that NPM administrator @MylesBorins mentioned in his tweet above are working as planned.
Stale metadata helps foil attackers
NPM provides developers with the ability to update the email address associated with their accounts. When a developer decides to switch email addresses, only the future package/version's metadata will contain the new email address. NPM does not retroactively update old metadata associated with a package that was previously published. This means that, even though someone looking to take over an NPM developer account might find package metadata indicating a developer with an expired email domain, it could simply be that the developer has updated their NPM account to a new email address.
This was the case in May 2022, when a security researcher claimed to have taken over the NPM package "foreach" by re-registering the email domain belonging to the NPM developer. Unbeknownst to the security researcher, the developer in question had actually updated their NPM account to use their Gmail address instead. So if any password recovery attempts were made, they would have failed — NPM would have generated and sent the password reset emails to the new Gmail account on file, which is still under the original developer's control.
PyPI
PyPI is the Python Package Index and currently contains almost 400,000 projects. Developers at PyPI have email addresses associated with their accounts, however, PyPI does not display the email address publicly by default. This is an option that the developer must explicitly choose to enable. Many developers are, of course, eager to interact with others who are running their code, so it is no surprise that large numbers of developers enable this feature.
PyPI accounts do not come with MFA enabled by default, so this is something else a developer would have to choose to enable. However, in July 2020 PyPi announced that it was rolling out mandatory MFA to "critical projects," a.k.a. the top 1% of the projects at PyPi (based on the number of downloads).
A list of all PyPI packages is available online. Many of these packages contain a mailto: link containing an email address. There is also a list of maintainers of the package. For developers that expose their email addresses publicly, it's found on the user's public profile page. It is a relatively simple process to scrape the email addresses associated with PyPI projects. PyPI reveals whether an email address is associated with an account (but it probably should not).
Account takeovers have been a problem at PyPI in the past. As recently as May 14, 2022, an attacker managed to take over a developer account and replaced the "ctx" package, adding malicious code that stole the user's environment variables, base64-encoded them and transmitted the data back to the attacker's C2 server. Fortunately, the changes made by the admins over at PyPI seem to be moving account security in the right direction.
CPAN
The Comprehensive Perl Archive Network (CPAN) contains more than 200,000 Perl modules. CPAN also provides an index of all the module authors.
The individual module authors each have their own "homepage" that lists their contributed modules. For anyone who wants to reach out to the dev, CPAN includes the author's email address.
A motivated attacker can easily scrape the CPAN website for a list of all author IDs and use those to scrape the email address belonging to the developers. A whois search on the email domain of the developer email addresses provides us with a list of developer accounts that are vulnerable to account takeover. From there, all that is required is standing the domain up somewhere and running a mail server. Triggering a password reset provides us with the magic link to get into the developer's account.
Talos has reached out to the admins at CPAN and provided them with a list of the vulnerable developer accounts we found. CPAN has disabled these accounts.
NuGet
NuGet is a software repository for .NET developers. The NuGet "gallery" contains more than 317,000 packages. Fortunately, registered developers at NuGet have their email addresses hidden by default. There is an option to allow users to contact you, using a form on the NuGet website that does not disclose the email address of the developer. Developers have the option of adding their Twitter handle, and many developers do. If an attacker wishes to attack NuGet developers en masse, they would have a very difficult time assembling a list of developer email addresses.
RubyGems
RubyGems is a software repository for Ruby developers. There are currently approximately 172,000 gems (packages) in the repository. Developer email addresses are hidden from the public by default. Even unchecking the "Hide email in public profile" check box has no discernable effect, and the email address remains hidden.
Some gems have "maintainers" files to indicate the contact email addresses of the developers, but this is not consistent across gems. Recently, the RubyGems team announced that they are enforcing MFA for top developer accounts.
Conclusion
The software supply chain attack problem is not likely to go away anytime soon. It is unreasonable to ask organizations to vet every piece of software that runs in their environment. Some amount of trust in software vendors and suppliers will always be necessary. However, that doesn't mean that defenders are helpless against these types of attacks.
Organizations should analyze what software is required on various internal systems. Many times, there may be opportunities to segment a group of systems running a particular piece of software from the rest of the internal network. This way, any compromise that occurs as a result of a software supply chain attack will be limited in scope. Obviously, there are limitations to this approach.
All parties in the software supply chain need to take more responsibility for security. For example, it would be far safer for software repositories to stop publishing or releasing any information related to a developer's email address. Yes, this is arguably a bit of security-by-obscurity, but it forces attackers to go elsewhere to correlate the email account of a developer with the particular software package in question, and greatly enhances the security of the repository. If a repository wishes to publish a developer's email address, it could instead give each developer an email address at the domain of the repository itself (ex., @npmjs.com, @cpan.org, etc.).
Forcing MFA on the most popular package maintainers also seems to be a sensible remedy that is currently being pursued by several repositories. However, security is always a delicate balance. If you sacrifice too much usability in the pursuit of security, developers may rebel, as was the case with PyPI developer "untitaker."
One sure-fire countermeasure against developer account takeover via expired domain registration is code signing. This is really the best way to be sure that the code you use has not been tampered with since it was last signed, and is indeed from a developer you trust. An attacker who gets control of a developer's expired domain name would have no way to recover the code signing keys belonging to that developer and no way to impersonate that developer.