Skip to content

Commit e79546e

Browse files
thatnealpatelgopherbot
authored andcommitted
ssh: curb GSSAPI DoS risk by limiting number of specified OIDs
Previously, an attacker could specify an integer up to 0xFFFFFFFF that would directly allocate memory despite the observability of the rest of the payload. This change places a hard cap on the amount of mechanisms that can be specified and encoded in the payload. Additionally, it performs a small sanity check to deny payloads whose stated size is contradictory to the observed payload. Thank you to Jakub Ciolek for reporting this issue. Fixes CVE-2025-58181 Fixes golang/go#76363 Change-Id: I0307ab3e906a3f2ae763b5f9f0310f7073f84485 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/721961 Auto-Submit: Roland Shoemaker <[email protected]> Reviewed-by: Damien Neil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent f91f7a7 commit e79546e

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

ssh/ssh_gss.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
106106
if !ok {
107107
return nil, errors.New("parse uint32 failed")
108108
}
109+
// Each ASN.1 encoded OID must have a minimum
110+
// of 2 bytes; 64 maximum mechanisms is an
111+
// arbitrary, but reasonable ceiling.
112+
const maxMechs = 64
113+
if n > maxMechs || int(n)*2 > len(rest) {
114+
return nil, errors.New("invalid mechanism count")
115+
}
109116
s := &userAuthRequestGSSAPI{
110117
N: n,
111118
OIDS: make([]asn1.ObjectIdentifier, n),
@@ -122,7 +129,6 @@ func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
122129
if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil {
123130
return nil, err
124131
}
125-
126132
}
127133
return s, nil
128134
}

ssh/ssh_gss_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,37 @@ func TestParseGSSAPIPayload(t *testing.T) {
1717
}
1818
}
1919

20+
func TestParseDubiousGSSAPIPayload(t *testing.T) {
21+
for _, tc := range []struct {
22+
name string
23+
payload []byte
24+
wanterr bool
25+
}{
26+
{
27+
"num mechanisms is unrealistic",
28+
[]byte{0xFF, 0x00, 0x00, 0xFF,
29+
0x00, 0x00, 0x00, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02},
30+
true,
31+
},
32+
{
33+
"num mechanisms greater than payload",
34+
[]byte{0x00, 0x00, 0x00, 0x40, // 64, |rest| too small
35+
0x00, 0x00, 0x00, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02},
36+
true,
37+
},
38+
} {
39+
t.Run(tc.name, func(t *testing.T) {
40+
_, err := parseGSSAPIPayload(tc.payload)
41+
if tc.wanterr && err == nil {
42+
t.Errorf("got nil, want error")
43+
}
44+
if !tc.wanterr && err != nil {
45+
t.Errorf("got %v, want nil", err)
46+
}
47+
})
48+
}
49+
}
50+
2051
func TestBuildMIC(t *testing.T) {
2152
sessionID := []byte{134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53,
2253
183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121}

0 commit comments

Comments
 (0)