From f9d8b83c2a2118746b9fe8bcca0e4aef38982688 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Mon, 4 Apr 2022 18:52:19 +0200 Subject: [PATCH] sshd: disable by default ssh-rsa host key algo Signed-off-by: Nicola Murino --- config/config.go | 2 ++ docs/full-configuration.md | 5 +++-- go.mod | 4 ++-- go.sum | 8 ++++---- sftpd/server.go | 34 +++++++++++++++++++++++++++++++++- sftpd/sftpd_test.go | 6 ++++++ sftpgo.json | 1 + windows-installer/README.txt | 2 +- 8 files changed, 52 insertions(+), 10 deletions(-) diff --git a/config/config.go b/config/config.go index bcf621c8..1df2262e 100644 --- a/config/config.go +++ b/config/config.go @@ -196,6 +196,7 @@ func Init() { Banner: defaultSFTPDBanner, HostKeys: []string{}, HostCertificates: []string{}, + HostKeyAlgorithms: []string{}, KexAlgorithms: []string{}, Ciphers: []string{}, MACs: []string{}, @@ -1541,6 +1542,7 @@ func setViperDefaults() { viper.SetDefault("sftpd.banner", globalConf.SFTPD.Banner) viper.SetDefault("sftpd.host_keys", globalConf.SFTPD.HostKeys) viper.SetDefault("sftpd.host_certificates", globalConf.SFTPD.HostCertificates) + viper.SetDefault("sftpd.host_key_algorithms", globalConf.SFTPD.HostKeyAlgorithms) viper.SetDefault("sftpd.kex_algorithms", globalConf.SFTPD.KexAlgorithms) viper.SetDefault("sftpd.ciphers", globalConf.SFTPD.Ciphers) viper.SetDefault("sftpd.macs", globalConf.SFTPD.MACs) diff --git a/docs/full-configuration.md b/docs/full-configuration.md index dcaf7bcd..b7c288b8 100644 --- a/docs/full-configuration.md +++ b/docs/full-configuration.md @@ -109,7 +109,8 @@ The configuration file contains the following sections: - `banner`, string. Identification string used by the server. Leave empty to use the default banner. Default `SFTPGo_`, for example `SSH-2.0-SFTPGo_0.9.5` - `host_keys`, list of strings. It contains the daemon's private host keys. Each host key can be defined as a path relative to the configuration directory or an absolute one. If empty, the daemon will search or try to generate `id_rsa`, `id_ecdsa` and `id_ed25519` keys inside the configuration directory. If you configure absolute paths to files named `id_rsa`, `id_ecdsa` and/or `id_ed25519` then SFTPGo will try to generate these keys using the default settings. - `host_certificates`, list of strings. Public host certificates. Each certificate can be defined as a path relative to the configuration directory or an absolute one. Certificate's public key must match a private host key otherwise it will be silently ignored. Default: empty. - - `kex_algorithms`, list of strings. Available KEX (Key Exchange) algorithms in preference order. Leave empty to use default values. The supported values are: `curve25519-sha256`, `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`, `diffie-hellman-group16-sha512`, `diffie-hellman-group18-sha512`, `diffie-hellman-group14-sha1`, `diffie-hellman-group1-sha1`. Default values: `curve25519-sha256`, `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`. Sha512 based KEXs are disabled by default because they are slow. + - `host_key_algorithms`, list of strings. Public key algorithms that the server will accept for host key authentication. The supported values are: `rsa-sha2-512-cert-v01@openssh.com`, `rsa-sha2-256-cert-v01@openssh.com`, `ssh-rsa-cert-v01@openssh.com`, `ssh-dss-cert-v01@openssh.com`, `ecdsa-sha2-nistp256-cert-v01@openssh.com`, `ecdsa-sha2-nistp384-cert-v01@openssh.com`, `ecdsa-sha2-nistp521-cert-v01@openssh.com`, `ssh-ed25519-cert-v01@openssh.com`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-rsa`, `ssh-dss`, `ssh-ed25519`. Default values: `rsa-sha2-512-cert-v01@openssh.com`, `rsa-sha2-256-cert-v01@openssh.com`, `ecdsa-sha2-nistp256-cert-v01@openssh.com`, `ecdsa-sha2-nistp384-cert-v01@openssh.com`, `ecdsa-sha2-nistp521-cert-v01@openssh.com`, `ssh-ed25519-cert-v01@openssh.com`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`, `rsa-sha2-512`, `rsa-sha2-256`, `ssh-ed25519`. + - `kex_algorithms`, list of strings. Available KEX (Key Exchange) algorithms in preference order. Leave empty to use default values. The supported values are: `curve25519-sha256`, `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`, `diffie-hellman-group16-sha512`, `diffie-hellman-group18-sha512`, `diffie-hellman-group14-sha1`, `diffie-hellman-group1-sha1`. Default values: `curve25519-sha256`, `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha256`. SHA512 based KEXs are disabled by default because they are slow. - `ciphers`, list of strings. Allowed ciphers in preference order. Leave empty to use default values. The supported values are: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`, `aes128-cbc`, `aes192-cbc`, `aes256-cbc`, `3des-cbc`, `arcfour256`, `arcfour128`, `arcfour`. Default values: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`, `aes128-ctr`, `aes192-ctr`, `aes256-ctr`. Please note that the ciphers disabled by default are insecure, you should expect that an active attacker can recover plaintext if you enable them. - `macs`, list of strings. Available MAC (message authentication code) algorithms in preference order. Leave empty to use default values. The supported values are: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`, `hmac-sha2-512-etm@openssh.com`, `hmac-sha2-512`, `hmac-sha1`, `hmac-sha1-96`. Default values: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-256`. - `trusted_user_ca_keys`, list of public keys paths of certificate authorities that are trusted to sign user certificates for authentication. The paths can be absolute or relative to the configuration directory. @@ -443,7 +444,7 @@ Supported hash algorithms: - MD5 crypt, prefix `$1$` - MD5 crypt APR1, prefix `$apr1$` - SHA512 crypt, prefix `$6$` -- LDAP md5, prefix `{MD5}` +- LDAP MD5, prefix `{MD5}` If you set a password with one of these prefixes it will not be hashed. When users log in, if their passwords are stored with anything other than the preferred algorithm, SFTPGo will automatically upgrade the algorithm to the preferred one. diff --git a/go.mod b/go.mod index 63a49706..9c5fb50a 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 golang.org/x/net v0.0.0-20220401154927-543a649e0bdd golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a - golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 + golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 google.golang.org/api v0.74.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 @@ -160,6 +160,6 @@ require ( replace ( github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 - golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20220403064943-e77ee20c52ed + golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20220404114519-57edd90b9b42 golang.org/x/net => github.com/drakkan/net v0.0.0-20220403065115-db06d28f9f8d ) diff --git a/go.sum b/go.sum index 3c8a2f4b..6bc45fd1 100644 --- a/go.sum +++ b/go.sum @@ -227,8 +227,8 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/ github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/drakkan/crypto v0.0.0-20220403064943-e77ee20c52ed h1:R2fY4T+bcDCLRpEIZO1TBAFYcbUOU8weMOWJZWLXlq4= -github.com/drakkan/crypto v0.0.0-20220403064943-e77ee20c52ed/go.mod h1:SiM6ypd8Xu1xldObYtbDztuUU7xUzMnUULfphXFZmro= +github.com/drakkan/crypto v0.0.0-20220404114519-57edd90b9b42 h1:zEfdtweSYZtEJqrUuezFPsfuvsSdNlbcpi3jlPUQqBc= +github.com/drakkan/crypto v0.0.0-20220404114519-57edd90b9b42/go.mod h1:SiM6ypd8Xu1xldObYtbDztuUU7xUzMnUULfphXFZmro= github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9 h1:LPH1dEblAOO/LoG7yHPMtBLXhQmjaga91/DDjWk9jWA= github.com/drakkan/ftp v0.0.0-20201114075148-9b9adce499a9/go.mod h1:2lmrmq866uF2tnje75wQHzmPXhmSWUt7Gyx2vgK1RCU= github.com/drakkan/net v0.0.0-20220403065115-db06d28f9f8d h1:pFFnOn4oQ+0Ewvn4/K41uW6troPfOwMeEHN7RBgIaA4= @@ -923,8 +923,8 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 h1:PgUUmg0gNMIPY2WafhL/oLyQGw+kdTNPlVWOjltpp3w= -golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb h1:PVGECzEo9Y3uOidtkHGdd347NjLtITfJFO9BxFpmRoo= +golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/sftpd/server.go b/sftpd/server.go index 1aae0964..8b2e2967 100644 --- a/sftpd/server.go +++ b/sftpd/server.go @@ -35,7 +35,24 @@ const ( ) var ( - sftpExtensions = []string{"statvfs@openssh.com"} + sftpExtensions = []string{"statvfs@openssh.com"} + supportedHostKeyAlgos = []string{ + ssh.CertAlgoRSASHA512v01, ssh.CertAlgoRSASHA256v01, + ssh.CertAlgoRSAv01, ssh.CertAlgoDSAv01, ssh.CertAlgoECDSA256v01, + ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01, ssh.CertAlgoED25519v01, + ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, + ssh.KeyAlgoRSASHA512, ssh.KeyAlgoRSASHA256, + ssh.KeyAlgoRSA, ssh.KeyAlgoDSA, + ssh.KeyAlgoED25519, + } + preferredHostKeyAlgos = []string{ + ssh.CertAlgoRSASHA512v01, ssh.CertAlgoRSASHA256v01, + ssh.CertAlgoECDSA256v01, + ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01, ssh.CertAlgoED25519v01, + ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, + ssh.KeyAlgoRSASHA512, ssh.KeyAlgoRSASHA256, + ssh.KeyAlgoED25519, + } supportedKexAlgos = []string{ "curve25519-sha256", "curve25519-sha256@libssh.org", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", @@ -106,6 +123,9 @@ type Configuration struct { // Each certificate can be defined as a path relative to the configuration directory or an absolute one. // Certificate's public key must match a private host key otherwise it will be silently ignored. HostCertificates []string `json:"host_certificates" mapstructure:"host_certificates"` + // HostKeyAlgorithms lists the public key algorithms that the server will accept for host + // key authentication. + HostKeyAlgorithms []string `json:"host_key_algorithms" mapstructure:"host_key_algorithms"` // KexAlgorithms specifies the available KEX (Key Exchange) algorithms in // preference order. KexAlgorithms []string `json:"kex_algorithms" mapstructure:"kex_algorithms"` @@ -340,6 +360,18 @@ func (c *Configuration) serve(listener net.Listener, serverConfig *ssh.ServerCon } func (c *Configuration) configureSecurityOptions(serverConfig *ssh.ServerConfig) error { + if len(c.HostKeyAlgorithms) == 0 { + c.HostKeyAlgorithms = preferredHostKeyAlgos + } else { + c.HostKeyAlgorithms = util.RemoveDuplicates(c.HostKeyAlgorithms) + } + for _, hostKeyAlgo := range c.HostKeyAlgorithms { + if !util.IsStringInSlice(hostKeyAlgo, supportedHostKeyAlgos) { + return fmt.Errorf("unsupported host key algorithm %#v", hostKeyAlgo) + } + } + serverConfig.HostKeyAlgorithms = c.HostKeyAlgorithms + if len(c.KexAlgorithms) > 0 { c.KexAlgorithms = util.RemoveDuplicates(c.KexAlgorithms) for _, kex := range c.KexAlgorithms { diff --git a/sftpd/sftpd_test.go b/sftpd/sftpd_test.go index 8e444d74..a123e1f4 100644 --- a/sftpd/sftpd_test.go +++ b/sftpd/sftpd_test.go @@ -396,6 +396,12 @@ func TestInitialization(t *testing.T) { if assert.Error(t, err) { assert.Contains(t, err.Error(), "unsupported key-exchange algorithm") } + sftpdConf.HostKeyAlgorithms = []string{"not a host key algo"} + err = sftpdConf.Initialize(configDir) + if assert.Error(t, err) { + assert.Contains(t, err.Error(), "unsupported host key algorithm") + } + sftpdConf.HostKeyAlgorithms = nil sftpdConf.HostCertificates = []string{"missing file"} err = sftpdConf.Initialize(configDir) if assert.Error(t, err) { diff --git a/sftpgo.json b/sftpgo.json index 1a4a9901..81eb6ae0 100644 --- a/sftpgo.json +++ b/sftpgo.json @@ -64,6 +64,7 @@ "banner": "", "host_keys": [], "host_certificates": [], + "host_key_algorithms": [], "kex_algorithms": [], "ciphers": [], "macs": [], diff --git a/windows-installer/README.txt b/windows-installer/README.txt index 466fc230..ebc7ee93 100644 --- a/windows-installer/README.txt +++ b/windows-installer/README.txt @@ -1,4 +1,4 @@ -SFTPGo allows to securely share your files over SFTP, HTTP and optionally FTP/S and WebDAV as well. +SFTPGo allows you to securely share your files over SFTP and optionally over HTTP/S, FTP/S and WebDAV as well. Several storage backends are supported: local filesystem, encrypted local filesystem, S3 (compatible) Object Storage, Google Cloud Storage, Azure Blob Storage, other SFTP servers.