Browse Source

ssh: make `env` command a passthrough (#7868)

## Describe the pull request

Fixes
https://github.com/gogs/gogs/security/advisories/GHSA-vm62-9jw3-c8w3
Joe Chen 4 tháng trước cách đây
mục cha
commit
009a1855aa
2 tập tin đã thay đổi với 8 bổ sung24 xóa
  1. 3 2
      internal/database/ssh_key.go
  2. 5 22
      internal/ssh/ssh.go

+ 3 - 2
internal/database/ssh_key.go

@@ -447,8 +447,9 @@ func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
 	return key, nil
 }
 
-// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
-// and returns public key found.
+// SearchPublicKeyByContent searches a public key using the content as prefix
+// (i.e. ignore the email part). It returns ErrKeyNotExist if no such key
+// exists.
 func SearchPublicKeyByContent(content string) (*PublicKey, error) {
 	key := new(PublicKey)
 	has, err := x.Where("content like ?", content+"%").Get(key)

+ 5 - 22
internal/ssh/ssh.go

@@ -6,7 +6,6 @@ package ssh
 
 import (
 	"context"
-	"fmt"
 	"io"
 	"net"
 	"os"
@@ -55,26 +54,8 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) {
 				payload := cleanCommand(string(req.Payload))
 				switch req.Type {
 				case "env":
-					var env struct {
-						Name  string
-						Value string
-					}
-					if err := ssh.Unmarshal(req.Payload, &env); err != nil {
-						log.Warn("SSH: Invalid env payload %q: %v", req.Payload, err)
-						continue
-					}
-					// Sometimes the client could send malformed command (i.e. missing "="),
-					// see https://discuss.gogs.io/t/ssh/3106.
-					if env.Name == "" || env.Value == "" {
-						log.Warn("SSH: Invalid env arguments: %+v", env)
-						continue
-					}
-
-					_, stderr, err := com.ExecCmd("env", fmt.Sprintf("%s=%s", env.Name, env.Value))
-					if err != nil {
-						log.Error("env: %v - %s", err, stderr)
-						return
-					}
+					// We only need to accept the request and do nothing since whatever environment
+					// variables being set here won't be used in subsequent commands anyway.
 
 				case "exec":
 					cmdName := strings.TrimLeft(payload, "'()")
@@ -175,7 +156,9 @@ func Listen(opts conf.SSHOpts, appDataPath string) {
 		PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
 			pkey, err := database.SearchPublicKeyByContent(strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key))))
 			if err != nil {
-				log.Error("SearchPublicKeyByContent: %v", err)
+				if !database.IsErrKeyNotExist(err) {
+					log.Error("SearchPublicKeyByContent: %v", err)
+				}
 				return nil, err
 			}
 			return &ssh.Permissions{Extensions: map[string]string{"key-id": com.ToStr(pkey.ID)}}, nil