CVE-2026-29781: Github.com/bishopfox/sliver Sliver Is Vulnerable To Authenticated Vulnerability

LOW
Advisory Identifier: GHSA-hx52-cv84-jr5v
CWE-476
Published
Advisory Summary

CVE-2026-29781 is a LOW sliver is vulnerable to authenticated vulnerability (CWE-476: NULL Pointer Dereference) affecting Github.com/bishopfox/sliver libraries in the Go ecosystem. The issue involves sliver is vulnerable to authenticated nil-pointer dereference through its handlers. Remediation is available in the latest vendor maintenance releases.

CVE-2026-29781 at a Glance

CVE Identifier CVE-2026-29781
GHSA Identifier GHSA-hx52-cv84-jr5v
Severity LOW
CVSS v3.1 Base Score N/A
CWE Classification CWE-476: NULL Pointer Dereference
Affected Product Github.com/bishopfox/sliver
Package Ecosystem Go
Published Date
Last Updated

How to Fix CVE-2026-29781

To remediate this vulnerability, upgrade all affected Github.com/bishopfox/sliver dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/bishopfox/sliver fixed: Latest secure release
Upgrade github.com/bishopfox/sliver to Latest secure release
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/bishopfox/sliver

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-29781, inspect your project dependencies for Github.com/bishopfox/sliver:

inspect dependencies for github.com/bishopfox/sliver

