Periksa masa berlaku JWT
- Issued token [REDACTED-LAB-TOKEN]
- Decoded payload { "user_id": 2, "username": "pentest_attacker", "is_admin": false, "iat": 1790737980 }
- Claims present iat, is_admin, user_id, username
- Expiry claim (exp) absent
LAB FAIL
Insufficient Session Expiration — Authentication — JWT Lifetime
CWE-613: Insufficient Session Expiration · OWASP A07:2021 - Identification and Authentication Failures
[FAIL] Insufficient Session Expiration - Authentication - JWT Lifetime
Token JWT yang diterbitkan tidak memuat klaim exp sehingga tidak pernah kedaluwarsa, dan tidak tersedia mekanisme pencabutan token. Selain itu token diterima dari beberapa lokasi sekaligus, termasuk parameter query URL, dan pada antarmuka web disimpan di localStorage sehingga terbaca oleh JavaScript.
Medium: token yang pernah bocor berlaku selamanya. Tidak ada rotasi maupun pencabutan, sehingga satu kali kebocoran memberi akses permanen ke akun korban. Penerimaan token melalui parameter query memperbesar peluang kebocoran karena URL tercatat di riwayat peramban, log server, dan header Referer. Penyimpanan di localStorage membuat token dapat dicuri oleh XSS, dan hal ini telah dibuktikan pada temuan Stored Cross-Site Scripting di mana JWT administrator berhasil diambil.
CWE-613: Insufficient Session Expiration
A07:2021 - Identification and Authentication Failures
Analisis token: token yang diterbitkan didekode dan hanya memuat klaim user_id, username, is_admin, dan iat; klaim exp tidak ada sama sekali. Verifikasi: token yang sama tetap diterima pada endpoint terproteksi. Pendukung: token juga diterima ketika dikirim sebagai parameter query pada URL, bukan hanya pada header Authorization.
POST http://127.0.0.1:5001/login (penerbitan token) GET http://127.0.0.1:5001/dashboard (penerimaan token)
Manajemen sesi berbasis JWT
- Tambahkan klaim exp dengan masa berlaku singkat dan terapkan refresh token yang dapat dicabut. - Simpan daftar pencabutan (denylist) atau gunakan token identifier agar sesi dapat dimatikan saat terjadi insiden. - Terima token hanya dari header Authorization; hentikan pembacaan dari parameter query dan form. - Pindahkan token sesi ke cookie HttpOnly, Secure, dan SameSite agar tidak terjangkau JavaScript.
LAB Semua target adalah sistem lab. Tidak ada satu pun yang merupakan pekerjaan klien. Bukti ditampilkan apa adanya; secret dihitamkan.
GET /dashboard HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 27266
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:01 GMT
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dashboard - VulnBank</title>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="icon" type="image/svg+xml" href="/static/favicon-16.svg" sizes="16x16">
<link rel="stylesheet" href="/static/style.css">
<link rel="stylesheet" href="/static/dashboard.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>document.documentElement.setAttribute("data-theme", localStorage.getItem("vb-theme") || "light");</script>
<script src="/static/vuln-disclaimer.js" defer></script>
</head>
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>
<!-- Mobile menu toggle -->
<button class="menu-toggle" onclick="toggleSidePanel()" aria-label="Toggle navigation menu">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
</button>
<div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleSidePanel()"></div>
<!-- Sidebar -->
<aside class="sidebar" id="sidebar" role="navigation" aria-label="Main navigation">
<div class="sidebar-logo">
<div class="sidebar-logo-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="1" x2="12" y2="23"></line><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path></svg>
</div>
<span class="sidebar-logo-text">VulnBank</span>
</div>
<nav class="sidebar-nav">
<div class="nav-section-label">Main</div>
<a href="#profile" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
Profile
</a>
<a href="#transfers" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
Money Transfer
</a>
<a href="#loans" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>
Loans
</a>
<div class="nav-section-label">Activity</div>
<a href="#transactions" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>
Transactions
</a>
<a href="#virtual-cards" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect><line x1="1" y1="10" x2="23" y2="10"></line></svg>
Virtual Cards
</a>
<a href="#bill-payments" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line></svg>
Bill Payments
</a>
</nav>
<div class="sidebar-footer">
<img id="sidebar-avatar" class="sidebar-avatar" src="/static/uploads/966073_payload.html" alt="">
<div class="sidebar-user-info">
<div class="sidebar-user-name">pentest_attacker</div>
<div class="sidebar-user-role">Personal Account</div>
</div>
<button class="sidebar-logout" onclick="logout()" aria-label="Sign out">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
</button>
</div>
</aside>
<!-- Topbar -->
<header class="topbar">
<div class="topbar-left">
<span class="topbar-greeting">Welcome back, pentest_attacker</span>
<span class="topbar-date" id="current-date"></span>
</div>
<div class="topbar-right">
<button class="theme-toggle" onclick="toggleTheme()" aria-label="Toggle dark mode">
<span class="toggle-icon toggle-icon-sun">☀️</span>
<span class="toggle-slider"></span>
<span class="toggle-icon toggle-icon-moon">🌙</span>
</button>
<button class="topbar-icon-btn" aria-label="Notifications">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3
[... 21259 more bytes not shown ...]
GET /dashboard?token=[REDACTED-LAB-TOKEN] HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 27266
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:03 GMT
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dashboard - VulnBank</title>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="icon" type="image/svg+xml" href="/static/favicon-16.svg" sizes="16x16">
<link rel="stylesheet" href="/static/style.css">
<link rel="stylesheet" href="/static/dashboard.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>document.documentElement.setAttribute("data-theme", localStorage.getItem("vb-theme") || "light");</script>
<script src="/static/vuln-disclaimer.js" defer></script>
</head>
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>
<!-- Mobile menu toggle -->
<button class="menu-toggle" onclick="toggleSidePanel()" aria-label="Toggle navigation menu">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
</button>
<div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleSidePanel()"></div>
<!-- Sidebar -->
<aside class="sidebar" id="sidebar" role="navigation" aria-label="Main navigation">
<div class="sidebar-logo">
<div class="sidebar-logo-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="1" x2="12" y2="23"></line><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path></svg>
</div>
<span class="sidebar-logo-text">VulnBank</span>
</div>
<nav class="sidebar-nav">
<div class="nav-section-label">Main</div>
<a href="#profile" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
Profile
</a>
<a href="#transfers" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
Money Transfer
</a>
<a href="#loans" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>
Loans
</a>
<div class="nav-section-label">Activity</div>
<a href="#transactions" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>
Transactions
</a>
<a href="#virtual-cards" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect><line x1="1" y1="10" x2="23" y2="10"></line></svg>
Virtual Cards
</a>
<a href="#bill-payments" class="nav-link" onclick="setActiveLink(this)">
<svg class="nav-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line></svg>
Bill Payments
</a>
</nav>
<div class="sidebar-footer">
<img id="sidebar-avatar" class="sidebar-avatar" src="/static/uploads/966073_payload.html" alt="">
<div class="sidebar-user-info">
<div class="sidebar-user-name">pentest_attacker</div>
<div class="sidebar-user-role">Personal Account</div>
</div>
<button class="sidebar-logout" onclick="logout()" aria-label="Sign out">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
</button>
</div>
</aside>
<!-- Topbar -->
<header class="topbar">
<div class="topbar-left">
<span class="topbar-greeting">Welcome back, pentest_attacker</span>
<span class="topbar-date" id="current-date"></span>
</div>
<div class="topbar-right">
<button class="theme-toggle" onclick="toggleTheme()" aria-label="Toggle dark mode">
<span class="toggle-icon toggle-icon-sun">☀️</span>
<span class="toggle-slider"></span>
<span class="toggle-icon toggle-icon-moon">🌙</span>
</button>
<button class="topbar-icon-btn" aria-label="Notifications">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3
[... 21259 more bytes not shown ...]
← Kasus sebelumnya: Excessive Data Exposure - GraphQL - Schema Introspection Kasus berikutnya: JWT Algorithm Confusion - Authentication - alg none →