gitex2026/AttackSurface/dist/static/simulation.html
2026-04-24 19:18:37 +00:00

283 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>AASD — Security Simulation</title>
<script src="https://cdn.tailwindcss.com/"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
aasd: { dark: '#0f172a', card: '#1e293b', border: '#334155', blue: '#3b82f6', purple: '#8b5cf6', text: '#f1f5f9', muted: '#94a3b8', dim: '#64748b' }
}
}
}
}
</script>
<style>
* { -webkit-tap-highlight-color: transparent; }
body { overscroll-behavior: none; }
.step-indicator { transition: all 0.5s ease; }
@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
.pulsing::after { content: ''; display: inline-block; width: 8px; height: 8px; background: #3b82f6; border-radius: 50%; margin-left: 8px; animation: pulse-dot 1.5s infinite; }
</style>
</head>
<body class="bg-slate-900 text-slate-100 min-h-screen">
<div class="container mx-auto px-4 py-6 max-w-lg">
<!-- Header -->
<div class="text-center mb-6">
<h1 class="text-2xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">AASD</h1>
<p class="text-sm text-slate-400">API Attack Surface Discovery</p>
<div class="mt-3 inline-block bg-slate-800 border-2 border-slate-600 rounded-full px-4 py-1.5 text-sm text-blue-400 font-mono" id="domainBadge">domain.com</div>
</div>
<!-- Progress Bar -->
<div class="w-full h-2 bg-slate-800 rounded-full mb-6 overflow-hidden">
<div class="h-full bg-gradient-to-r from-blue-500 to-purple-500 rounded-full transition-all duration-700 ease-out" id="progressFill" style="width: 0%"></div>
</div>
<!-- Step Sequencer (5 steps for new workflow) -->
<div class="bg-slate-800 rounded-2xl p-5 border border-slate-700 mb-4">
<h2 class="text-sm font-semibold text-slate-400 uppercase tracking-wider mb-4">Discovery Pipeline</h2>
<div class="space-y-3">
<!-- Step 1: Email Validation -->
<div class="step-indicator flex items-center gap-3 p-3 rounded-xl bg-slate-900 border border-slate-700" id="step1">
<div class="w-8 h-8 rounded-full bg-slate-700 text-slate-400 text-sm font-bold flex items-center justify-center shrink-0" id="icon1">1</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-semibold text-slate-200" id="title1">Email Validation</div>
<div class="text-xs text-slate-500" id="desc1">Verifying email and extracting domain</div>
</div>
<div class="text-xs text-slate-600 shrink-0" id="time1">0-2s</div>
</div>
<!-- Step 2: Domain Discovery -->
<div class="step-indicator flex items-center gap-3 p-3 rounded-xl bg-slate-900 border border-slate-700" id="step2">
<div class="w-8 h-8 rounded-full bg-slate-700 text-slate-400 text-sm font-bold flex items-center justify-center shrink-0" id="icon2">2</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-semibold text-slate-200" id="title2">Domain Discovery</div>
<div class="text-xs text-slate-500" id="desc2">Scanning subdomains with passive enumeration</div>
</div>
<div class="text-xs text-slate-600 shrink-0" id="time2">2-10s</div>
</div>
<!-- Step 3: Filter & Target Selection -->
<div class="step-indicator flex items-center gap-3 p-3 rounded-xl bg-slate-900 border border-slate-700" id="step3">
<div class="w-8 h-8 rounded-full bg-slate-700 text-slate-400 text-sm font-bold flex items-center justify-center shrink-0" id="icon3">3</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-semibold text-slate-200" id="title3">Target Selection</div>
<div class="text-xs text-slate-500" id="desc3">Identifying the most critical endpoint</div>
</div>
<div class="text-xs text-slate-600 shrink-0" id="time3">2-5s</div>
</div>
<!-- Step 4: GoTestWAF Scan -->
<div class="step-indicator flex items-center gap-3 p-3 rounded-xl bg-slate-900 border border-slate-700" id="step4">
<div class="w-8 h-8 rounded-full bg-slate-700 text-slate-400 text-sm font-bold flex items-center justify-center shrink-0" id="icon4">4</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-semibold text-slate-200" id="title4">WAF Penetration Test</div>
<div class="text-xs text-slate-500" id="desc4">GoTestWAF scanning against Wallarm endpoint</div>
</div>
<div class="text-xs text-slate-600 shrink-0" id="time4">10-120s</div>
</div>
<!-- Step 5: AI Report Generation -->
<div class="step-indicator flex items-center gap-3 p-3 rounded-xl bg-slate-900 border border-slate-700" id="step5">
<div class="w-8 h-8 rounded-full bg-slate-700 text-slate-400 text-sm font-bold flex items-center justify-center shrink-0" id="icon5">5</div>
<div class="flex-1 min-w-0">
<div class="text-sm font-semibold text-slate-200" id="title5">AI Resilience Narrative</div>
<div class="text-xs text-slate-500" id="desc5">DeepSeek AI generating your report</div>
</div>
<div class="text-xs text-slate-600 shrink-0" id="time5">5-15s</div>
</div>
</div>
</div>
<!-- Status -->
<div class="bg-slate-800 rounded-2xl p-5 border border-slate-700 text-center mb-4">
<div class="text-sm text-slate-400 mb-1">Status</div>
<div class="text-lg font-bold text-slate-200" id="statusDisplay">
<span class="inline-flex items-center gap-2">
<span class="w-2.5 h-2.5 rounded-full bg-slate-500" id="statusDot"></span>
<span id="statusText">Pending</span>
</span>
</div>
</div>
<!-- Result Panel (shown on completion) -->
<div id="resultPanel" class="hidden bg-slate-800 rounded-2xl p-5 border border-slate-700 text-center mb-4">
<h2 class="text-lg font-bold text-slate-100 mb-3">Discovery Complete</h2>
<div class="grid grid-cols-2 gap-3 mb-4">
<div class="bg-slate-900 rounded-xl p-3">
<div class="text-2xl font-bold text-blue-400" id="subdomainCount">0</div>
<div class="text-xs text-slate-400">Subdomains Found</div>
</div>
<div class="bg-slate-900 rounded-xl p-3">
<div class="text-2xl font-bold text-green-400" id="wafStatus">Ready</div>
<div class="text-xs text-slate-400">WAF Tested</div>
</div>
</div>
<a id="reportLink" href="#"
class="btn-primary block w-full text-white font-bold py-4 px-6 rounded-xl text-lg shadow-lg hover:shadow-blue-500/25 active:scale-[0.97] transition-all"
style="background: linear-gradient(90deg, #3b82f6, #8b5cf6);">
View Your Resilience Report
</a>
<p class="text-xs text-slate-500 mt-3">Show this code to <strong class="text-blue-400">Sechpoint Aftica Team</strong></p>
</div>
<!-- Footer -->
<div class="text-center text-xs text-slate-600 mt-6">
GITEX 2026 — sechpoint.app | <a href="/admin-dashboard" class="text-blue-500 hover:underline">Consultant Dashboard</a>
</div>
</div>
<script>
// Get token from URL
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');
const domainParam = urlParams.get('domain');
// Determine what identifier to use for polling
const pollId = token || domainParam || 'unknown';
// Show domain if available, or mask for token
if (domainParam) {
document.getElementById('domainBadge').textContent = domainParam;
} else if (token) {
document.getElementById('domainBadge').textContent = 'Scan: ' + token.substring(0, 8) + '...';
}
const steps = ['step1', 'step2', 'step3', 'step4', 'step5'];
let currentStep = -1;
const statusText = document.getElementById('statusText');
const statusDot = document.getElementById('statusDot');
const progressFill = document.getElementById('progressFill');
const resultPanel = document.getElementById('resultPanel');
const statusDisplay = document.getElementById('statusDisplay');
// Map API statuses to step indices
const statusStepMap = {
'pending': -1,
'discovering': 0, // step 1-2
'scanning': 2, // step 3-4
'generating': 4, // step 5
'completed': 5,
'failed': -2
};
function setActive(stepIndex) {
// Reset all steps
steps.forEach((id, idx) => {
const el = document.getElementById(id);
const icon = document.getElementById('icon' + (idx + 1));
el.classList.remove('border-blue-500', 'bg-blue-500/10', 'border-green-500', 'bg-green-500/10');
el.classList.add('border-slate-700');
el.classList.remove('pulsing');
if (idx < stepIndex) {
// Completed
el.classList.add('border-green-500', 'bg-green-500/10');
icon.textContent = '✓';
icon.className = 'w-8 h-8 rounded-full bg-green-600 text-white text-sm font-bold flex items-center justify-center shrink-0';
} else if (idx === stepIndex) {
// Active
el.classList.add('border-blue-500', 'bg-blue-500/10');
icon.textContent = idx + 1;
icon.className = 'w-8 h-8 rounded-full bg-blue-600 text-white text-sm font-bold flex items-center justify-center shrink-0';
} else {
// Pending
icon.textContent = idx + 1;
icon.className = 'w-8 h-8 rounded-full bg-slate-700 text-slate-400 text-sm font-bold flex items-center justify-center shrink-0';
}
});
if (stepIndex >= 0 && stepIndex < steps.length) {
const maxSteps = steps.length;
const pct = Math.min(100, Math.round(((stepIndex + 1) / maxSteps) * 100));
progressFill.style.width = pct + '%';
}
}
function setStatus(label, color) {
statusText.textContent = label;
statusDot.className = 'w-2.5 h-2.5 rounded-full ' + color;
}
function showResults(data) {
resultPanel.classList.remove('hidden');
document.getElementById('subdomainCount').textContent = data.subdomains_discovered || 'N/A';
document.getElementById('wafStatus').textContent = data.status === 'completed' ? 'Passed' : 'N/A';
document.getElementById('reportLink').href = data.report || ('/reports/' + token + '.html');
// Mark step 5 complete
setActive(5);
progressFill.style.width = '100%';
setStatus('Completed', 'bg-green-500');
statusDisplay.className = 'bg-slate-800 rounded-2xl p-5 border border-green-500/50 text-center mb-4';
}
function showFailed() {
setStatus('Failed', 'bg-red-500');
statusDisplay.className = 'bg-slate-800 rounded-2xl p-5 border border-red-500/50 text-center mb-4';
}
// Poll scan status
async function pollStatus() {
try {
const resp = await fetch('/scan-status/' + encodeURIComponent(pollId));
if (!resp.ok) return;
const data = await resp.json();
const apiStatus = data.status || '';
// Map status to step
if (apiStatus === 'completed') {
showResults(data);
return;
}
if (apiStatus === 'failed') {
showFailed();
return;
}
const stepIndex = statusStepMap[apiStatus] !== undefined ? statusStepMap[apiStatus] : -1;
if (stepIndex === -2) {
showFailed();
return;
}
if (stepIndex >= 0) {
setActive(stepIndex);
}
// Update status display
switch (apiStatus) {
case 'pending':
setStatus('Pending', 'bg-slate-500');
break;
case 'discovering':
setStatus('Discovering Subdomains', 'bg-blue-500');
break;
case 'scanning':
setStatus('Scanning WAF Endpoint', 'bg-purple-500');
break;
case 'generating':
setStatus('Generating AI Report', 'bg-yellow-500');
break;
default:
setStatus(apiStatus, 'bg-slate-500');
}
} catch (err) {
console.error('Poll error:', err);
}
}
// Start polling
pollStatus();
setInterval(pollStatus, 3000);
// Activate first step initially
setActive(0);
setStatus('Starting Pipeline', 'bg-blue-500');
</script>
</body>
</html>