Analyze the terminal output to locate any version of Github.com/bishopfox/sliver in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than the patched release), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-476: NULL Pointer Dereference, where the product dereferences a pointer that it expects to be valid but is null. In Github.com/bishopfox/sliver, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## 1. Executive Summary A vulnerability exists in the Sliver C2 server's Protobuf unmarshalling logic due to a systemic lack of nil-pointer validation. By extracting valid implant credentials and omitting nested fields in a signed message, an authenticated actor can trigger an unhandled runtime panic. Because the mTLS, WireGuard, and DNS transport layers lack the panic recovery middleware present in the HTTP transport, this results in a global process termination. While requiring post-authentication access (a captured implant), this flaw effectively acts as an infrastructure "kill-switch," instantly severing all active sessions across the entire fleet and requiring a manual server restart to restore operations. ## 2. Vulnerability Details ### 2.0 Technical Workflow: From Envelope to Handler Sliver encapsulates all C2 traffic in a generic `sliverpb.Envelope`, which acts as a routing wrapper. When the server receives an Envelope with `Type = 53` (MsgBeaconRegister), the internal router strips the envelope and passes the raw `Data` bytes directly to the vulnerable `handlers.beaconRegisterHandler(implantConn, data)`. This flow is consistent across all transports, but the **error handling** of the transport itself determines the final impact. ### 2.1 BeaconRegister Nil-Pointer Dereference - **Vulnerability Type:** Remote Denial of Service via Nil-Pointer Dereference ([CWE-476](https://cwe.mitre.org/data/definitions/476.html)) - **Component:** `server/handlers/beacons.go` - **Affected Functions:** [beaconRegisterHandler](https://github.com/BishopFox/sliver/blob/master/server/handlers/beacons.go#L46-L110). - **Severity:** Critical - **Complexity:** Low #### Root Cause Analysis The core of the vulnerability lies in the architectural handling of Protobuf messages within the Go runtime. In `proto3`, all fields are optional by design. When a message contains a nested sub-message (like `Register` inside `BeaconRegister`), the Go Protobuf implementation represents this sub-message as a **pointer**. In `server/handlers/beacons.go`, the server unmarshals the incoming data without subsequent validation of its nested structures: ```Go func beaconRegisterHandler(implantConn *core.ImplantConnection, data []byte) *sliverpb.Envelope { // ... beaconReg := &sliverpb.BeaconRegister{} err := proto.Unmarshal(data, beaconReg) // Successful even if 'Register' sub-message is omitted // VULNERABILITY: beaconReg.Register is nil if omitted by sender. // Accessing any property of a nil pointer triggers an immediate runtime panic. beaconRegUUID, _ := uuid.FromString(beaconReg.Register.Uuid) // ... } ``` If an attacker constructs a `BeaconRegister` message and deliberately omits the `Register` field, `proto.Unmarshal` parses the stream without error but leaves the `Register` pointer as `nil`. The subsequent attempt to access `beaconReg.Register.Uuid` triggers a **Nil-Pointer Dereference**. ### 2.2 Expanded Inventory: System-Wide Nil-Pointer Vulnerabilities Beyond the beacon registration, the investigation revealed a systemic pattern of missing nil-checks across various handlers. These vulnerabilities follow the same root cause: immediate dereferencing of nested Protobuf fields post-unmarshalling. #### 2.2.1 Remote Implant Vectors (Unauthenticated) These handlers process data from implants. If an implant binary is captured, these can be triggered to crash the server: - **Reverse Tunneling (`server/handlers/sessions.go`):** The `createReverseTunnelHandler` panics when `req.Rportfwd` is omitted. - **SOCKS Proxying (`server/handlers/sessions.go`):** The `socksDataHandler` fails when the `SocksData` sub-message is absent. - **Pivot/Peer Communication (`server/handlers/pivot.go`):** Functions `serverKeyExchange` and `peersToString` dereference `peerEnvelope.Peers` without checking if the peer list is empty or nil. #### 2.2.2 Authenticated Operator Vectors (gRPC Layer) The Sliver RPC server (`server/rpc/`) is also susceptible. While these require an authenticated operator, they represent a significant stability risk where a malformed request from a custom client or automated script can bring down the entire C2 infrastructure. | Function | File | Vulnerable Pattern | | ------------------- | ------------------------------- | ------------------------------------------------------- | | getTimeout | server/rpc/rpc.go | `req.GetRequest().Timeout` | | getError | server/rpc/rpc.go | `resp.GetResponse().Err` | | Portfwd | server/rpc/rpc-portfwd.go | `req.Request.SessionID` | | GetSystem | server/rpc/rpc-priv.go | `req.GetRequest().SessionID` | | GetPrivileges | server/rpc/rpc-priv.go | `req.Request.SessionID` | | NetConnPivot | server/rpc/rpc-pivot.go | `req.Request.SessionID` | | PivotListeners | server/rpc/rpc-pivot.go | `req.Request.SessionID` | | SocksStart | server/rpc/rpc-socks.go | `req.Request.SessionID` | | SocksStop | server/rpc/rpc-socks.go | `req.Request.SessionID` | | RPortfwd | server/rpc/rpc-rportfwd.go | `req.Request.SessionID` | | Shell | server/rpc/rpc-shell.go | `req.Request.SessionID` | | ShellResize | server/rpc/rpc-shell.go | `req.Request.SessionID` | | BackdoorImplant | server/rpc/rpc-backdoor.go | `req.Request.SessionID`, `req.Request.Timeout` | | CrackstationTrigger | server/rpc/rpc-crackstations.go | `statusUpdate.HostUUID` (after unmarshal of `req.Data`) | | Tasks | server/rpc/rpc-tasks.go | `req.Request.SessionID` | | ImplantReconfig | server/rpc/rpc-reconfig.go | `req.Request.SessionID` | | MsfInject | server/rpc/rpc-msf.go | `req.Request.SessionID` | | Hijack | server/rpc/rpc-hijack.go | `req.Request.SessionID` | --- ## 3. Proof of Concept & Attack Feasibility ### 3.1 Attack Feasibility: Credential Extraction The exploit requires valid implant credentials, which are inherently embedded in Sliver's generated binaries. Since these binaries are often deployed to untrusted or compromised environments, credential recovery is a high-probability event. During testing, it was confirmed that an attacker can obtain the required mTLS certificates and Age Secret Keys through: - **Static Extraction (Trivial):** By default, running the `strings` utility on the implant binary or dumping the embedded configuration block is sufficient to recover the private keys. - **Memory Forensics:** If an implant is captured during execution, the configuration structures can be carved directly from the process memory, bypassing most disk-level obfuscation. ### 3.2 Exploit Execution Flow The provided exploit [mtls_poc.go](https://github.com/skoveit/Sliver-Nil-Pointer-DoS-PoC/blob/main/mtls_poc.go) or [mtls_poc.go](https://gist.github.com/skoveit/a5e52b5c9197fc53e2605a861cd8aa33) demonstrates how a single captured implant can be weaponized into a "Kill Switch" for the entire C2 infrastructure. The attack follows these steps: 1. **Authentication:** Establishes a valid mTLS connection using the extracted certificates. 2. **Multiplexing:** Negotiates a Yamux stream, bypassing standard network-level protections. 3. **Payload Construction:** Builds a `BeaconRegister` Protobuf message where the `ID` is defined, but the critical `Register` sub-message is explicitly omitted (set to `nil`). 4. **Envelope Signing:** Deterministically signs the malicious envelope using the recovered Age private key to ensure it is accepted by the server. 5. **Trigger:** Sends the malformed payload. Upon receipt, the server's handler attempts to dereference the missing `Register` pointer, leading to an immediate **Full Server DoS**. ## 4. Transport-Specific Response & Recovery Analysis The impact of this panic varies significantly depending on the C2 transport used by the implant. While the nil-pointer dereference happens in the shared handler logic, the transport layer determines whether this results in a localized request failure or a total server termination. ### 4.1 HTTP/S Transport HTTP-based beacons do **not** crash the entire Sliver server. This is because Sliver utilizes the standard Go `net/http` library. **Code Reference ([server/c2/http.go](https://github.com/BishopFox/sliver/blob/master/server/c2/http.go)):** ```go server.HTTPServer = &http.Server{ Addr: fmt.Sprintf("%s:%d", req.Host, req.Port), Handler: server.router(), // ... } // ... go server.HTTPServer.ListenAndServe() ``` By design, `net/http`'s `ServeHTTP` implementation wraps every connection in a `defer recover()` block. When the [beaconRegisterHandler](https://github.com/BishopFox/sliver/blob/master/server/handlers/beacons.go#L46-L109) panics, the standard library catches it, logs the trace, and simply closes that specific TCP connection. The rest of the server remains unaffected. ### 4.2 mTLS & WireGuard Transports (Full DoS) Both mTLS and WireGuard utilize the `yamux` multiplexer to handle multiple streams over a single connection. Unlike the HTTP server, Sliver manually manages these goroutines without a global recovery mechanism. **mTLS [server/c2/mtls.go](https://github.com/BishopFox/sliver/blob/master/server/c2/mtls.go):** ```go if handler, ok := handlers[envelope.Type]; ok { mtlsLog.Debugf("Received new mtls message type %d, data: %s", envelope.Type, envelope.Data) go func(envelope *sliverpb.Envelope) { respEnvelope := handler(implantConn, envelope.Data) // <--- PANIC HERE if respEnvelope != nil { implantConn.Send <- respEnvelope } }(envelope) } ``` **WireGuard [server/c2/wireguard.go](https://github.com/BishopFox/sliver/blob/master/server/c2/wireguard.go):** ```go if handler, ok := handlers[envelope.Type]; ok { go func(envelope *sliverpb.Envelope) { respEnvelope := handler(implantConn, envelope.Data) // <--- PANIC HERE // ... }(envelope) } ``` Because these handlers are invoked in a **raw goroutine** without a `recover()` block, the panic propagates to the top of the stack, causing the entire Go runtime to exit (SIGSEGV). This kills the `sliver-server` process immediately. ### 4.3 DNS Transport (Full DoS) Similar to mTLS, the DNS transport reassembles messages and then forwards them to handlers in unsynchronized goroutines. **DNS [server/c2/dns.go](https://github.com/BishopFox/sliver/blob/master/server/c2/dns.go):** ```go // Line 833: Forwarding the completed envelope go dnsSession.ForwardCompletedEnvelope(msg.ID, pending) // ... // Inside ForwardCompletedEnvelope: if handler, ok := handlers[envelope.Type]; ok { respEnvelope := handler(s.ImplantConn, envelope.Data) // <--- PANIC HERE // ... } ``` This asynchronous call also lacks a `recover()` block, making DNS sessions equally capable of crashing the entire server. ### 4.4 Vulnerability Matrix by Protocol | Protocol | Uses `recover()`? | Impact of Panic | Server Crash? | | :--- | :---: | :--- | :---: | | **HTTP / HTTPS** | Yes (Built-in) | Request Terminated | No | | **mTLS** | No | Process Termination | **Yes** | | **WireGuard** | No | Process Termination | **Yes** | | **DNS** | No | Process Termination | **Yes** | ## 5. Impact Analysis The impact of this vulnerability is **Total Operational Paralysis**. Because the panic causes the entire Go runtime to terminate: - **Global Disconnection:** Every active session and beacon across all transports (including the resilient HTTP transport) is instantly terminated. - **Persistence Risk:** Implants waiting for their next check-in will find the server offline. Repeated failures may trigger internal implant "kill-date" or cleanup logic, or alert defensive monitoring to a failure in the C2 channel. - **Operator Eviction:** All active operators are evicted from the gRPC interface, losing all unsaved state, active shell buffers, and real-time monitoring streams. - **Operational Downtime:** Restoration requires manual intervention to restart the service and potentially re-establish complex pivot chains, creating a significant "Recovery Time Objective" (RTO) penalty. ## 6. Countermeasures & Remediation Addressing these vulnerabilities requires a systemic shift towards "fail-safe" architecture. The root cause is a combination of unprotected Protobuf pointer dereferences and a lack of isolation in asynchronous transport layers. ### 6.1 Tier 1: Tactical Defensive Programming The immediate priority is to implement strict validation for all nested Protobuf fields. In Go, omitted sub-messages are `nil` after unmarshaling; handlers must assume any pointer-typed field from an implant is potentially `nil`. #### Implementation Pattern: Validation-First Handlers Handlers should validate the entire message structure before proceeding to business logic. ```go beaconReg := &sliverpb.BeaconRegister{} if err := proto.Unmarshal(data, beaconReg); err != nil { return nil // Drop malformed wire data } // MANDATORY VALIDATION BLOCK if beaconReg.Register == nil { beaconHandlerLog.Errorf("Nil Register message from %s", core.GetRemoteAddr(implantConn)) return nil } // Deep access is now safe id := beaconReg.Register.Uuid // ... ``` ### 6.2 Tier 2: Infrastructure Hardening (RPC Global Accessors) To protect the gRPC/Operator interface, the server should deprecate direct access to the [Request](https://github.com/BishopFox/sliver/blob/master/server/core/sessions.go#L148-L185) metadata field in favor of safe accessors that handle missing metadata gracefully. #### Recommended Helper Update ```go // server/rpc/rpc.go // getRequestSafe returns the Request metadata or an error, preventing panics func getRequestSafe(req GenericRequest) (*commonpb.Request, error) { r := req.GetRequest() if r == nil { return nil, status.Error(codes.InvalidArgument, "missing mandatory 'Request' metadata") } return r, nil } ``` ### 6.3 Tier 3: Strategic Architectural Resilience (Panic Recovery Middleware) To achieve parity with the resilience of the HTTP transport, all multiplexed transports (mTLS, WireGuard, DNS) must implement a supervisor pattern using Go's `recover()` mechanism. #### Implementation: Protected Handler Invoke All handlers should be executed inside a "Safe Wrapper" that catches runtime panics, logs the failure, and terminates only the affected stream without crashing the entire C2 daemon. ```go func SafeInvoke(handler ServerHandler, conn *core.ImplantConnection, data []byte) { defer func() { if r := recover(); r != nil { log.Errorf("RECOVERY: Intercepted panic in handler: %v\n%s", r, debug.Stack()) // The daemon continues running; only this specific action failed. } }() response := handler(conn, data) if response != nil { conn.Send <- response } } ``` ### 6.4 Tier 4: Long-Term Assurance The framework should move away from manual nil-checking towards automated schema validation: - **`protoc-gen-validate` (PGV)**: Annotate [.proto](https://github.com/BishopFox/sliver/blob/master/protobuf/dnspb/dns.proto) files with `(validate.rules).message.required = true` and generate automatic validation code. - **Static Analysis CI**: Integrate custom linters to detect unprotected pointer dereferences of Protobuf types during the PR process. By adopting this multi-tiered approach, Sliver evolves from a "fail-deadly" design to a robust, enterprise-grade C2 architecture.

