Executive Summary
Update: since publication of this blog, new, malicious packages attributable to the accounts identified in our original report appeared on npm. In addition, new CDN (content distribution network) infrastructure was identified being used for script inclusion. We have updated our blog post to include the latest information and will continue updating it as new threats or information become available. (July 6, 2022)
ReversingLabs researchers recently discovered evidence of a widespread software supply chain attack involving malicious Javascript packages offered via the npm package manager. Researchers at ReversingLabs identified more than two dozen npm packages, dating back six months, that contain obfuscated Javascript designed to steal form data from individuals using applications or websites where the malicious packages had been deployed.
Upon closer inspection, we discovered evidence of a coordinated supply chain attack, with a large number of npm packages containing jQuery scripts designed to steal form data from deployed applications that include them. While the full extent of this attack isn’t yet known, the malicious packages we discovered are likely used by hundreds, if not thousands of downstream mobile and desktop applications as well as websites. In one case, a malicious package had been downloaded more than 17,000 times.
As with the recent (benign) dependency confusion attacks targeting German organizations, these clearly malicious attacks relied on typo-squatting, a technique in which attackers offer up packages via public repositories with names that are similar to — or common misspellings of — legitimate packages. Attackers impersonated high-traffic npm modules like umbrellajs and packages published by ionic.io. However, it is the end users of software (and their data) rather than development organizations that are the real targets. That makes this attack more comparable to the infamous SolarWinds compromise than to other, more recent supply chain compromises. Furthermore, similarities between the domains used to exfiltrate data suggest that the various modules in this campaign are in the control of a single actor.
Here’s detailed information on this widespread software supply chain attack, including known indicators of compromise (IOCs) associated with the attacks — and recommendations for remediating the threat posed by these malicious npm modules.
[ Watch Karlo Zanki's discussion about his IconBurst research on ConversingLabs ]
Introduction
The ReversingLabs research team is continuously monitoring open-source package repositories for instances of malicious code planting and software supply chain attacks. This work involves both automated and human-led scanning and analysis of packages published in the most popular public package repositories like npm, PyPI, Ruby and NuGet. During these scans, we leverage our proprietary Titanium platform, and our deep file repository of goodware and badware to spot malicious and even suspicious elements hiding in plain view. Our newly released ReversingLabs Software Supply Chain Security platform builds upon that past work. The platform provides a way for dev and SOC teams to deeply examine their CI/CD workflows, containers and release packages to spot nascent or active software supply chain compromises.
Frequently, our work turns up evidence of active software supply chain attacks. In April, we came across npm packages that used a javascript obfuscator to hide their functionality. Our analysis of those packages produced proof of the simulated “dependency confusion” attacks on the software supply chain of leading German companies across a number of industries. We have been tracking npm repositories for occurrences of packages that use the same obfuscator ever since.
Here’s how tracking the usage of this obfuscation technique resulted in discovering several npm accounts, which were used to publish malicious code designed to steal form data entered by end users of infected web applications.
Discussion
The core capability of ReversingLabs’ secure.software solution is analyzing code intent while highlighting malicious behaviors. These indicators cover all kinds of software behavior, from network and file system activities to use of packers associated with malicious campaigns, and the use of evasion techniques.
Got obfuscation?
One technique we’re increasingly attuned to is the use of javascript obfuscator, a goodware component that is intended (mostly) to protect Javascript applications from the prying eyes of those who seek to steal or reverse engineer the code. Despite the respectable bona fides of javascript obfuscator and its laudable purpose, our past research revealed several instances of malicious packages using this tool to disguise malicious code. At this point, every encounter with such behavior requires a closer look.
The presence of a javascript obfuscator was the indicator that initially got our team looking at a wide range of npm packages, mostly published in the last two months, all using the mentioned obfuscator. In total, we discovered more than two dozen npm packages. When we looked at the names of those packages, we noticed some striking similarities. To show you what we mean, check out the following list of suspect packages.
Figure 1: Similarly named packages using javascript obfuscator
Can you spot the pattern? A deeper investigation into these npm modules reveals even more connections. All were connected to one of a handful of npm accounts with names like ionic-io; arpanrizki; kbrstore; and aselole.
Obfuscated code found stealing form data
To figure out what was going on with these packages, our team started by de-obfuscating the package content using a javascript deobfuscator. We followed that with a detailed examination of the de-obfuscated samples, which revealed that all of them perform collection of form data using jQuery Ajax functions, and then exfiltrate that data to various domains controlled by malicious authors. In other words: This is clear evidence of malicious intent.
Clearly, the typosquatting technique used to fool developers into confusing the malicious packages with their legitimate counterparts was working. Packages created by the npm ionic-io author, for example, show that the author published 18 versions of an npm package named icon-package containing the malicious form stealing code. That was a glaring attempt to mislead developers into using this package instead of ionicons, a popular, open-source icon set with more than 1,000 icons for web, iOS, Android, and desktop apps.
Figure 2: Version data related to icon-package
Download stats from npm show that the malicious icon-package has over 17,000 downloads. Data exfiltrated using this package passes through a domain hxxps://ionicio.com, a play on the legitimate ionicons framework domain ionic.io that would be easy for application developers to overlook. The ruse extends beyond the npm ecosystem, though. Note the visual similarity between the fake ionic web page seen in Figure 3 and the legitimate ionic page in Figure 4.
Figure 3: Fake ionic webpage
Figure 4: Legitimate ionic webpage
Under the hood, the malicious packages use a modified script that extends the behavior of the jQuery ajax() function to exfiltrate serialized form data to domains controlled by the attacker. Prior to sending the data, the function validates the URL content to perform target filtering checks.
The trail begins in December 2021
In the process of tracing the origin of the campaign, even older packages containing this type of malicious functionality were discovered. They were published in December 2021 by the author fontsawesome, and also targeted the already mentioned ionicons icon set. The domain used for data exfiltration in these packages is the same as the one used in the first two versions of the icon-package package: hxxps://graph-googleapis.com.
While the exact start of this campaign is unknown, the malicious package published from December 2021 all the way to the middle of May 2022 focused on mimicking the ionicons framework. At that point, the attackers switched to developing new npm packages that reused the same functionality and also started targeting other popular UI frameworks.
One of those packages is called umbrellaks, which is an obvious attempt at a typosquatting attack on the quite popular umbrellajs javascript DOM (document object model) manipulation framework.
We also observed several packages published by the npm account arpanrizki engaging in similar form data-grabbing. However, the exfiltration domain associated with these packages is different: hxxps://arpanrizki.my.id. The form identifier for exfiltrated data was quite specific: ValidateVerificationDataForm. So, as part of our investigation, we performed a GitHub search for this identifier, with some interesting results. (See Figure 5.)
Figure 5: GitHub search results
As the results show, one of the GitHub repositories containing the string in question were maintained by arpantek, a nickname very similar to the one of the npm author. The other result was related to a HackingTool repository belonging to the npm author Woxruz.
Figure 6: Woxruz’s HackingTool
The last commit’s description gives us a clue of the intended use for these software projects. These tools were designed for “Hacking PUBG i’d” [sic]. PUBG is a popular online-multiplayer video game with a large number of users. In other words, it seems the person behind the arpantek and arpanrizki accounts tried to port the login stealing script to the npm ecosystem to expand the reach.
Names of the packages published by arpanrizki also suggest they are targeting popular Javascript frameworks like ionicons and sidr. In particular, the sidr npm package hasn’t been maintained for 6 years, but still has more than 500 weekly downloads, which makes it a good target. Packages published by this author have since been removed from npm and replaced with security placeholders. The sidr package description confirms that in this phase of the campaign, the main target of the actor behind arpanrizki account were PUBG users.
Figure 7: sidr package description and the content of the referenced website
Hungry for data
While the malicious packages we initially observed took a conservative approach to harvesting form data, the more recently published malicious packages are taking a more aggressive approach to acquiring data. Another malicious package we identified, footericon, gathers data from all form elements with a defined “login-form” class.
Figure 8: Form data exfiltration code from footericon package
Similarly, the swiper-bundIe package, a malicious npm package targeting the popular Javascript framework swiper, uses the embedded jQuery approach, extending its end() function with functionality that gathers data from every form element on the page.
Figure 9: Form data exfiltration code from swiper-bundIe package
Clues hidden in code
While we can’t yet identify the actor(s) responsible for these attacks, clues as to the structure of the campaign abound in the deployed packages. For example, the swiper-bundIe package contains a Javascript header in the payload script with cleartext comments that name the author of the package as Alberto Varela, the author of the sidr package targeted by the arpanrizki author. Similarly, the long, commented Javascript one-liner also contains several references to the sidr package.
Figure 10: Comment header at the beginning of the payload from swiper-bundIe package
Finally, the malicious packages use exfiltration domains with a consistent naming pattern: <subdomain>.my.id. Together, these clues suggest a common actor behind the various malicious packages and a unified campaign.
List of malicious npm modules
Author / Package name | Download count |
fontsawesome | |
ionic-icon | 108 |
ionicio | 3,724 |
ionic-io | |
icon-package | 17,774 |
ajax-libs | 2,440 |
umbrellaks | 686 |
ajax-library | 530 |
arpanrizki | |
iconion-package | 101 |
package-sidr | 91 |
kbrstore | 89 |
icons-package | 380 |
subek | 99 |
package-show | 103 |
package-icon | 122 |
kbrstore | |
icons-packages | 170 |
ionicon-package | 64 |
icons-pack | 49 |
pack-icons | 468 |
ionicons-pack | 89 |
aselole | |
package-ionicons | 144 |
package-ionicon | 57 |
base64-javascript | 40 |
ionicons-js | 38 |
ionicons-json | 39 |
footericon | |
footericon | 1,903 |
ajax-libz | |
roar-01 | 40 |
roar-02 | 37 |
wkwk100 | 38 |
swiper-bundie | 39 |
ajax-libz | 40 |
swiper-bundle | 185 |
atez | 43 |
ajax-googleapis | 38 |
tezdoank | 69 |
ryucha | |
ajaxapis | 40 |
tescodek | 38 |
atezzz | 114 |
libz.jquery | 160 |
ajax-libary | 36 |
kabarstre | |
icon-ionicon | 384 |
icon-ionicons | 65 |
arpan-package | 109 |
ion-package | 254 |
package-ion | 98 |
ionpackages | 67 |
ionpackagesa | 96 |
ditznesiaa | |
basencrypt | 73 |
basecrypt | 174 |
cdnpjs | 87 |
cndpjs | 42 |
pattern.json | 44 |
rakaganz | |
rochman | 135 |
footericonfootericon | 169 |
footericons | 245 |
sdomino | 96 |
codashop | 78 |
freefire | 64 |
true_id | 66 |
rakaws | |
logo-facebook | 183 |
jubaa | |
ajax-libss | 48 |
Table 1: List of malicious packages with corresponding download count
Conclusion
ReversingLabs’ research uncovered an extensive software supply chain attack involving more than two dozen npm modules used by thousands of downstream applications, as indicated by the package download counts.
Analysis of the modules reveals evidence of coordination, with malicious modules traceable to a small number of npm publishers, and consistent patterns in supporting infrastructure such as exfiltration domains. ReversingLabs reached out to the npm security team to report the findings on July 1, 2022.
This attack marks a significant escalation in software supply chain attacks. Malicious code bundled within the npm modules is running within an unknown number of mobile and desktop applications and web pages, harvesting untold amounts of user data. The npm modules our team identified have been collectively downloaded more than 27,000 times. As very few development organizations have the ability to detect malicious code within open source libraries and modules, the attacks persisted for months before coming to our attention. While a few of the named packages have been removed from npm, most are still available for download at the time of this report.
In publishing this report, we hope it serves as a resource for development organizations to assess their own exposure to these malicious npm modules. We have prepared a list of affected modules and indicators of compromise that organizations can use to look for evidence of active attacks.
Looking beyond this specific incident, it is clear that software development organizations as well as their customers need new tools and processes for assessing supply chain risks like the ones posed by these malicious npm packages. The decentralized and modular nature of application development means that applications and services are only as strong as their least secure component. The success of this attack — with more than two dozen malicious modules available for download on a popular package repository, and one of them with 17,000 downloads in a matter of weeks — underscores the freewheeling nature of application development, and the low barriers to malicious or even vulnerable code entering sensitive applications and IT environments.
Indicators of Compromise (IoC)
C2 domains extracted from the analyzed npm packages:
graph-googleapis.com
ionicio.com
curls.safhosting.xyz
arpanrizki.my.id
dnster.my.id
okep.renznesia.xyz
ryucha.my.id
panelllgege.001www.com
nge.scrp.my.id
apiii-xyz.yogax.my.id
panel.archodex.xyz
panel.curlz.online
api.mlbb-x-02.ml
Package versions:
Package Name | Package Version | SHA1 |
ionic-icon | 4.7.0 | 8ab228743d3fef5c89aa55c7d3a714361249eba8 |
ionicio | 5.0.0 | f0221e1707075e2976010d279494bb73f0b169c7 |
icon-package | 5.0.0 | 9299a3eb1f11fcc090c7584bb9ce895ba38fd2cb |
icon-package | 5.1.0 | 6092606456adce8eb705ba33ad3e9536682d917f |
icon-package | 5.2.0 | d106693abc732a93176085410c67c4581de28447 |
icon-package | 5.3.0 | 5a631ab46373251dade6dca5bb460b55bf738a64 |
icon-package | 5.4.0 | c173de3d3ee1dd0920ee5a3a4f80d8c280ce2697 |
icon-package | 5.5.0 | 49f2bc011d1beece62b7a4ed47818e288b71edb6 |
icon-package | 5.9.0 | cf8a7066865ab6d009e226096fa879867b8e61bc |
icon-package | 6.0.0 | 6e2b0d621bf6031beee18b897b2da5d93d3ce5e7 |
icon-package | 6.0.1 | 164ff2295b63434e8b260a46041669c98eab4235 |
icon-package | 6.0.2 | 96aca5e901bd8f1229683339766073e4e5d1de59 |
icon-package | 6.6.6 | 6253324c1d741c1be3ae20fd8262adb54530ee8b |
icon-package | 6.6.7 | c77eda629d2076663276bc48c7462ea07470dbdc |
icon-package | 6.6.8 | b7dc23a51469574205b0691944f4120e2d92e64d |
icon-package | 7.7.7 | 83e5ebd7f355b1655778a37db6b6953042fb77c4 |
icon-package | 7.7.8 | 123dad7d48c47486e9c226ad50b26b2ba5ec9fe2 |
icon-package | 7.7.9 | 17fef01df47ceb87b2755f4a18db23d8f7276d30 |
icon-package | 8.0.9 | ae70ef4e5a0bb522179e5d488ed56efb9ae5b4d9 |
icon-package | 9.0.0 | e66609e433e5b51a148889ff128bd7182fe22d4b |
ajax-libs | 9.0.1 | 54549337e60eede3d4dc6b52662c582449b66c40 |
ajax-libs | 9.0.2 | fd72a461bb62dce8989f1c24bdcc6ae6d4eaabc5 |
ajax-libs | 9.0.3 | 66c41baf38e29c4b0a979cff35df4a1eed11e13e |
umbrellaks | 1.0.0 | 81031febc2ed49bdd8c8f7ca810830df1b0d3476 |
ajax-library | 1.0.0 | 326dab8f5d4dab461ca5fd14f136503d12227eae |
ajax-library | 1.0.1 | 2afd6730426166f061d96a8ccbfba8d8c7ed9e3e |
iconion-package | 1.0.0 | 73db956f7f752c4f71a8a8588604fa7d7af7de7e |
package-sidr | 2.2.2 | 87cb0505dbb141391103e2bd358f3aa774210a4a |
kbrstore | 1.0.0 | 7e14150502ee992fc8b1259de58261aeb2f58ae1 |
icons-package | 4.4.4 | fb672c0b982542eeacce66be67a5bc4ff9567596 |
icons-package | 4.4.5 | a386ddf8fb1d0846e01501f6fbac11e0389ef581 |
icons-package | 2.2.2 | a5ad7a0edda67b7267694898a82abbee1ec7a466 |
icons-package | 3.0.9 | 20254c86209118144e6a25fb90abea6f7c903d8e |
subek | 1.0.0 | 68d1c1883cfab75fa933ab08189ba7abbd2625a8 |
package-show | 5.5.9 | def789dc6322255264703c00d4f4dd265a48b50e |
package-icon | 6.0.5 | 1a719f2efa398ef8659a401e6209377beab87105 |
icons-packages | 7.4.0 | a2d25c070750cbd20f0c327980a40c26f4ea47ec |
ionicon-package | 9.0.3 | f78a57ab8e288c725e452787f3b070ec690f276b |
icons-pack | 7.8.3 | 6388e354433f8c608ab8a97ed9391b9dc44d2a99 |
pack-icons | 2.4.3 | cda4b444744196ae9b2753830f750bc5e4548061 |
package-ionicons | 8.0.5 | abb8ff44d224b23266769d0808ebe97c3838e484 |
package-ionicon | 8.0.5 | c11d9aa077207adeef30cfdd9df3fe979e114b06 |
footericon | 1.0.0 | 067e42878df480c0d1ca45c268300c96a258be63 |
footericon | 3.7.1 | 06dbd365e76e7cb593df86a80385e8c46ca05545 |
footericon | 3.7.0 | 8562edf90e988f7ca556183c2f032bc307dfefdb |
footericon | 3.7.3 | 08bc77bb17b6a4ab365d0354683cbd912219becf |
footericon | 1.7.9 | 9f5f2f34f15a03c4528d6fa632899d0e3b6d1ceb |
roar-01 | 1.0.0 | 8c128c3be9645582db2fee9e64e175149d51d92c |
roar-02 | 1.0.0 | a1e2cb98d2aa1b134b3be04d6a720393dcf6c072 |
wkwk100 | 3.4.5 | 9f2a2001a07b92adef023ca697e4febba073728e |
swiper-bundie | 10.5.3 | b64a10493897c96feb6eda1d0c9fc7ec85506258 |
ajax-libz | 1.0.0 | dd01c6baadd1d79f29b3d69a300e82b860edc57d |
swiper-bundle | 1.0.0 | 05d2084e1b2ce1d28c3096f16694413ec480704e |
swiper-bundle | 3.7.1 | 1de14d6be4029aa7888f8fc83779b61c96c063da |
swiper-bundle | 10.52.3 | 06cb7b1810ca1485e15fa81d92bd92533ff8c001 |
swiper-bundle | 10.22.3 | fa234405c958a9ff22bac7debfbcde452294d73c |
swiper-bundle | 10.21.3 | 64cd1eda88f92b32323f9784aab6d1a0bdd7a38c |
ionicons-pack | 1.5.2 | fe59a8d59f6764800ce5b85f2bfbc4db05840bae |
base64-javascript | 3.7.2 | 77170de7458ee81382efd7de2499694a459abee3 |
ionicons-js | 5.0.2 | 069f9c723af8be981a3e6220b991b9c40320d8b5 |
ionicons-json | 5.0.2 | 52a96612e3d2df0a7980de81d622da6c5ff84513 |
atez | 1.0.0 | c6569dc3fd94f642cad56cb7a950175ff7c2062f |
ajax-googleapis | 1.0.0 | 77a0f0cc89e98b9662b224b653a35895d3ac69fa |
tezdoank | 1.0.0 | eec7e3769b4d8b23aeb00f81583750ed26fadc47 |
tezdoank | 2.0.0 | 5ba35812337b3c7a0064accf17479a26de486951 |
ajaxapis | 1.0.0. | 2a8c46d643d3027b3815eecbbfd183a7dee9e91d |
tescodek | 6.0.0. | 8304b8c9549d08e3c258ce22f99587843bb52c00 |
atezzz | 1.0.0. | bc494a3249ce95b7cea5a62e29ee3cc023e2b5b1 |
atezzz | 2.0.0. | e2bc4408cea300c0f852e16665e7279cf5d0cd69 |
atezzz | 3.0.0. | b5b8d49f302cfeee5cb4dcf134320861c9fdaa66 |
libz.jquery | 1.0.0. | 9a41b333143eb0ad75bb93288a988ec8387379ca |
libz.jquery | 3.6.1. | fd7197e446107ba047a2fa43814cdecc794b3dae |
libz.jquery | 3.6.0. | 1517b34ed31cf3f2815105d344dd0b845d48d092 |
libz.jquery | 3.6.3. | 4e30e0d1cf39cdaf5f03b7afda81aa2aed6a6d5d |
ajax-libary | 2.0.3. | 50d681e5c016904b0080ad70f40abb86926849a0 |
icon-ionicon | 2.4.3 | 6132a31838fa836aeadbbe39054de9fa702c8fbb |
icon-ionicons | 2.4.3 | a28477cc116aa0de478014d6f4adb1603cdd6bb1 |
arpan-package | 2.0.5 | 8dfd7a91308508b859bf464df375030e6231602f |
ion-package | 2.4.3-Base | 5f66bb7a4df11b16238de0c1ad33dddafec779f4 |
package-ion | 2.4.3-icons | f7d09b4429f59e136796a70410b689754c355708 |
basencrypt | 2.0.0 | 9c11c8512ae2f1ed0d4e7ece99e7aa42dd77d4e2 |
basecrypt | 3.1.0 | 45162797b66a8ea41f530468bca09b5f783383f4 |
cdnpjs | 4.5.0 | a3c9595043120c3471c58d6fa43893f34c12b402 |
cndpjs | 4.5.2 | 2b112481f4adba7b840a397bad7d00acb59ee256 |
cdnpjs | 4.5.8 | 7e5228665b9396b60c3c7b7024bb948cc45c4a84 |
pattern.json | 4.12.7 | 879699f620acf2b9c7d24a5fd89e008ac60f4b57 |
rochman | 1.0.0 | 07280f0b4ec2db03143e1f7add5fd0a04f9b7f3b |
rochman | 3.6.0 | dfbcb2e7e3fc7444415fc5575d8d2a793f9ae668 |
footericonfootericon | 3.7.1 | 9b8b5fa9e36ed902045ca5de26c00ddd9a035d36 |
footericons | 3.7.1 | b38aa72b39fc015c0366e11d072de0947266e884 |
sdomino | 7.9.0 | ae603d5a3d8360d076a62d9622679d1a0c79b395 |
footericons | 4.8.0 | f0fff262a3dda9b8ca0e0cfedd1808ec0342be75 |
codashop | 5.6.0 | 6353469679f07b8d6f5870c1e211b17bd575ea89 |
freefire | 7.9.0 | a6ef2f3538571db4119d5466b9a3d2a91a984bcc |
true_id | 8.3.0 | e00999f831120a0fc5b37986c0e2d1af947caf0b |
ionpackages | 2.2.1-Base | 925c585c1b1507bf29deb89a4db9fe1f90721140 |
ionpackagesa | 2.4.5-icons | 9b1d41d813067d16de7a77512cf205603cb555fa |
logo-facebook | 4.8.2 | ec731509e1478decc6020f9dd57b196853f456c5 |
ajax-libss | 3.6.0 | ff862d407422fcca070f726e0aa477c9a93b270b |
Complete affected package list:
https://blog.reversinglabs.com/hubfs/Blog/IconBurst/package_versions.tsv
Keep learning
- Find the best building blocks for your next app with RL's Spectra Assure Community, where you can quickly search the latest safe packages on npm, PyPI and RubyGems.
- Get up to speed on securing AI/ML systems and software with our Special Report. Plus, see the Webinar: The MLephant in the Room.
- Learn about complex binary analysis and why it is critical to software supply chain security in our Special Report. Plus: Take a deep dive with RL's white paper.
Explore RL's Spectra suite: Spectra Assure for software supply chain security, Spectra Detect for scalable file analysis, Spectra Analyze for malware analysis and threat hunting, and Spectra Intelligence for reputation data and intelligence.