Know every vulnerabilitybefore it knows you.
DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.
GHSA-97vp-pwqj-46qc
No affected components available
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, after reading the length prefix, the server immediately allocates a buffer of the attacker-specified size:
// 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:
- Excessive limit:
ServerMaxMessageSizeis 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). - 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 andio.ReadFull. Once the TLS connection is established, no further cryptographic proof is needed to trigger the allocation. - Yamux amplification: The yamux session allows up to
mtlsYamuxMaxConcurrentStreams = 128concurrent streams. Each stream processessocketReadEnvelopeindependently, so a single connection can trigger 128 parallel ~2 GiB allocations. - Implant-side exposure: The implant-side readers (ReadEnvelope in mTLS/WireGuard, read() in pivots) have no upper-bound check at all — they accept any
dataLength > 0.
The same pattern exists in socketWGReadEnvelope for the WireGuard transport.
Note: The same unbounded allocation pattern is also present in implant-side readers, though it poses no immediate risk to the server 1, 2, 3, 4.
Proof of Concept
PoC Links: mtls_poc.go or Gist Version
- Establish mTLS connection: Complete a valid TLS 1.3 handshake presenting a valid implant client certificate.
- Negotiate yamux: Send the
MUX/1preface to enter multiplexed stream mode. - Open concurrent streams: Open multiple yamux streams (up to 128).
- Send malicious length prefix: On each stream, send a 74-byte raw signature buffer followed by a 4-byte length prefix claiming
0x7FFFFFFF(2,147,483,647 bytes ≈ 2 GiB). No actual data needs to follow. - Result: Each stream triggers a
make([]byte, 0x7FFFFFFF)allocation. With 128 concurrent streams, the server process attempts to allocate up to ~256 GiB of memory, causing the OS OOM killer to terminate the process.
Impact
- Server availability: The Sliver server process is killed. Active implant sessions are disrupted until the operator manually restarts the server.
- Host degradation: On hosts with swap enabled, the OOM event may cause swap thrashing and degrade other services sharing the same host before the process is killed.
The vulnerability can be exploited over the network without needing physical access. It is easy for an attacker to exploit this vulnerability. An attacker needs basic access or low-level privileges. No user interaction is needed for the attacker to exploit this vulnerability.
Exploitation attempts have been detected. Elevated vigilance and prompt remediation are advised.
The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.
We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.
Browse More
Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.
Checkout DevGuard