Kembali ke indeks

LAB FAIL

Insufficient Session Expiration - Authentication - JWT Lifetime

Insufficient Session Expiration — Authentication — JWT Lifetime

CWE-613: Insufficient Session Expiration · OWASP A07:2021 - Identification and Authentication Failures

Kerentanan

[FAIL] Insufficient Session Expiration - Authentication - JWT Lifetime

Deskripsi

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.

Dampak

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

CWE-613: Insufficient Session Expiration

OWASP

A07:2021 - Identification and Authentication Failures

Skenario

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.

Endpoint

POST http://127.0.0.1:5001/login (penerbitan token) GET http://127.0.0.1:5001/dashboard (penerimaan token)

Fitur terdampak

Manajemen sesi berbasis JWT

Rekomendasi perbaikan

- 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.

Bukti konsep

  1. (Screenshot 1) ANALISIS: token hasil login didekode -> hanya memuat user_id, username, is_admin, dan iat; klaim exp tidak ada.
  2. (Screenshot 2) VERIFIKASI: token yang sama diterima pada endpoint terproteksi -> HTTP 200.
  3. (Screenshot 3) DAMPAK: token yang sama juga diterima ketika dikirim sebagai parameter query pada URL -> HTTP 200, memperbesar peluang kebocoran melalui log dan Referer.

Rekaman lengkap

LAB Semua target adalah sistem lab. Tidak ada satu pun yang merupakan pekerjaan klien. Bukti ditampilkan apa adanya; secret dihitamkan.

Periksa masa berlaku JWT

  1. Issued token [REDACTED-LAB-TOKEN]
  2. Decoded payload { "user_id": 2, "username": "pentest_attacker", "is_admin": false, "iat": 1790737980 }
  3. Claims present iat, is_admin, user_id, username
  4. Expiry claim (exp) absent
Tangkapan layar
HTTP request
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 response
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 ...]
Tangkapan layar
HTTP request
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 response
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 ...]
Tangkapan layar

← Kasus sebelumnya: Excessive Data Exposure - GraphQL - Schema Introspection Kasus berikutnya: JWT Algorithm Confusion - Authentication - alg none →