ssh: prevent malformed exit-status panic
A malicious server can crash any client by sending a truncated exit-status payload, which triggers a panic in binary.BigEndian.Uint32. Change-Id: Iff4fe182b40210c99d46562f6c3b5ecf38bb98b4 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/780181 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Nicola Murino <nicola.murino@gmail.com> Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
@@ -423,6 +423,9 @@ func (s *Session) wait(reqs <-chan *Request) error {
|
||||
for msg := range reqs {
|
||||
switch msg.Type {
|
||||
case "exit-status":
|
||||
if len(msg.Payload) < 4 {
|
||||
return errors.New("ssh: malformed exit-status request")
|
||||
}
|
||||
wm.status = int(binary.BigEndian.Uint32(msg.Payload))
|
||||
case "exit-signal":
|
||||
var sigval struct {
|
||||
|
||||
@@ -334,6 +334,25 @@ func TestExitWithoutStatusOrSignal(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExitStatusShortPayload(t *testing.T) {
|
||||
for _, payload := range [][]byte{nil, {0}, {0, 0}, {0, 0, 0}} {
|
||||
conn := dial(exitStatusShortPayloadHandler(payload), t)
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to request new session: %v", err)
|
||||
}
|
||||
if err := session.Shell(); err != nil {
|
||||
t.Fatalf("unable to execute command: %v", err)
|
||||
}
|
||||
err = session.Wait()
|
||||
if err == nil {
|
||||
t.Fatalf("expected error for payload length %d", len(payload))
|
||||
}
|
||||
session.Close()
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// windowTestBytes is the number of bytes that we'll send to the SSH server.
|
||||
const windowTestBytes = 16000 * 200
|
||||
|
||||
@@ -482,6 +501,17 @@ func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) {
|
||||
readLine(shell, t)
|
||||
}
|
||||
|
||||
func exitStatusShortPayloadHandler(payload []byte) serverType {
|
||||
return func(ch Channel, in <-chan *Request, t *testing.T) {
|
||||
defer ch.Close()
|
||||
shell := newServerShell(ch, in, "> ")
|
||||
readLine(shell, t)
|
||||
if _, err := ch.SendRequest("exit-status", false, payload); err != nil {
|
||||
t.Errorf("unable to send status: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func shellHandler(ch Channel, in <-chan *Request, t *testing.T) {
|
||||
defer ch.Close()
|
||||
// this string is returned to stdout
|
||||
|
||||
Reference in New Issue
Block a user