GitHub Security Advisory: GHSA-97vp-pwqj-46qc
Package: github.com/bishopfox/sliver (GO)
Severity: MODERATE (CVSS 0.0)
CWE: CWE-770: Allocation of Resources Without Limits or Throttling, CWE-789: Memory Allocation with Excessive Size Value
Vulnerable versions: <= 1.7.3
Patched in: unpatched

Summary: Sliver Vulnerable to Authenticated OOM via Memory Exhaustion in mTLS/WireGuard Transports

Details:
# Summary
A Remote OOM (Out-of-Memory) vulnerability exists in the Sliver C2 server's mTLS and WireGuard C2 transport layer. The `socketReadEnvelope` and `socketWGReadEnvelope` functions trust an attacker-controlled 4-byte length prefix to allocate memory, with `ServerMaxMessageSize` allowing single allocations of up to **~2 GiB**. A compromised implant or an attacker with valid credentials can exploit this by sending fabricated length prefixes over concurrent yamux streams (up to 128 per connection), forcing the server to attempt allocating **~256 GiB** of memory and triggering an OS OOM kill. This crashes the Sliver server, disrupts all active implant sessions, and may degrade or kill other processes sharing the same host. The same pattern also affects all implant-side readers, which have **no** upper-bound check at all.

---
# Root Cause Analysis

The C2 envelope framing protocol uses a 4-byte little-endian length prefix to delimit protobuf messages on the wire:

```
[raw_signature (74 bytes)] [uint32 length] [protobuf data]
```

In [socketReadEnvelope](https://github.com/BishopFox/sliver/blob/master/server/c2/mtls.go#L337-L392), after reading the length prefix, the server immediately allocates a buffer of the attacker-specified size:

```go
// server/c2/mtls.go
const ServerMaxMessageSize = (2 * 1024 * 1024 * 1024) - 1  // ~2 GiB

dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf))
if dataLength <= 0 || ServerMaxMessageSize < dataLength {
    return nil, errors.New("[pivot] invalid data length")
}
dataBuf := make([]byte, dataLength)  // ← Allocates up to ~2 GiB

// ... data is read into buffer ...

// Envelope signature verification happens AFTER allocation and read:
if !ed25519.Verify(pubKey, dataBuf, signature) {
    return nil, errors.New("[mtls] invalid signature")
}
```

**Key issues:**

1. **Excessive limit**: `ServerMaxMessageSize` is set to `(2 * 1024 * 1024 * 1024) - 1` ≈ **2 GiB**, far exceeding any legitimate protobuf envelope (large payloads like screenshots and downloads are chunked at the RPC layer).
2. **Allocation before envelope verification**: While the TLS handshake validates the client certificate, the per-envelope ed25519 signature check (`ed25519.Verify`) occurs **after** the buffer allocation and `io.ReadFull`. Once the TLS connection is established, no further cryptographic proof is needed to trigger the allocation.
3. **Yamux amplification**: The yamux session allows up to `mtlsYamuxMaxConcurrentStreams = 128` concurrent streams. Each stream processes `socketReadEnvelope` independently, so a single connection can trigger **128 parallel ~2 GiB allocations**.
4. **Implant-side exposure**: The implant-side readers ([ReadEnvelope](https://github.com/BishopFox/sliver/blob/master/implant/sliver/transports/mtls/mtls.go#L184) in mTLS/WireGuard, [read()](https://github.com/BishopFox/sliver/blob/master/implant/sliver/pivots/pivots.go#L478) in pivots) have **no upper-bound check at all** — they accept any `dataLength > 0