Skip to content

Sliver is Vulnerable to Authenticated Nil-Pointer Dereference through its Handlers

Low severity GitHub Reviewed Published Mar 4, 2026 in BishopFox/sliver • Updated Mar 9, 2026

Package

gomod github.com/bishopfox/sliver (Go)

Affected versions

<= 1.7.3

Patched versions

None

Description

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)
  • Component: server/handlers/beacons.go
  • Affected Functions: beaconRegisterHandler.
  • 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:

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.SessionIDreq.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 or mtls_poc.go 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):

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 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:

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:

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:

// 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.

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 metadata field in favor of safe accessors that handle missing metadata gracefully.

Recommended Helper Update

// 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.

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 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.

References

@moloch-- moloch-- published to BishopFox/sliver Mar 4, 2026
Published to the GitHub Advisory Database Mar 5, 2026
Reviewed Mar 5, 2026
Published by the National Vulnerability Database Mar 7, 2026
Last updated Mar 9, 2026

Severity

Low

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v4 base metrics

Exploitability Metrics
Attack Vector Network
Attack Complexity Low
Attack Requirements None
Privileges Required Low
User interaction None
Vulnerable System Impact Metrics
Confidentiality None
Integrity None
Availability Low
Subsequent System Impact Metrics
Confidentiality None
Integrity None
Availability None

CVSS v4 base metrics

Exploitability Metrics
Attack Vector: This metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the resulting severity) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable system. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater severity.
Attack Complexity: This metric captures measurable actions that must be taken by the attacker to actively evade or circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. These are conditions whose primary purpose is to increase security and/or increase exploit engineering complexity. A vulnerability exploitable without a target-specific variable has a lower complexity than a vulnerability that would require non-trivial customization. This metric is meant to capture security mechanisms utilized by the vulnerable system.
Attack Requirements: This metric captures the prerequisite deployment and execution conditions or variables of the vulnerable system that enable the attack. These differ from security-enhancing techniques/technologies (ref Attack Complexity) as the primary purpose of these conditions is not to explicitly mitigate attacks, but rather, emerge naturally as a consequence of the deployment and execution of the vulnerable system.
Privileges Required: This metric describes the level of privileges an attacker must possess prior to successfully exploiting the vulnerability. The method by which the attacker obtains privileged credentials prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, self-service provisioned accounts do not constitute a privilege requirement if the attacker can grant themselves privileges as part of the attack.
User interaction: This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable system. This metric determines whether the vulnerability can be exploited solely at the will of the attacker, or whether a separate user (or user-initiated process) must participate in some manner.
Vulnerable System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the VULNERABLE SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the VULNERABLE SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the VULNERABLE SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
Subsequent System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the SUBSEQUENT SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the SUBSEQUENT SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the SUBSEQUENT SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
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

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(17th percentile)

Weaknesses

NULL Pointer Dereference

The product dereferences a pointer that it expects to be valid but is NULL. Learn more on MITRE.

CVE ID

CVE-2026-29781

GHSA ID

GHSA-hx52-cv84-jr5v

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.