February 18, 2021 | 9 min read
Amnon Even-Zohar

A supply-chain attack is an indirect attack which targets the tools, automatic software updates or supply chain in general, in order to introduce malicious code or dependencies into existing software, without the developers being aware. External package dependencies, which are fetched from public repositories during a build process, can pose an opportunity allowing attackers to add backdoors during builds and get access to the crown jewels.
This is the third post in our series on the history of supply chain attacks. This post will cover the importance of maintaining high password hygiene of developer accounts, keeping a strong authentication policy, following best practices when working with open source  packages and steps to reduce risks for supply chain attack, specifically on your build environment. 

The ESLint Attack

ESLint is a widely used static code analysis tool for identifying problematic patterns found in JavaScript code. It covers both code quality and coding style issues. Rules in ESLint are configurable, and customized rules can be defined and loaded.
In 2018, ESLint was targeted in yet another supply chain attack. An attacker compromised the npm account of an ESLint maintainer via a third-party breach, revealing that he had used the same login and password details across multiple accounts and did not have two-factor authentication enabled on his npm account. The attacker was thus able to test leaked logins from other breaches against the npm account, a method known as “credential stuffing”.
After compromise, the attacker modified package.json in both eslint-escope@3.7.2 and eslint-config-eslint@5.0.2, adding a postinstall script to run build.js and uploaded to the npm registry.

  • eslint-scope@3.7, a scope analysis library, is a dependency of several popular packages, including some older versions of eslint and the latest versions of babel-eslint and webpack.
  • eslint-config-eslint@5.0 is a configuration used internally by the ESLint team, with very little usage elsewhere.

On installation, the malicious packages downloaded and executed code from pastebin.com which sent the contents of the user’s .npmrc file to the attacker. An .npmrc file typically contains access tokens for publishing to npm. In this case, these malicious packages were spotted in about 40 minutes. Once the ESLint team was notified, the pastebin.com link containing malicious code was taken down. The npm team unpublished eslint-scope@3.7.2 after being contacted by an ESLint maintainer, and ESLint team published eslint-scope@3.7.3 with the code from eslint-scope@3.7.1 so that caches could pick up the new version. npm revoked all access tokens generated before 2018-07-12 12:30 UTC (an hour or so since the attack was reported). As a result, all access tokens compromised by this attack should no longer be usable. 40 minutes sounds like a short time, but npm is seeing ~2B downloads per day, so only 54M downloads occurred during this time. For each one that was ESLint, the attacker got publish control of that next user’s repo. And so on, potentially causing a wide impact.

It is worth mentioning that at the same year, Gentoo was attacked in the same manner due to a developer using a weak password across multiple sites, including a GitHub account.  By stealing the victim’s GitHub account, where Gentoo kept backups of its source code, the attacker was able add their own malicious code, designed to wipe user content, to the repository.  Meanwhile, the account’s actual owner was locked out for nearly an entire week.  In fact, the user losing access to the account was the only way the attack was even detected. In the aftermath, Gentoo had to declare all of their source code compromised and reverted to previous uncompromised commits. 

Takeaways

The ESLint attack (as well as the one on Gentoo) not only revealed just how critical the practice of good password hygiene really is but demonstrated just how dangerous malicious code can be when unleashed on a highly trusted point in the supply chain that most users take for granted without a second thought.  Worse yet, attackers with stolen accounts are often able to remain hidden for weeks or months at a time, allowing them space to target additional victims. With the hindsight of this incident, we have a few recommendations to reduce the risk of exposing to similar attacks and reduce their impact :

  • Maintain high password hygiene:
    • Avoid reusing the same password across multiple different sites. A password manager like 1Password or LastPass can help with this.
    • Enable two-factor authentication in your account. 
  • Follow open source packages secure development best practices:
    • Avoid as much as possible using any services that auto-merge dependency upgrades.
    • Use a lockfile (package-lock.json or yarn.lock) to prevent the auto-install of new packages.
  • Enforce least privilege policies to reduce the scope of access to your repositories, especially on people who have access to publish.
  • Continuously scan your source code repository for any secrets and access keys that can be obtained, if compromised.  If found, revoke and remove them to keep your repository as secure as possible.

How Cycode Can Help

Crises are a time for the community to come together. As such, Cycode is offering a free code repository security assessment to any organization that is looking to harden their development infrastructure. Alternatively, if there is some other way we can help your organization, please get in touch with us.