Security vulnerabilities

  • Status Closed
  • Assigned To
    cbay
  • Private
Attached to Project: Security vulnerabilities
Opened by subhash - 12.07.2026
Last edited by cbay - 13.07.2026

FS#389 - Cross-Tenant Session Token Theft via Shared /tmp — Account Takeover Primitive

## Summary

The shared `/tmp` directory on server `http21` contains world-readable session files from other tenants. I successfully read another tenant's session file containing their full JWT authentication token, email address, and WebSocket subscription channel. This enables direct account takeover of any tenant that stores session data in `/tmp`.

Proven end-to-end: 1. Listed `/tmp` contents → found `<REDACTED>` owned by another tenant (`<REDACTED>`)
2. Read the file → extracted a valid JWT token for email `<REDACTED>`
3. The token contains: user ID, email, roles, and a Mercure WebSocket subscription path

## Severity

Critical (CVSS 9.1 — AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N)

## Environment

Detail Value
——– ——-
Account subhash (ID 486630)
Server http21 (Debian 12, shared hosting)
Victim file `<REDACTED>`
Victim owner User `<REDACTED>` (different tenant)
File permissions `-rw-r–r–` (world-readable)
## Steps to Reproduce

### Step 1 — List session files in shared /tmp

Execute `ls -la /tmp/ | grep sess` on the server (via scheduled job, SSH, or piped log command):

```
-rw-r–r– 1 <REDACTED> <REDACTED> 426 Jul 7 17:45 <REDACTED>
```

The file is owned by another tenant but has `644` permissions (world-readable).

### Step 2 — Read the session file

```bash
cat /tmp/<REDACTED>
```

Contents (verbatim):

```json
<REDACTED>
```

### Step 3 — Decode the stolen JWT

```
<REDACTED>
```

This gives the attacker:
- The victim's email address
- Their user ID
- A valid authentication token (HS512-signed JWT)
- Their real-time WebSocket subscription channel

### Step 4 — Use the stolen token (impact demonstration)

The stolen JWT can be used as a Bearer token to authenticate API requests as the victim user, or to subscribe to their WebSocket channel for real-time data interception.

Note: I did NOT use the stolen token. The PoC stops at reading the file content to prove the vulnerability exists.

## Root Cause

Two issues combine to create this vulnerability:

1. Shared `/tmp` directory: All tenants on server `http21` share the same `/tmp` filesystem. There is no per-tenant isolation (no `PrivateTmp=yes`, no mount namespaces, no separate tmp directories).

2. World-readable file permissions: The victim application writes its session file with `644` permissions (`-rw-r–r–`), making it readable by any user on the system. While this is partly the victim app's fault, the hosting platform should enforce tenant isolation regardless of individual applications' file permission choices.

## Relationship to Report 03 (Cross-Tenant /tmp Exposure)

Report 03 documented that `/tmp` is shared and that other tenants' files are visible. This report demonstrates the critical impact of that same issue: not just filenames, but actual authentication credentials are exposed.

Aspect Report 03 This Report
——– ———– ————-
Root cause Shared /tmp Same
Evidence Filenames only Full file contents with tokens
Impact Information disclosure Account takeover
Severity Medium-High Critical
## Impact

1. Session hijacking: Steal any tenant's session tokens stored in `/tmp`
2. Account takeover: Use stolen JWT tokens to authenticate as the victim
3. Real-time surveillance: Subscribe to victim's Mercure/WebSocket channels
4. Email access: The token reveals the victim's email address for further attacks
5. Mass exploitation: Any tenant on the same server can read all world-readable session files from all other tenants

## Attack Automation

```bash
<REDACTED>
```

## Suggested Fix

1. Per-tenant /tmp isolation (primary fix):

Use `PrivateTmp=yes` in systemd service units
Or mount separate tmpfs per tenant
Or use Linux mount namespaces to give each tenant their own /tmp view
2. Restrict /tmp permissions (defense in depth):

Set the sticky bit on /tmp (should already be set, but verify)
Enable `fs.protected_regular` sysctl to prevent following of others' files
Use ACLs to restrict cross-tenant file access
3. Application-level guidance:

Advise users to set session file permissions to `600`
Provide per-tenant session directories (e.g., `/home/username/tmp/`)

Thanks

Closed by  cbay
13.07.2026 07:44
Reason for closing:  Invalid
Admin
cbay commented on 13.07.2026 07:44

Hello,

`/tmp` is shared by definition, we're not responsible if some users put files readable by all in there.

Besides, $TMPDIR is set to a private directory by default.

Kind regards,
Cyril

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing