VDB
Sign up
HIGH7.5

GHSA-4595-rvpx-4q34

emp3r0r has an unauthenticated HTTP Polling DoS

Quick fix

GHSA-4595-rvpx-4q34 — github.com/jm33-m0/emp3r0r/core: upgrade to the fixed version with the command below.

go get github.com/jm33-m0/emp3r0r/core@v0.0.0-20260531142011-aed3d81641ab

Details

### Summary The `http_poll` C2 transport accepts attacker-controlled HTTP polling sessions before CBOR `MsgAuth` authentication is completed. A remote unauthenticated attacker can create arbitrary polling sessions and send request bodies that are forwarded into the C2 dispatch path. This can consume server resources and trigger pre-auth C2 processing.

### Details The plain HTTP C2 server starts the HTTP polling listener and forwards requests into `HandleHTTPServerSession`: ```go // core/internal/cc/server/c2_http_server.go mux.HandleFunc(c2Path, func(w http.ResponseWriter, req *http.Request) { stream, err := transport.HandleHTTPServerSession(w, req, &live.RuntimeConfig.MalleableC2) ... if stream != nil { go cborStreamAccept(transport.NewStreamTransport(stream, req.RemoteAddr)) } }) ``` The HTTP polling handler accepts an attacker-supplied `sessionID` and `init=1` cookie, then creates and stores a server-side stream before authentication:

```go // core/internal/transport/c2channel_http.go if isInit { stream = newHTTPServerStream(sessionID) w.WriteHeader(http.StatusOK) return stream, nil } ``` POST bodies for that unauthenticated session are read and queued before CBOR authentication rejects them: ```go // core/internal/transport/c2channel_http.go case http.MethodPost: data, err := io.ReadAll(req.Body) if err == nil && len(data) > 0 { select { case stream.readCh <- data: w.WriteHeader(http.StatusOK) ... } } ``` Authentication only happens later in the C2 dispatch layer: ```go // core/internal/cc/server/dispatcher.go secureConn := transport.NewSecureConn(t) ... n, err := secureConn.Read(authFrame) ```

### PoC 1. Start the C2 server in a lab environment with the HTTP polling transport exposed, for example with `--http-port 12345`. 2. Send an unauthenticated HTTP POST to the default polling path `/api/v1/telemetry` with a random `sessionID` cookie and the `init=1` cookie value. 3. Send a second unauthenticated HTTP POST to `/api/v1/telemetry` using the same `sessionID`, with a request body containing repeated `A` bytes. 4. Observe that both unauthenticated requests return HTTP `200`. 5. Observe the C2 server log showing attacker-controlled bytes reaching the encrypted C2 frame parser, for example: `read: invalid encrypted chunk length: 1094795585`. 6. `1094795585` is `0x41414141`, which corresponds to `AAAA`, confirming unauthenticated request body data reached `cborProtocolDispatch` before CBOR `MsgAuth` authentication. 7. Repeat the request sequence concurrently to increase server resource usage and log volume.

### Impact - Remote unauthenticated attackers can create arbitrary HTTP polling sessions. - Attacker-controlled request bodies reach pre-auth C2 dispatch handling. - Repeated requests can consume server memory, goroutines, request handling capacity, and log volume. - C2 service availability and operator reliability may be degraded under sustained traffic.

### Remediation - Require authentication before creating long-lived HTTP polling sessions. - Do not forward request bodies into the C2 stream before validation. - Add strict request body limits.

Are you affected?

Enter the version of the package you're using.

Affected packages

Go/github.com/jm33-m0/emp3r0r/core
Introduced in: 0Fixed in: 0.0.0-20260531142011-aed3d81641ab
Fixgo get github.com/jm33-m0/emp3r0r/core@v0.0.0-20260531142011-aed3d81641ab

References