Sliver of Truth: Exposing the C2 Server via Path Traversal
Feb 5, 2026·5 min read·4 visits
Executive Summary (TL;DR)
Authenticated operators on a Sliver C2 server (v1.6.10 and below) can read arbitrary files on the host system by using directory traversal sequences (`../`) in the `WebsiteAddContent` RPC. Fixed in v1.6.11.
Bishop Fox Sliver, a premier command and control framework, suffers from an authenticated path traversal vulnerability in its website management subsystem. By manipulating the logical path of hosted content, an operator can coerce the server into reading arbitrary files from the host filesystem. This turns the hunters into the hunted, allowing low-privileged operators to exfiltrate sensitive server configurations, SSH keys, or system credentials.
The Hook: When the C2 Becomes the Target
Sliver is the darling of the modern red team arsenal. Written in Go, supporting multi-player operations, and packed with features, it's the tool used to manage implants inside compromised networks. We usually think of the C2 server as the fortress—the unassailable base of operations. But what happens when the fortress has a back door unlocked from the inside?
This vulnerability (GHSA-2286-HXV5-CMP2) isn't an exploit against the implants or the victims. It's a fratricidal flaw in the C2 server itself. It allows any authenticated operator—even one with restricted permissions—to read files off the server's disk.
Imagine a scenario where a Blue Team captures a low-level operator's client configuration. Normally, they might just kick the operator or see some logs. With this bug, they can pivot from that stolen config to reading /etc/shadow on your infrastructure. It is a classic case of "trusted input" going rogue.
The Flaw: Trusting the Path
The vulnerability lies in the Website Content Subsystem. Sliver allows operators to host static content (like phishing pages or payload delivery sites) directly from the C2 server. When an operator adds content, they specify a Path (e.g., /index.html) and the raw bytes.
The logic flaw here is a textbook misuse of Golang's path/filepath package. When the server needed to retrieve this content later, it didn't look up a database ID or a hash; it looked up the file on disk using the path provided by the user.
Specifically, the server took the root directory for web content and simply joined it with the user-supplied path using filepath.Join. While filepath.Join cleans up dirty paths, it does not sandbag them against directory traversal if the resulting path is syntactically valid. If you ask for ../../etc/passwd, the server happily resolves the path relative to the web root, realizes it points outside, and—crucially—proceeds to read it anyway.
The Code: A Tale of Two Joins
Let's look at the smoking gun in server/db/models/website.go. In the vulnerable versions, the server reconstructed the file path blindly using the user's input stored in webcontent.Path.
Vulnerable Code:
// The server blindly joins the base directory with the user-controlled Path
contents, _ := os.ReadFile(filepath.Join(webContentDir, webcontent.Path))If webcontent.Path is ../../../../etc/shadow, the code effectively runs os.ReadFile("/root/.sliver/web/../../../../etc/shadow"). Since the Sliver server often runs with high privileges (sometimes root, though it shouldn't), this reads the system's shadow file.
The Fix (Commit 818127349ccec812876693c4ca74ebf4350ec6b7):
The Bishop Fox team fixed this by decoupling the logical path (the URL) from the physical path (the file on disk). Instead of using the user's string as a filename, they now use the database's internal UUID for the content.
// The server now uses a generated UUID, which cannot contain traversal characters
contents, err := os.ReadFile(filepath.Join(webContentDir, webcontent.ID.String()))Now, even if the user sets the path to ../../etc/passwd, the server ignores it during file retrieval and looks for a file named 550e8400-e29b-41d4-a716-446655440000 (or similar UUID) inside the web content directory. Simple, elegant, and secure.
The Exploit: Reading /etc/hosts
Exploiting this requires an authenticated mTLS connection to the Sliver server. This means you need a valid operator config file (.cfg). Once connected, we abuse the gRPC interface.
The Attack Chain:
- Craft the Payload: We create a
WebsiteAddContentrequest. We set theNameto a dummy website and, critically, we set thePathto a traversal string like../../../../../../etc/hosts. - Poison the Database: We send this request. The server saves the metadata to its SQL database. It might fail to write the file to disk locally depending on permissions, or it might write it successfully. But the read is what we care about.
- Trigger the Read: We call the
WebsiteRPC to request details about our site. The server iterates through the content entries. When it hits our malicious entry, it executes the vulnerableos.ReadFilelogic. - Exfiltrate: The server reads the actual
/etc/hostsfrom the host OS, packages the bytes into the Protobuf response, and sends it back to our client.
Here is a snippet of how a researcher might construct the traversal path in Go:
// Calculate traversal depth dynamically or just spam ../
targetPath := "/etc/passwd"
webPath := "../../../../../../../../" + strings.TrimPrefix(targetPath, "/")
// Send the malicious gRPC call
rpc.WebsiteAddContent(ctx, &clientpb.WebsiteAddContent{
Name: "exploit-site",
Contents: map[string]*clientpb.WebContent{
webPath: {
Path: webPath,
ContentType: "text/plain",
Content: []byte("irrelevant"),
},
},
})The Impact: Why This Hurts
You might argue, "If I have an operator config, I already own the C2." Not necessarily. Sliver supports multi-user environments with different roles. This vulnerability collapses those boundaries.
The Real Danger:
- Server Compromise: Reading
/root/.ssh/id_rsaor/etc/shadowallows the attacker to SSH into the C2 server itself, gaining full root shell access outside the Sliver environment. - Config Theft: The attacker could read the server's main configuration file, potentially recovering database credentials or other sensitive API keys used for integrations (e.g., Discord or Slack webhooks).
- Lateral Movement: If the C2 server is inside a protected network segment (e.g., a redirector setup), reading local files helps map the internal network topology via
/etc/hostsor network config files.
This is a classic privilege escalation: from "Application User" to "System Administrator".
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Sliver Bishop Fox | < 1.6.11 | 1.6.11 |
| Attribute | Detail |
|---|---|
| CVE ID | N/A (GHSA-2286-HXV5-CMP2) |
| CVSS v3.1 | 6.5 (Medium) |
| Attack Vector | Network (Authenticated gRPC) |
| CWE | CWE-22 (Path Traversal) |
| Impact | Arbitrary File Read |
| Privileges Required | Low (Operator) |
MITRE ATT&CK Mapping
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.