What's the vulnerability?

Sliver has DNS C2 OTP Bypass that Allows Unauthenticated Session Flooding and Denial of Service

Root Cause Analysis

## Summary
The Sliver DNS C2 listener in the 1d50db698 (2023) code path accepts unauthenticated DNSMessageType_TOTP bootstrap requests and allocates a new DNSSession for each request even when EnforceOTP is enabled. The TOTP message is treated as a “hello” packet that bypasses any OTP validation, so an unauthenticated remote actor can repeatedly send a tiny protobuf payload and force session allocations without cleanup.

## Impact
- Package/component affected: Sliver server DNS C2 listener (server/c2/dns.go).
- Affected versions: At least commit 1d50db6982880a1e538afac2ad8c5f268e62c51a (June 2023), prior to removal of TOTP bootstrap in Feb 2026.
- Risk level and consequences: High availability risk. A remote unauthenticated actor can flood the DNS listener with minimal TOTP bootstrap messages to create unbounded sessions and memory growth, leading to denial of service.

## Root Cause
The DNS handler routes all DNSMessageType_TOTP messages directly to handleHello without checking the EnforceOTP flag or validating the OTP value. In handleHello, the server allocates a DNSSession and stores it in sessions with a newly generated DNS session ID, and there is no cleanup for this bootstrap path. The bug is visible in server/c2/dns.go: handleC2 checks for TOTP and calls handleHello, while handleHello simply stores a new session. A later fix removes TOTP from DNS C2 and adds pending message GC (commit 9b001ab88ea17b7247f2622c13003c4dcabe5bf3).

## Reproduction Steps
1. Run `repro/reproduction_steps.sh`.
2. The script clones Sliver, checks out commit 1d50db698, adds placeholder assets required for build tags, and runs a minimal DNS listener using StartDNSListener with EnforceOTP=true. It then sends a single base32-encoded DNSMessageType_TOTP query to the listener.
3. Expected evidence: the DNS response contains a non-zero session ID and the script prints “received session id …” followed by “Vulnerability reproduced…”.

## Evidence
- Log file: `logs/dns_totp_poc.log`
- Key excerpt (example): `received session id 196.251.221.137`
- Environment details: Go toolchain go1.20.14 (via GOTOOLCHAIN) with build tags `server go_sqlite` on linux/arm64.

## Recommendations / Next Steps
- Suggested fix: enforce OTP validation in the TOTP bootstrap handler (reject invalid OTPs when EnforceOTP is enabled) and add lifecycle cleanup for sessions created during bootstrap. Preferably remove unauthenticated TOTP bootstrap entirely, as in the Feb 2026 change.
- Upgrade guidance: move to a version that removes TOTP bootstrap and includes session/pending message GC.
- Testing recommendations: add unit/integration tests that send TOTP bootstrap messages with EnforceOTP enabled and assert the server rejects them without creating sessions; add load tests ensuring session tables remain bounded.

## Additional Notes
- Idempotency: `repro/reproduction_steps.sh` was run twice consecutively and succeeded both times.
- Limitations: the script demonstrates session allocation for a single request; sustained flooding would exacerbate memory use but is not required to confirm the bug.
One Command

Verify with pruva-verify

Run the Pruva CLI to automatically fetch and execute the reproduction script.

pruva-verify REPRO-2026-00088
or pruva-verify GHSA-WXRW-GVG8-FQJP
Install: curl -fsSL https://pruva.dev/install.sh | sh

Or Run Manually

1

Download the script

curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00088/artifacts/reproduction_steps.sh
2

Make executable

chmod +x reproduction_steps.sh
3

Run the script

./reproduction_steps.sh
Run in a VM, container, or disposable environment. This exploits a real vulnerability.

How Pruva Reproduced This

Watch the AI agent's step-by-step process.

Loading session...

Artifacts

No artifacts available