Skip to content

Fix integer overflow in parseString bounds check - #262

Open
arpitjain099 wants to merge 1 commit into
gliderlabs:masterfrom
arpitjain099:chore/fix-parsestring-overflow
Open

Fix integer overflow in parseString bounds check#262
arpitjain099 wants to merge 1 commit into
gliderlabs:masterfrom
arpitjain099:chore/fix-parsestring-overflow

Conversation

@arpitjain099

Copy link
Copy Markdown

I do supply-chain security research and found this while auditing SSH server parsers.

parseString reads a uint32 length prefix and then guards with uint32(len(in)) < 4+length. The 4+length is evaluated in uint32, so a length close to the max wraps around. With length = 0xFFFFFFFF, 4+length becomes 3, the check passes for any buffer of four or more bytes, and execution reaches in[4 : 4+length] which is in[4:3] and panics with a slice-bounds error.

You can hit this with a malformed pty-req: parsePtyRequest feeds the term field straight into parseString. There is no recover() in the package and DefaultSessionHandler runs in its own goroutine, so the panic brings the whole process down rather than just failing the one connection. When a server sets neither a PublicKeyHandler nor a PasswordHandler, NoClientAuth is enabled, so on those setups an unauthenticated client can trigger it.

The fix advances past the length prefix first and then compares len(in) against length directly, which is the same shape golang.org/x/crypto/ssh uses and avoids the addition entirely. Valid inputs parse exactly as before.

Added util_test.go: a normal round-trip case, the 0xFFFFFFFF length case, and a malformed pty-req. The oversized cases panic on master and pass with this change; go test ./... is green after the fix.

parseString read a uint32 length prefix and then checked len(in) against
4+length. That addition is done in uint32, so a length near the maximum
wraps: with length 0xFFFFFFFF, 4+length becomes 3, the guard passes for
any buffer of 4+ bytes, and the code slices in[4:4+length] = in[4:3],
which panics with a slice-bounds error.

This is reachable through a malformed pty-req (parsePtyRequest calls
parseString on the term field). There is no recover() in the package and
the session handler runs in its own goroutine, so the panic takes down
the whole process. On servers with no PublicKeyHandler or PasswordHandler
set, gliderlabs enables NoClientAuth, so this is unauthenticated there.

Advance past the length prefix before the bounds check and compare
len(in) against length directly, matching the shape used in
golang.org/x/crypto/ssh. Valid parsing is unchanged.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
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.

1 participant