CVE-2026-29781 Affected Github.com/bishopfox/sliver Versions

1 component(s)
Product / Package Ecosystem Affected Versions Fixed Version
github.com/bishopfox/sliver
Go
≤ 1.7.3

References

Frequently Asked Questions

What is CVE-2026-29781?
CVE-2026-29781 is a security vulnerability in Github.com/bishopfox/sliver involving Sliver is Vulnerable to Authenticated Nil-Pointer Dereference through its Handlers under CWE-476: NULL Pointer Dereference.
Which Github.com/bishopfox/sliver versions are affected?
Affected versions include releases prior to current release patches across affected packages: github.com/bishopfox/sliver.
What version fixes CVE-2026-29781?
Upgrading to current release patches (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/bishopfox/sliver affected?
Yes, github.com/bishopfox/sliver is affected in releases prior to Latest secure release. Upgrade your dependency to Latest secure release or later.
What CWE is associated with CVE-2026-29781?
CVE-2026-29781 is classified under CWE-476: NULL Pointer Dereference (The product dereferences a pointer that it expects to be valid but is NULL.).
How can I check Go dependencies for CVE-2026-29781?
Run the dependency tree command: 'inspect dependencies for github.com/bishopfox/sliver'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-hx52-cv84-jr5v",
  "modified" : "2026-03-09T15:49:25Z",
  "published" : "2026-03-05T00:26:40Z",
  "aliases" : [ "CVE-2026-29781" ],
  "summary" : "Sliver is Vulnerable to Authenticated Nil-Pointer Dereference through its Handlers",
  "details" : "## 1. Executive Summary\nA vulnerability exists in the Sliver C2 server's Protobuf unmarshalling logic due to a systemic lack of nil-pointer validation. By extracting valid implant credentials and omitting nested fields in a signed message, an authenticated actor can trigger an unhandled runtime panic. Because the mTLS, WireGuard, and DNS transport layers lack the panic recovery middleware present in the HTTP transport, this results in a global process termination. While requiring post-authentication access (a captured implant), this flaw effectively acts as an infrastructure \"kill-switch,\" instantly severing all active sessions across the entire fleet and requiring a manual server restart to restore operations.\n\n## 2. Vulnerability Details\n### 2.0 Technical Workflow: From Envelope to Handler\nSliver encapsulates all C2 traffic in a generic `sliverpb.Envelope`, which acts as a routing wrapper. When the server receives an Envelope with `Type = 53` (MsgBeaconRegister), the internal router strips the envelope and passes the raw `Data` bytes directly to the vulnerable `handlers.beaconRegisterHandler(implantConn, data)`. This flow is consistent across all transports, but the **error handling** of the transport itself determines the final impact.\n\n### 2.1 BeaconRegister Nil-Pointer Dereference\n- **Vulnerability Type:** Remote Denial of Service via Nil-Pointer Dereference ([CWE-476](https://cwe.mitre.org/data/definitions/476.html))\n- **Component:** `server/handlers/beacons.go`\n- **Affected Functions:** [beaconRegisterHandler](https://github.com/BishopFox/sliver/blob/master/server/handlers/beacons.go#L46-L110).\n- **Severity:** Critical\n- **Complexity:** Low\n\n#### Root Cause Analysis\nThe core of the vulnerability lies in the architectural handling of Protobuf messages within the Go runtime. In `proto3`, all fields are optional by design. When a message contains a nested sub-message (like `Register` inside `BeaconRegister`), the Go Protobuf implementation represents this sub-message as a **pointer**.\n\nIn `server/handlers/beacons.go`, the server unmarshals the incoming data without subsequent validation of its nested structures:\n```Go\nfunc beaconRegisterHandler(implantConn *core.ImplantConnection, data []byte) *sliverpb.Envelope {\n    // ...\n    beaconReg := &sliverpb.BeaconRegister{}\n    err := proto.Unmarshal(data, beaconReg)\n\t// Successful even if 'Register' sub-message is omitted\n    \n    // VULNERABILITY: beaconReg.Register is nil if omitted by sender.\n    // Accessing any property of a nil pointer triggers an immediate runtime panic.\n    beaconRegUUID, _ := uuid.FromString(beaconReg.Register.Uuid) \n    // ...\n}\n```\n\nIf an attacker constructs a `BeaconRegister` message and deliberately omits the `Register` field, `proto.Unmarshal` parses the stream without error but leaves the `Register` pointer as `nil`. The subsequent attempt to access `beaconReg.Register.Uuid` triggers a **Nil-Pointer Dereference**.\n### 2.2 Expanded Inventory: System-Wide Nil-Pointer Vulnerabilities\nBeyond the beacon registration, the investigation revealed a systemic pattern of missing nil-checks across various handlers. These vulnerabilities follow the same root cause: immediate dereferencing of nested Protobuf fields post-unmarshalling.\n\n#### 2.2.1 Remote Implant Vectors (Unauthenticated)\nThese handlers process data from implants. If an implant binary is captured, these can be triggered to crash the server:\n- **Reverse Tunneling (`server/handlers/sessions.go`):** The `createReverseTunnelHandler` panics when `req.Rportfwd` is omitted.\n- **SOCKS Proxying (`server/handlers/sessions.go`):** The `socksDataHandler` fails when the `SocksData` sub-message is absent.\n- **Pivot/Peer Communication (`server/handlers/pivot.go`):** Functions `serverKeyExchange` and `peersToString` dereference `peerEnvelope.Peers` without checking if the peer list is empty or nil.\n\n#### 2.2.2 Authenticated Operator Vectors (gRPC Layer)\nThe Sliver RPC server (`server/rpc/`) is also susceptible. While these require an authenticated operator, they represent a significant stability risk where a malformed request from a custom client or automated script can bring down the entire C2 infrastructure.\n\n| Function            | File                            | Vulnerable Pattern                                      |\n| ------------------- | ------------------------------- | ------------------------------------------------------- |\n| getTimeout          | server/rpc/rpc.go               | `req.GetRequest().Timeout`                              |\n| getError            | server/rpc/rpc.go               | `resp.GetResponse().Err`                                |\n| Portfwd             | server/rpc/rpc-portfwd.go       | `req.Request.SessionID`                                 |\n| GetSystem           | server/rpc/rpc-priv.go          | `req.GetRequest().SessionID`                            |\n| GetPrivileges       | server/rpc/rpc-priv.go          | `req.Request.SessionID`                                 |\n| NetConnPivot        | server/rpc/rpc-pivot.go         | `req.Request.SessionID`                                 |\n| PivotListeners      | server/rpc/rpc-pivot.go         | `req.Request.SessionID`                                 |\n| SocksStart          | server/rpc/rpc-socks.go         | `req.Request.SessionID`                                 |\n| SocksStop           | server/rpc/rpc-socks.go         | `req.Request.SessionID`                                 |\n| RPortfwd            | server/rpc/rpc-rportfwd.go      | `req.Request.SessionID`                                 |\n| Shell               | server/rpc/rpc-shell.go         | `req.Request.SessionID`                                 |\n| ShellResize         | server/rpc/rpc-shell.go         | `req.Request.SessionID`                                 |\n| BackdoorImplant     | server/rpc/rpc-backdoor.go      | `req.Request.SessionID`, `req.Request.Timeout`          |\n| CrackstationTrigger | server/rpc/rpc-crackstations.go | `statusUpdate.HostUUID` (after unmarshal of `req.Data`) |\n| Tasks               | server/rpc/rpc-tasks.go         | `req.Request.SessionID`                                 |\n| ImplantReconfig     | server/rpc/rpc-reconfig.go      | `req.Request.SessionID`                                 |\n| MsfInject           | server/rpc/rpc-msf.go           | `req.Request.SessionID`                                 |\n| Hijack              | server/rpc/rpc-hijack.go        | `req.Request.SessionID`                                 |\n\n---\n\n## 3. Proof of Concept & Attack Feasibility\n### 3.1 Attack Feasibility: Credential Extraction\nThe exploit requires valid implant credentials, which are inherently embedded in Sliver's generated binaries. Since these binaries are often deployed to untrusted or compromised environments, credential recovery is a high-probability event. During testing, it was confirmed that an attacker can obtain the required mTLS certificates and Age Secret Keys through:\n- **Static Extraction (Trivial):** By default, running the `strings` utility on the implant binary or dumping the embedded configuration block is sufficient to recover the private keys.\n- **Memory Forensics:** If an implant is captured during execution, the configuration structures can be carved directly from the process memory, bypassing most disk-level obfuscation.\n\n### 3.2 Exploit Execution Flow\nThe provided exploit [mtls_poc.go](https://github.com/skoveit/Sliver-Nil-Pointer-DoS-PoC/blob/main/mtls_poc.go) or [mtls_poc.go](https://gist.github.com/skoveit/a5e52b5c9197fc53e2605a861cd8aa33) demonstrates how a single captured implant can be weaponized into a \"Kill Switch\" for the entire C2 infrastructure. The attack follows these steps:\n1. **Authentication:** Establishes a valid mTLS connection using the extracted certificates.\n2. **Multiplexing:** Negotiates a Yamux stream, bypassing standard network-level protections.\n3. **Payload Construction:** Builds a `BeaconRegister` Protobuf message where the `ID` is defined, but the critical `Register` sub-message is explicitly omitted (set to `nil`).\n4. **Envelope Signing:** Deterministically signs the malicious envelope using the recovered Age private key to ensure it is accepted by the server.\n5. **Trigger:** Sends the malformed payload. Upon receipt, the server's handler attempts to dereference the missing `Register` pointer, leading to an immediate **Full Server DoS**.\n\n## 4. Transport-Specific Response & Recovery Analysis\nThe impact of this panic varies significantly depending on the C2 transport used by the implant. While the nil-pointer dereference happens in the shared handler logic, the transport layer determines whether this results in a localized request failure or a total server termination.\n\n### 4.1 HTTP/S Transport\nHTTP-based beacons do **not** crash the entire Sliver server. This is because Sliver utilizes the standard Go `net/http` library.\n\n**Code Reference ([server/c2/http.go](https://github.com/BishopFox/sliver/blob/master/server/c2/http.go)):**\n```go\nserver.HTTPServer = &http.Server{\n    Addr:         fmt.Sprintf(\"%s:%d\", req.Host, req.Port),\n    Handler:      server.router(),\n    // ...\n}\n// ...\ngo server.HTTPServer.ListenAndServe()\n```\n\nBy design, `net/http`'s `ServeHTTP` implementation wraps every connection in a `defer recover()` block. When the [beaconRegisterHandler](https://github.com/BishopFox/sliver/blob/master/server/handlers/beacons.go#L46-L109) panics, the standard library catches it, logs the trace, and simply closes that specific TCP connection. The rest of the server remains unaffected.\n\n### 4.2 mTLS & WireGuard Transports (Full DoS)\nBoth mTLS and WireGuard utilize the `yamux` multiplexer to handle multiple streams over a single connection. Unlike the HTTP server, Sliver manually manages these goroutines without a global recovery mechanism.\n\n**mTLS [server/c2/mtls.go](https://github.com/BishopFox/sliver/blob/master/server/c2/mtls.go):**\n```go\nif handler, ok := handlers[envelope.Type]; ok {\n    mtlsLog.Debugf(\"Received new mtls message type %d, data: %s\", envelope.Type, envelope.Data)\n    go func(envelope *sliverpb.Envelope) {\n        respEnvelope := handler(implantConn, envelope.Data) // <--- PANIC HERE\n        if respEnvelope != nil {\n            implantConn.Send <- respEnvelope\n        }\n    }(envelope)\n}\n```\n\n**WireGuard [server/c2/wireguard.go](https://github.com/BishopFox/sliver/blob/master/server/c2/wireguard.go):**\n```go\nif handler, ok := handlers[envelope.Type]; ok {\n    go func(envelope *sliverpb.Envelope) {\n        respEnvelope := handler(implantConn, envelope.Data) // <--- PANIC HERE\n        // ...\n    }(envelope)\n}\n```\n\nBecause these handlers are invoked in a **raw goroutine** without a `recover()` block, the panic propagates to the top of the stack, causing the entire Go runtime to exit (SIGSEGV). This kills the `sliver-server` process immediately.\n\n### 4.3 DNS Transport (Full DoS)\nSimilar to mTLS, the DNS transport reassembles messages and then forwards them to handlers in unsynchronized goroutines.\n\n**DNS [server/c2/dns.go](https://github.com/BishopFox/sliver/blob/master/server/c2/dns.go):**\n```go\n// Line 833: Forwarding the completed envelope\ngo dnsSession.ForwardCompletedEnvelope(msg.ID, pending)\n// ...\n// Inside ForwardCompletedEnvelope:\nif handler, ok := handlers[envelope.Type]; ok {\n    respEnvelope := handler(s.ImplantConn, envelope.Data) // <--- PANIC HERE\n    // ...\n}\n```\n\nThis asynchronous call also lacks a `recover()` block, making DNS sessions equally capable of crashing the entire server.\n\n### 4.4 Vulnerability Matrix by Protocol\n\n| Protocol | Uses `recover()`? | Impact of Panic | Server Crash? |\n| :--- | :---: | :--- | :---: |\n| **HTTP / HTTPS** | Yes (Built-in) | Request Terminated | No |\n| **mTLS** | No | Process Termination | **Yes** |\n| **WireGuard** | No | Process Termination | **Yes** |\n| **DNS** | No | Process Termination | **Yes** |\n\n\n## 5. Impact Analysis\nThe impact of this vulnerability is **Total Operational Paralysis**. Because the panic causes the entire Go runtime to terminate:\n- **Global Disconnection:** Every active session and beacon across all transports (including the resilient HTTP transport) is instantly terminated.\n- **Persistence Risk:** Implants waiting for their next check-in will find the server offline. Repeated failures may trigger internal implant \"kill-date\" or cleanup logic, or alert defensive monitoring to a failure in the C2 channel.\n- **Operator Eviction:** All active operators are evicted from the gRPC interface, losing all unsaved state, active shell buffers, and real-time monitoring streams.\n- **Operational Downtime:** Restoration requires manual intervention to restart the service and potentially re-establish complex pivot chains, creating a significant \"Recovery Time Objective\" (RTO) penalty.\n## 6. Countermeasures & Remediation\nAddressing these vulnerabilities requires a systemic shift towards \"fail-safe\" architecture. The root cause is a combination of unprotected Protobuf pointer dereferences and a lack of isolation in asynchronous transport layers.\n\n### 6.1 Tier 1: Tactical Defensive Programming\nThe immediate priority is to implement strict validation for all nested Protobuf fields. In Go, omitted sub-messages are `nil` after unmarshaling; handlers must assume any pointer-typed field from an implant is potentially `nil`.\n\n#### Implementation Pattern: Validation-First Handlers\nHandlers should validate the entire message structure before proceeding to business logic.\n\n```go\nbeaconReg := &sliverpb.BeaconRegister{}\nif err := proto.Unmarshal(data, beaconReg); err != nil {\n\treturn nil // Drop malformed wire data\n}\n\n// MANDATORY VALIDATION BLOCK\nif beaconReg.Register == nil {\n\tbeaconHandlerLog.Errorf(\"Nil Register message from %s\", core.GetRemoteAddr(implantConn))\n\treturn nil\n}\n\n// Deep access is now safe\nid := beaconReg.Register.Uuid\n// ...\n```\n\n### 6.2 Tier 2: Infrastructure Hardening (RPC Global Accessors)\nTo protect the gRPC/Operator interface, the server should deprecate direct access to the [Request](https://github.com/BishopFox/sliver/blob/master/server/core/sessions.go#L148-L185) metadata field in favor of safe accessors that handle missing metadata gracefully.\n#### Recommended Helper Update \n```go\n// server/rpc/rpc.go\n// getRequestSafe returns the Request metadata or an error, preventing panics\nfunc getRequestSafe(req GenericRequest) (*commonpb.Request, error) {\n    r := req.GetRequest()\n    if r == nil {\n        return nil, status.Error(codes.InvalidArgument, \"missing mandatory 'Request' metadata\")\n    }\n    return r, nil\n}\n```\n### 6.3 Tier 3: Strategic Architectural Resilience (Panic Recovery Middleware)\nTo achieve parity with the resilience of the HTTP transport, all multiplexed transports (mTLS, WireGuard, DNS) must implement a supervisor pattern using Go's `recover()` mechanism.\n\n#### Implementation: Protected Handler Invoke\nAll handlers should be executed inside a \"Safe Wrapper\" that catches runtime panics, logs the failure, and terminates only the affected stream without crashing the entire C2 daemon.\n\n```go\nfunc SafeInvoke(handler ServerHandler, conn *core.ImplantConnection, data []byte) {\n    defer func() {\n        if r := recover(); r != nil {\n            log.Errorf(\"RECOVERY: Intercepted panic in handler: %v\\n%s\", r, debug.Stack())\n            // The daemon continues running; only this specific action failed.\n        }\n    }()\n    \n    response := handler(conn, data)\n    if response != nil {\n        conn.Send <- response\n    }\n}\n```\n\n### 6.4 Tier 4: Long-Term Assurance\nThe framework should move away from manual nil-checking towards automated schema validation:\n- **`protoc-gen-validate` (PGV)**: Annotate [.proto](https://github.com/BishopFox/sliver/blob/master/protobuf/dnspb/dns.proto) files with `(validate.rules).message.required = true` and generate automatic validation code.\n- **Static Analysis CI**: Integrate custom linters to detect unprotected pointer dereferences of Protobuf types during the PR process.\n\nBy adopting this multi-tiered approach, Sliver evolves from a \"fail-deadly\" design to a robust, enterprise-grade C2 architecture.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/bishopfox/sliver"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "last_affected" : "1.7.3"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/BishopFox/sliver/security/advisories/GHSA-hx52-cv84-jr5v"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-29781"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/BishopFox/sliver"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-476" ],
    "severity" : "LOW",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-03-05T00:26:40Z",
    "nvd_published_at" : "2026-03-07T16:15:55Z"
  }
}