DNS & WHOIS Reconnaissance
Analyse des enregistrements DNS, informations WHOIS et infrastructure réseau de la cible.
SORTIE TERMINAL
// En attente d'exécution...
', '">', "javascript:alert`1`", '', ]; payloads.forEach(p => { addLine(`${ts()} [TEST] ${escH(p)}`); }); addLine(`${ts()} [VULN] Paramètre qXSS REFLECTED CONFIRMÉ`); addLine(`${ts()} Payload: <img src=x onerror=alert(document.domain)>`); }}, { pct:72, label:'DOM-based…', ms:700, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [VULN] DOM-XSS via location.search → innerHTML`); addLine(` → Flux non sanitisé : source → sink sans encodage`); }}, { pct:88, label:'WAF detection…', ms:500, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [INFO] Aucun WAF détecté — payloads basiques suffisants`); }}, { pct:95, label:'Rapport…', ms:300, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [HIGH] 2 vulnérabilités XSS — CVSS v3: 7.2 (High)`); addLine(` → Encoder les sorties HTML (htmlspecialchars)`); addLine(` → Mettre en place une Content-Security-Policy stricte`); addLine(` → Utiliser textContent à la place de innerHTML`); }}, ]); } }, /* ────────────────── SSL ────────────────── */ ssl: { title: 'Audit SSL/TLS', desc: 'Vérification des certificats, suites de chiffrement, protocoles obsolètes et vulnérabilités connues.', buildInputs() { return `
HÔTE CIBLE
PORT
`; }, run() { const tgt = val('f-target') || 'exemple.com'; const port = val('f-port') || '443'; clearTerm(); addLine(`${ts()} $ ssl-audit --host ${tgt}:${port} --full --ciphers`); addLine(`─────────────────────────────────────────────`); steps([ { pct:20, label:'Connexion TLS…', ms:700, action() { addLine(`${ts()} [✓] Connexion établie via TLS 1.3`); addLine(`${ts()} [✓] Certificat : *.${tgt} (Let's Encrypt)`); addLine(`${ts()} [✓] Algorithme : RSA 2048 bits`); }}, { pct:40, label:'Vérif. certificat…', ms:700, action() { addLine(`${ts()} [✓] Validité : 2024-01-15 → 2025-04-15 (actif)`); addLine(`${ts()} [✓] Chaîne : complète et valide`); addLine(`${ts()} [✓] SAN/CN : cohérents, pas de wildcard abusif`); addLine(`${ts()} [✓] Révocation : OCSP Stapling actif`); }}, { pct:60, label:'Protocoles…', ms:900, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [✗] SSLv3 : ACTIVÉ — CVE-2014-3566 (POODLE)`); addLine(`${ts()} [✗] TLS 1.0 : ACTIVÉ — CVE-2011-3389 (BEAST)`); addLine(`${ts()} [!] TLS 1.1 : ACTIVÉ — déprécié RFC 8996`); addLine(`${ts()} [✓] TLS 1.2 : actif`); addLine(`${ts()} [✓] TLS 1.3 : actif`); }}, { pct:80, label:'Cipher suites…', ms:700, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [!] RC4 cipher détecté — chiffrement faible`); addLine(`${ts()} [!] 3DES (SWEET32) — longueur de bloc 64 bits`); addLine(`${ts()} [✓] ECDHE supporté — Perfect Forward Secrecy OK`); addLine(`${ts()} [✓] HEARTBLEED : non vulnérable`); addLine(`${ts()} [✓] ROBOT : non vulnérable`); }}, { pct:95, label:'Score…', ms:300, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} Score SSL Labs : C (61 / 100)`); addLine(` → Désactiver SSLv3, TLS 1.0 et TLS 1.1`); addLine(` → Supprimer les cipher suites RC4 et 3DES`); }}, ]); } }, /* ────────────────── AUTH ────────────────── */ auth: { title: "Test d'Authentification", desc: "Audit des mécanismes d'authentification, politiques de mots de passe et gestion de sessions.", buildInputs() { return `
URL DE CONNEXION
CHAMP USERNAME
CHAMP PASSWORD
Tests
⚠ Usage éthique uniquement. Obtenez toujours une autorisation écrite avant tout test.
`; }, run() { const tgt = val('f-target') || 'https://exemple.com/login'; clearTerm(); addLine(`${ts()} $ auth-audit --url ${tgt} --all`); addLine(`─────────────────────────────────────────────`); steps([ { pct:20, label:'Analyse formulaire…', ms:700, action() { addLine(`${ts()} [FORM] Champs : username, password, submit`); addLine(`${ts()} [FORM] Méthode : POST / Encodage : application/x-www-form-urlencoded`); addLine(`${ts()} [✗] Aucun token CSRF détecté dans le formulaire`); addLine(`${ts()} [!] Autocomplétion activée sur le champ password`); }}, { pct:40, label:'Test verrouillage…', ms:1000, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [TEST] 10 tentatives avec mauvais mot de passe...`); for (let i=1;i<=5;i++) { addLine(`${ts()} Tentative ${i*2} : HTTP 200 — "Identifiants incorrects"`); } addLine(`${ts()} [VULN] Pas de verrouillage après 10 tentatives — Bruteforce possible`); }}, { pct:62, label:'Cookies session…', ms:700, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [!] Cookie : HttpOnly absent — vol via XSS possible`); addLine(`${ts()} [✓] Cookie : flag Secure présent`); addLine(`${ts()} [!] Cookie : SameSite non défini (défaut Lax)`); addLine(`${ts()} [!] Session ID : entropie faible (64 bits)`); }}, { pct:80, label:'Énumération users…', ms:700, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [!] Messages d'erreur différentiels détectés:`); addLine(`${ts()} user inconnu : "Utilisateur inconnu" (200ms)`); addLine(`${ts()} user existant : "Mot de passe incorrect" (1200ms)`); addLine(`${ts()} [!] Énumération d'utilisateurs possible (timing + message)`); }}, { pct:95, label:'Résumé…', ms:300, action() { addLine(`─────────────────────────────────────────────`); addLine(`${ts()} [HIGH] 5 problèmes d'authentification identifiés`); addLine(` → Implémenter CSRF tokens, rate limiting, messages génériques`); addLine(` → Ajouter HttpOnly, SameSite=Strict sur les cookies de session`); }}, ]); } }, /* ────────────────── REPORT ────────────────── */ report: { title: 'Rapport de Sécurité', desc: 'Synthèse de tous les tests effectués avec classification des vulnérabilités et recommandations.', buildInputs() { return `
ORGANISATION
AUDITEUR
FORMAT D'EXPORT
Inclure dans le rapport
`; }, run() { const org = val('f-org') || 'Organisation cible'; const aud = val('f-auditor') || 'Auditeur'; clearTerm(); const term = document.getElementById('terminal'); const rep = document.getElementById('report-output'); term.style.display = 'none'; rep.classList.add('visible'); rep.innerHTML = buildReport(org, aud); } }, }; /* ══════════════════════════════════════════════════════ HELPERS ══════════════════════════════════════════════════════ */ function val(id) { const el = document.getElementById(id); return el ? el.value.trim() : ''; } function pad(s, n) { return String(s).padEnd(n); } function rnd(a, b) { return Math.floor(Math.random() * (b - a + 1)) + a; } function ts() { return `[${new Date().toLocaleTimeString('fr-FR')}]`; } function escH(s) { return s.replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } function clearTerm() { const term = document.getElementById('terminal'); const rep = document.getElementById('report-output'); term.style.display = 'block'; term.innerHTML = ''; rep.classList.remove('visible'); rep.innerHTML = ''; termHistory[activeTool] = []; } function addLine(html) { const term = document.getElementById('terminal'); if (!term) return; if (!termHistory[activeTool]) termHistory[activeTool] = []; const div = document.createElement('p'); div.className = 'tl'; div.innerHTML = html; termHistory[activeTool].push(html); term.appendChild(div); term.scrollTop = term.scrollHeight; } function steps(arr) { const progWrap = document.getElementById('prog-wrap'); const progFill = document.getElementById('prog-fill'); const progStat = document.getElementById('prog-stat'); const runBtn = document.getElementById('run-btn'); if (progWrap) progWrap.classList.add('visible'); if (runBtn) runBtn.disabled = true; let i = 0; function next() { if (i >= arr.length) { if (progFill) progFill.style.width = '100%'; if (progStat) progStat.textContent = 'Terminé'; if (runBtn) runBtn.disabled = false; setTimeout(() => { if (progWrap) progWrap.classList.remove('visible'); if (progFill) progFill.style.width = '0%'; }, 1200); return; } const step = arr[i++]; if (progFill) progFill.style.width = step.pct + '%'; if (progStat) progStat.textContent = step.label; if (step.action) step.action(); setTimeout(next, step.ms || 600); } next(); } /* ══════════════════════════════════════════════════════ RENDER TOOL ══════════════════════════════════════════════════════ */ function renderTool(id) { const t = TOOLS[id]; if (!t) return; document.getElementById('tool-title').innerHTML = t.title; document.getElementById('tool-desc').textContent = t.desc; // Input panel const ip = document.getElementById('input-panel'); ip.innerHTML = ` ${t.buildInputs()}
En cours…
`; document.getElementById('run-btn').addEventListener('click', () => t.run()); document.getElementById('clear-btn').addEventListener('click', () => { clearTerm(); document.getElementById('terminal').innerHTML = '// En attente d\'exécution...'; }); // Restore terminal const term = document.getElementById('terminal'); const rep = document.getElementById('report-output'); term.style.display = 'block'; rep.classList.remove('visible'); const hist = termHistory[id]; if (hist && hist.length) { term.innerHTML = hist.map(h => `

${h}

`).join(''); term.scrollTop = term.scrollHeight; } else { term.innerHTML = '// En attente d\'exécution...'; } } /* ══════════════════════════════════════════════════════ NAVIGATION ══════════════════════════════════════════════════════ */ document.querySelectorAll('.nav-item').forEach(item => { item.addEventListener('click', () => { document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active')); item.classList.add('active'); activeTool = item.dataset.tool; renderTool(activeTool); }); }); /* ══════════════════════════════════════════════════════ COPY / EXPORT ══════════════════════════════════════════════════════ */ document.getElementById('btn-copy').addEventListener('click', () => { const term = document.getElementById('terminal'); const rep = document.getElementById('report-output'); const src = rep.classList.contains('visible') ? rep : term; navigator.clipboard.writeText(src.innerText).catch(() => { const ta = document.createElement('textarea'); ta.value = src.innerText; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); }); }); document.getElementById('btn-export').addEventListener('click', () => { const term = document.getElementById('terminal'); const rep = document.getElementById('report-output'); const src = rep.classList.contains('visible') ? rep : term; const blob = new Blob([src.innerText], { type: 'text/plain' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = `pentestkit_${activeTool}_${Date.now()}.txt`; a.click(); URL.revokeObjectURL(a.href); }); /* ══════════════════════════════════════════════════════ REPORT BUILDER ══════════════════════════════════════════════════════ */ function buildReport(org, aud) { const date = new Date().toLocaleDateString('fr-FR', { year:'numeric', month:'long', day:'numeric' }); const vulns = [ { sev:'CRITIQUE', cls:'badge-crit', name:'SQL Injection (Error-based & Boolean)', cvss:'9.8', detail:'Paramètre "id" injectable sur /page — exécution de requêtes SQL arbitraires possible.', reco:'Utiliser des PreparedStatements, valider les entrées, principe du moindre privilège.' }, { sev:'CRITIQUE', cls:'badge-crit', name:'MySQL exposé publiquement (port 3306)', cvss:'9.1', detail:'Port MySQL accessible depuis internet sans restriction de pare-feu.', reco:'Restreindre l\'accès MySQL à localhost uniquement via règles iptables/firewall.' }, { sev:'HIGH', cls:'badge-high', name:'XSS Reflected + DOM-based', cvss:'7.2', detail:'Paramètre "q" non sanitisé reflété dans le DOM via innerHTML.', reco:'Encoder les sorties HTML, implémenter une CSP stricte, utiliser textContent.' }, { sev:'HIGH', cls:'badge-high', name:'FTP non chiffré (port 21)', cvss:'7.5', detail:'Service FTP actif sans chiffrement — credentials transmis en clair.', reco:'Désactiver FTP, migrer vers SFTP (SSH) ou FTPS.' }, { sev:'HIGH', cls:'badge-high', name:'Absence de verrouillage de compte', cvss:'7.3', detail:'Aucune protection contre les attaques par force brute sur le formulaire de connexion.', reco:'Implémenter un rate limiting et un lockout après N tentatives échouées.' }, { sev:'MEDIUM', cls:'badge-med', name:'Protocoles SSL/TLS obsolètes', cvss:'5.9', detail:'SSLv3 (POODLE), TLS 1.0 (BEAST) et TLS 1.1 (déprécié) activés.', reco:'Désactiver SSLv3, TLS 1.0 et TLS 1.1. N\'autoriser que TLS 1.2 et TLS 1.3.' }, { sev:'MEDIUM', cls:'badge-med', name:'Absence de token CSRF', cvss:'5.4', detail:'Formulaire de connexion sans protection CSRF — attaques cross-site possibles.', reco:'Générer un token CSRF synchronisé par formulaire et session.' }, { sev:'MEDIUM', cls:'badge-med', name:'Headers de sécurité manquants', cvss:'4.3', detail:'CSP, X-Content-Type-Options et Permissions-Policy absents.', reco:'Configurer tous les headers de sécurité recommandés par OWASP.' }, { sev:'MEDIUM', cls:'badge-med', name:'Cookie de session sans HttpOnly', cvss:'4.8', detail:'Le cookie de session peut être accédé via JavaScript (exploitation XSS facilitée).', reco:'Ajouter les flags HttpOnly et SameSite=Strict aux cookies de session.' }, { sev:'LOW', cls:'badge-low', name:'Version serveur exposée', cvss:'2.6', detail:'Headers Server et X-Powered-By révèlent Apache 2.4.41 et PHP 7.4.3.', reco:'Masquer les headers de version (ServerTokens Prod, expose_php = Off).' }, { sev:'LOW', cls:'badge-low', name:'Sous-domaines sensibles exposés', cvss:'3.1', detail:'admin.*, dev.* et staging.* accessibles publiquement.', reco:'Restreindre l\'accès via authentification IP, VPN ou HTTP Basic.' }, { sev:'LOW', cls:'badge-low', name:'CORS trop permissif', cvss:'3.7', detail:'Access-Control-Allow-Origin: * autorise toute origine.', reco:'Restreindre CORS aux origines de confiance uniquement.' }, ]; const counts = { CRITIQUE:0, HIGH:0, MEDIUM:0, LOW:0 }; vulns.forEach(v => counts[v.sev]++); const vulnHtml = vulns.map(v => `
${v.name}
${v.sev} CVSS ${v.cvss}
${v.detail}
→ ${v.reco}
`).join(''); return `
Rapport de Pentest — ${org}
Auditeur : ${aud}
Date : ${date}
Durée : ~52 minutes
Score risque global : CRITIQUE (8.4 / 10)
${counts.CRITIQUE}
CRITIQUE
${counts.HIGH}
HIGH
${counts.MEDIUM}
MEDIUM
${counts.LOW}
LOW
Vulnérabilités identifiées (${vulns.length})
${vulnHtml}
Priorités de remédiation
Immédiat : Fermer le port MySQL 3306, corriger l'injection SQL et désactiver FTP.
Sous 7 jours : Corriger les XSS, mettre en place le rate limiting et les tokens CSRF.
Sous 30 jours : Désactiver SSLv3/TLS1.0, ajouter les headers de sécurité, sécuriser les cookies.
Sous 90 jours : Masquer les versions, restreindre les sous-domaines, affiner la politique CORS.
`; } /* ══════════════════════════════════════════════════════ GLOBAL HELPERS FOR INLINE HANDLERS ══════════════════════════════════════════════════════ */ window.toggleCustomPorts = function(val) { const f = document.getElementById('custom-ports-field'); if (f) f.style.display = val === 'custom' ? 'flex' : 'none'; }; /* ── Init ── */ renderTool('recon');