golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
121.22k stars 17.37k forks source link

x/crypto/ssh: client fails to exchange versions with servers that present more than 255 bytes on connection #66716

Open hdm opened 3 months ago

hdm commented 3 months ago

Go version

go version go1.22.2 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/dev/Library/Caches/go-build'
GOENV='/Users/dev/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/dev/go/pkg/mod'
GOOS='darwin'
GOPATH='/Users/dev/go'
GOPROXY='direct'
GOROOT='/usr/local/go'
GOSUMDB='off'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.2'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/9x/745q85m113g3dk0wrrds984m0000gp/T/go-build4011179544=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

The x/crypto/ssh client fails to connect to servers that present more than 255 bytes before providing the complete SSH-2.0 version string. This is at odds with OpenSSH, which is more forgiving, and handles these servers today.

This limit is defined in ssh/transport.go:

// maxVersionStringBytes is the maximum number of bytes that we'll
// accept as a version string. RFC 4253 section 4.2 limits this at 255
// chars
const maxVersionStringBytes = 255

An example of a semi-common Dropbear configuration that triggers this issue:

% nc funky-dropbear-system 22

Will output 1024 bit rsa secret key to '/tmp/dropbear_rsa_host_key.1921'
Generating key, this may take a while...

Public key portion is:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCIMhjuaUs3uwh+c/eK73qeBQ09G450f/9bOlRB4nVoZPzJfxf2ss6wCddwdta0mamv+uJgUPjWXbE7XGzRRUshtLq3yy8y62XlPDSyP9KOnLNsUTioyGKMHYJJ1JG0plLPAbaotc7VE8ZZ8exv/8JaA8hQnixDBlIiOY9w89tMeQp/
Fingerprint: sha1 d7:aa:67:8d:7d:55:4e:13:d9:68:8e:4d:2a:88:b3:51:4d:87:42:ef

SSH-2.0-dropbear_2016.74

What did you see happen?

The SSH client fails to connect and returns a "version overflow" handshake error.

What did you expect to see?

A completed handshake without the overflow error.

A simple fix is to increase the number of bytes read in the version exchange:

const maxVersionStringBytes = 1024

cagedmantis commented 3 months ago

cc @drakkan @golang/security