Skip to content

fix(implant): bound pivot frame allocation from length prefix - #2292

Merged
moloch-- merged 2 commits into
BishopFox:masterfrom
Luppa90:fix/pivot-frame-bounds
Jul 30, 2026
Merged

fix(implant): bound pivot frame allocation from length prefix#2292
moloch-- merged 2 commits into
BishopFox:masterfrom
Luppa90:fix/pivot-frame-bounds

Conversation

@Luppa90

@Luppa90 Luppa90 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Problem

Both pivot readers — NetConnPivot.read() (implant/sliver/pivots/pivots.go) and NetConnPivotClient.read() (implant/sliver/transports/pivotclients/pivotclient.go) — read a 4-byte little-endian length prefix and then make([]byte, dataLength) with only a lower-bound (<= 0) check. A corrupted or desynced prefix (e.g. a framing desync during a transfer over a pivot) is therefore read as a value up to ~4 GiB and triggers an allocation large enough to crash the implant.

This matches the failure mode reported in #1452 ("Downloading 300KiB file over http->named pipe pivot breaks implant and fails") — the tiny payload rules out a legitimately-large frame, pointing at an oversized/garbage declared length.

Change

  • Add MaxFrameLength (512 MiB) and reject frames whose declared length exceeds it with a new ErrFrameTooLarge, before allocating.
  • The constant/error are defined once in the pivots package and reused by pivotclients (which already imports it).
  • 512 MiB is far above any realistic relayed message but well below the point where the allocation itself is fatal — tight enough to catch a garbage length that reads as ~1 GiB (which a 2 GiB-style cap would miss), generous enough never to reject a real frame.

Testing

  • New tests in both packages: an oversized length prefix is rejected with ErrFrameTooLarge (with a timeout guard so a regression fails fast instead of hanging), and a valid frame still round-trips unchanged.
  • go test ./implant/sliver/pivots/... ./implant/sliver/transports/pivotclients/... pass; go vet and gofmt clean.

Note / possible follow-up

The identical unbounded make([]byte, dataLength) pattern also exists in the implant's mTLS (mtls.go) and WireGuard (wireguard.go) readers. I kept this PR scoped to the pivot path (the one #1452 is about) to keep it small, but I'm happy to extend the same bound to those readers here or in a follow-up — whichever you prefer.

Both pivot readers (NetConnPivot and NetConnPivotClient) allocated
make([]byte, dataLength) directly from a peer's 4-byte length prefix with only
a lower-bound (<= 0) check. A corrupted or desynced prefix -- e.g. from a
framing desync during a transfer over a pivot -- can therefore be read as a
value up to ~4GiB and trigger an allocation large enough to crash the implant
(reported in BishopFox#1452 with a 300KiB download over an http -> named-pipe pivot).

Add an upper bound (MaxFrameLength, 512MiB) and reject oversized frames with
ErrFrameTooLarge before allocating. The constant and error live in the pivots
package and are reused by pivotclients, which already imports it.

Adds tests covering rejection of an oversized prefix (with a timeout guard so a
regression fails fast instead of hanging) and a valid-frame round-trip.
@Luppa90
Luppa90 requested a review from a team as a code owner July 18, 2026 16:33
@Luppa90
Luppa90 requested a review from zkvL July 18, 2026 16:33
@moloch--
moloch-- merged commit 19e8206 into BishopFox:master Jul 30, 2026
9 checks passed
moloch-- pushed a commit that referenced this pull request Aug 5, 2026
…h prefix

Same vulnerability fixed for pivots in #2292: a corrupted or desynced
4-byte length prefix could trigger an allocation up to ~4 GiB, crashing
the implant. Cap at 512 MiB (matching the pivot transport limit) and
return a descriptive error instead of allocating.

Also fixes stale "[pivot]" log tags in both transports' zero-length
error paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants