Parent : [[INDEX-CYBERSECU]]
Honeypot anti-extension - Detection de bypass via modal.min.js et ban définitif
Problème
Un script chargé sur toutes les pages, renommé de security.min.js à modal.min.js pour passer inaperçu. Le contenu est obfusqué en base64. Le script attend 2,5 secondes, puis cherche un élément .yggsearch-api-btn dans la page (une classe injectée par l'extension navigateur YGGMollo). Si l'élément est détecté, un formulaire caché soumet un POST silencieux vers /engine/gm. Le serveur log le user ID, le pseudo et l'IP dans extension_users.txt, puis ban définitivement le compte sans avertissement (sanction_5: "oo" = ban permanent).
Contexte archive Ygg
- Source :
https://yggleak.top/fr/home/ygg-dossier - Fichier :
modal.min.js(anciennementsecurity.min.js) - Extension ciblée : YGGMollo (extension Chrome pour contourner la limite de 5 téléchargements/jour)
- Endpoint :
/engine/gm(gm = get modal, nom anodin) - Log :
extension_users.txt - Sanction :
sanction_5: "oo"(ban permanent) - Victimes : 13+ utilisateurs identifiés dans
extension_users.txt
Technique de l'attaquant (site YGG)
1. Renommage pour passer inaperçu
Rename-Item -Path "assets\js\security.min.js" -NewName "modal.min.js"
2. Obfuscation en base64
var _c=[atob('LnlnZ3NlYXJjaC1hcGktYnRu'),atob('L2VuZ2luZS9nbQ==')];
// decode : selecteur = '.yggsearch-api-btn', endpoint = '/engine/gm'
3. Détection et ban
// Le script attend 2.5 secondes
setTimeout(() => {
const target = document.querySelector('.yggsearch-api-btn');
if (target) {
// Formulaire caché POST silencieux vers /engine/gm
const form = document.createElement('form');
form.action = '/engine/gm';
form.method = 'POST';
form.style.display = 'none';
document.body.appendChild(form);
form.submit();
// Ban définitif du compte (sans avertissement)
// sanction_5: "oo" = ban permanent
}
}, 2500);
4. Log des utilisateurs piégés
// extension_users.txt
user_id, pseudo, ip, timestamp
13225478, Tyuito, [REDACTED], 2025-12-25 04:06:07
4561732, Kono_yaro, X.X.X.X, 2025-12-25 04:06:17
Solution protectif — Détection de honeypot et protection
1. Détecter les honeypots de détection d'extension
// detect-honeypot.js — Détecter les scripts qui surveillent les extensions
(function() {
'use strict';
// Surveiller la création de formulaires cachés
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.tagName === 'FORM') {
const style = window.getComputedStyle(node);
const isHidden = style.display === 'none' || style.visibility === 'hidden';
if (isHidden && node.action && node.action.includes('/engine/')) {
console.warn('[HONEYPOT-DETECT] Formulaire caché suspect détecté!');
console.warn(' Action:', node.action);
console.warn(' Method:', node.method);
// Bloquer la soumission
node.addEventListener('submit', e => {
e.preventDefault();
console.warn('[HONEYPOT-BLOCK] Soumission bloquée');
}, true);
}
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
// Surveiller les requêtes POST silencieuses
const originalFetch = window.fetch;
window.fetch = function(url, options = {}) {
if (options.method === 'POST' && typeof url === 'string' && url.includes('/engine/')) {
console.warn('[HONEYPOT-DETECT] Requête POST suspecte:', url);
console.warn(' Body:', options.body);
// Bloquer la requête
return Promise.reject(new Error('Honeypot request blocked'));
}
return originalFetch.apply(this, arguments);
};
// Surveiller les setTimeout suspects (2-3 secondes = pattern de honeypot)
const originalSetTimeout = window.setTimeout;
window.setTimeout = function(callback, delay, ...args) {
if (delay >= 2000 && delay <= 3000) {
// Pattern suspect : timeout de 2-3 secondes pour détecter les extensions
const callbackString = callback.toString();
if (callbackString.includes('querySelector') || callbackString.includes('yggsearch')) {
console.warn('[HONEYPOT-DETECT] setTimeout suspect détecté (délai:', delay, 'ms)');
// Ne pas exécuter le callback
return -1;
}
}
return originalSetTimeout(callback, delay, ...args);
};
})();
2. Détecter les scripts obfusqués en base64
// detect-obfuscated-scripts.js
(function() {
'use strict';
// Surveiller l'exécution de scripts avec atob/base64
const originalAtob = window.atob;
window.atob = function(str) {
const decoded = originalAtob(str);
// Détecter les patterns suspects dans le décodage
const suspiciousPatterns = [
'yggsearch', 'api-btn', 'engine', 'gm', 'extension',
'bypass', 'limit', 'download'
];
if (suspiciousPatterns.some(p => decoded.includes(p))) {
console.warn('[OBFUSCATION-DETECT] Base64 décodant un pattern suspect:');
console.warn(' Decoded:', decoded);
console.trace();
}
return decoded;
};
// Surveiller les scripts inline avec atob
const scripts = document.querySelectorAll('script');
scripts.forEach(script => {
if (script.textContent.includes('atob(')) {
console.warn('[OBFUSCATION-DETECT] Script contenant atob() détecté');
console.warn(' Source:', script.src || 'inline');
}
});
})();
3. Protection contre la détection d'extension (côté extension)
// extension-protection.js — Ne pas injecter de classes identifiables
// ❌ MAUVAIS — Classe identifiable
const button = document.createElement('button');
button.className = 'yggsearch-api-btn'; // ❌ Détectable
// ✅ BON — Classe aléatoire, générée dynamiquement
const randomClass = 'btn-' + Math.random().toString(36).substring(2, 10);
const button = document.createElement('button');
button.className = randomClass;
// ✅ BON — Utiliser des attributs data-* générés dynamiquement
const dataAttr = 'data-' + Math.random().toString(36).substring(2, 6);
button.setAttribute(dataAttr, 'true');
// ✅ BON — Injection via Shadow DOM (isolation)
const shadowHost = document.createElement('div');
const shadow = shadowHost.attachShadow({ mode: 'closed' });
shadow.innerHTML = '<button>Download</button>';
document.body.appendChild(shadowHost);
4. Détection côté serveur (pour les développeurs)
// detect-honeypot-server.php — Détecter si le site est un honeypot
function detectHoneypotBehavior($html) {
$suspiciousPatterns = [
// Scripts avec setTimeout de 2-3 secondes
'setTimeout\s*\(\s*function\s*\(\s*\)\s*\{[^}]*querySelector',
// Scripts avec atob et des patterns suspects
'atob\s*\(\s*[\'"]',
// Formulaires cachés avec action /engine/
'<form[^>]*action=[\'"]/engine/[^>]*display:\s*none',
// Requêtes POST silencieuses vers /engine/
'fetch\s*\(\s*[\'"]/engine/',
];
$score = 0;
foreach ($suspiciousPatterns as $pattern) {
if (preg_match('/' . $pattern . '/i', $html)) {
$score += 25;
}
}
return $score >= 50; // Probable honeypot si score >= 50
}
5. Éthique — Ne PAS créer de honeypots malveillants
## Éthique des honeypots
Un honeypot doit :
- ✅ Être transparent sur sa présence (terms of service)
- ✅ Ne PAS collecter plus de données que nécessaire
- ✅ Ne PAS ban définitif sans avertissement
- ✅ Ne PAS usurper l'identité d'autres extensions
- ✅ Être utilisé pour la sécurité, pas la rétorsion
Un honeypot ne doit PAS :
- ❌ Bannir définitivement sans avertissement
- ❌ Collecter des données personnelles sans consentement
- ❌ Usurper des classes d'extensions légitimes
- ❌ Être dissimulé comme un script inoffensif (modal.min.js)
Checklist de validation
- Pas de ban définitif sans avertissement (honeypot = détection, pas rétorsion)
- Pas de collecte de données personnelles via honeypot
- Pas d'usurpation de classes d'extensions légitimes
- Scripts de détection transparents (pas renommés pour passer inaperçu)
- Détection des formulaires cachés POST vers des endpoints suspects
- Monitoring des setTimeout de 2-3 secondes avec querySelector
- Détection des scripts obfusqués en base64 avec atob()
- Utilisation de Shadow DOM pour isoler les extensions
- Classes générées dynamiquement (pas de patterns fixes)
- Éthique : honeypot pour la sécurité, pas la rétorsion
Références
- Archive Ygg :
modal.min.js,extension_users.txt(YGGLeak) - OWASP : Honeypot Ethics