proftpd
proftpd copied to clipboard
mod_sftp: diffie-hellman-group-exchange-sha256 fixed at 1024 bit
proftpd:
(kex) diffie-hellman-group-exchange-sha256 (1024-bit)
(kex) diffie-hellman-group-exchange-sha1 (1024-bit)
(key) rsa-sha2-512 (3072-bit)
(key) rsa-sha2-256 (3072-bit)
CerberusFTPServer_11.0 FIPS
(kex) diffie-hellman-group-exchange-sha256
(kex) diffie-hellman-group-exchange-sha1 (2048-bit)
(key) ssh-rsa (2048-bit)
CerberusFTPServer_12.0 FIPS
(kex) diffie-hellman-group-exchange-sha256 (2048-bit)
(kex) diffie-hellman-group-exchange-sha1 (2048-bit)
(key) rsa-sha2-256 (2048-bit)
(key) rsa-sha2-512 (2048-bit)
SFTP Server 2020 - www.nsoftware.com
(kex) diffie-hellman-group-exchange-sha256 (1024-bit)
(kex) diffie-hellman-group-exchange-sha1 (1024-bit)
(key) ssh-rsa (2048-bit)
1.82_sshlib GlobalSCAPE
(kex) diffie-hellman-group-exchange-sha256 (1024-bit)
(kex) diffie-hellman-group-exchange-sha1 (1024-bit)
(key) ssh-rsa (2048-bit)
1.36_sshlib GlobalSCAPE
(kex) diffie-hellman-group-exchange-sha256 (1024-bit)
(kex) diffie-hellman-group-exchange-sha1 (1024-bit)
(key) ssh-rsa (2048-bit)
7.15 FlowSsh: Bitvise SSH Server (WinSSHD) 7.15
(kex) diffie-hellman-group-exchange-sha256 (1024-bit)
(kex) diffie-hellman-group-exchange-sha1 (1024-bit)
(key) rsa-sha2-512 (3072-bit)
(key) rsa-sha2-256 (3072-bit)
GoAnywhere6.7.1
(kex) diffie-hellman-group-exchange-sha1 (1024-bit)
(kex) diffie-hellman-group-exchange-sha256 (1024-bit)
(key) rsa-sha2-512 (2048-bit)
(key) rsa-sha2-256 (2048-bit)
One day later after hardening
(kex) diffie-hellman-group-exchange-sha256 (4096-bit)
(key) rsa-sha2-512 (2048-bit)
(key) rsa-sha2-256 (2048-bit)
SFTP Server
(kex) diffie-hellman-group-exchange-sha256 (2048-bit)
(kex) diffie-hellman-group-exchange-sha1 (2048-bit)
(key) rsa-sha2-256 (2048-bit)
(key) rsa-sha2-512 (2048-bit)
OpenSSH_9.0
(kex) diffie-hellman-group-exchange-sha256 (2048-bit)
(kex) diffie-hellman-group-exchange-sha1 (2048-bit) (not available by default, added manually)
(key) rsa-sha2-512 (3072-bit)
(key) rsa-sha2-256 (3072-bit)
Can proftpd bits be raised for these kex algos? How did GoAnywhere6 start with 1024 then harden to 4096? That's better than diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 and well supported. Seems like the server can arbitrarily choose the MODP. Maybe it should be adjustable in case there are clients with fixed limits, to be added later when we find clients with fixed limits.
group-exchange is a secure algo if we can get the bits up.
Edit
Found it in SFTPDHParamFile. 2048 works. I'm trying to get it up to 3072 or 4096.
The help needs to be updated with the new params.
# man openssl
dhparam
Generation and Management of Diffie-Hellman Parameters. Superseded by genpkey(1) and pkeyparam(1).
The help needs to be updated with the new params.
It's one of the "fun" parts of documenting someone else's (OpenSSL's) interfaces -- they can and will change (across versions) underneath you. For this, I may just link to OpenSSL's docs, and let readers sort out the versioning differences.
2048 is the highest it goes.
This is really wierd. With SFTPDHParamFile not present you get 1024. With it present and garbage like SFTPDHParamFile /dev/null you get 2048. For SFTPDHParamFile /etc/dhparams.pem you always get 2048. Adding and removing sizes seems to have no effect.
The format is different than ssh moduli. Is the code compatible with the moduli format?
And no, group exchange is not better than the other groups. It's a coloring bug in sshaudit.
diffie-hellman-group-exchange-sha256 adjustable group14 2048 group15 3072 group16 4096 group17 6144 group18 8192
Edit: found it. It's a permissions problem. /etc/proftpd is not readable by the suid down process. That's why it's placed in /etc.
WARNING: unable to read SFTPDHParamFile '/etc/proftpd/dhparams3072.pem': Permission denied
There are clients limited to 1024.
unable to find suitable DH in SFTPDHParamFile '/dev/null' for 1024-8192 bit sizes
unable to find suitable DH in SFTPDHParamFile '/dev/null' for 1024-1024 bit sizes
gex is garbage. Adjustable is it's downfall. Of course there would be clients that only support the lowest possible value. Having to include the lowest possible value means the rest can choose it.
Ok, the only real feature request is to log the bits chosen after any of the adjustable gex kex entries--or somewhere nearby, so I know which clients are garbage and when I can raise the minimum value.
Session key exchange: diffie-hellman-group-exchange-sha256 (4096)
Session key exchange: diffie-hellman-group-exchange-sha1 (1024)
Another approach might be to implement yet another SFTPClientMatch key, one that allows specifying the minimum allowed DH size, based on the client banner. Having per-client SFTPDHParamFile settings might be another approach...
That could work. Also log both the chosen bits and the client range so I know if they support recommended sizes but are intentionally choosing below. There's a problem if an up to date client does this:
Session key exchange: diffie-hellman-group-exchange-sha256 (1024-bit range 1024-8192)
sshaudit will do that since it's trying to scam me with the lowest possible value.
It's barely worth fooling with adding DH size to SFTPClientMatch. diffie-hellman-group-exchange-sha256 is a deprecated algorithm anyways and as far as I'm concerned the entire RSA suite needs to be deprecated. Since I can't raise the minimum gex to 3072 I can only offer it per SFTPClientMatch and the problem is already solved.
If I find that clients are doing as shown above, intentionally picking 1024 when they could be picking 4096, you can add DH size support. The Bitvise sftp client has a ssh gex box with 4096 as the default.
Fair enough. I appreciate you doing this research! I'll probably still add a little logging around, per your suggestion, for future work in this area.
I suppose we could make the DH group selection slightly better by choosing from the "larger than preferred size" DH group list first (see here), then choosing from the "preferred size" list. Given this language in RFC 4419, Section 3:
The server should return the smallest group it knows that is larger than the size the client requested. If the server does not know a group that is larger than the client request, then it SHOULD return the largest group it knows
then perhaps this change of behavior, of using the "larger than preferred DH size" list first might need to be tunable via SFTPOption/SFTPClientMatch.
Fair enough. I appreciate you doing this research! I'll probably still add a little logging around, per your suggestion, for future work in this area.
Note that there is logging of the client-sent min/preferred/max DH sizes, and the selected DH size, using trace logging (e.g. Trace ssh2:20) from here; the generated trace logging would look like:
<ssh2:20> client requested min 1024, pref 4096, max 8192 sizes for DH group exchange, selected DH of 4096 bits
I made a quick patch to show the min max values.
JSCH-0.1.50,JSCH-0.1.51
+ Session original client DHgex group exchange min 1024, pref 1024, max 1024
+ Session effective client DHgex group exchange min 1024, pref 2048, max 1024, selected 1024 bits
WS_FTP-12.4-0,WinSCP_release_5.1.4
+ Session original client DHgex group exchange min 1024, pref 2048, max 8192
+ Session effective client DHgex group exchange min 1024, pref 2048, max 8192, selected 2048 bits
SecureBlackbox,FTPGetter3
+ Session original client DHgex group exchange min 1024, pref 1024, max 8192
+ Session effective client DHgex group exchange min 1024, pref 2048, max 8192, selected 2048 bits
9.18 FlowSsh: Bitvise SSH Client (Tunnelier) 9.18 - BvSsh (DH gex min bits @ 2047)
+ Session original client DHgex group exchange min 2047, pref 3072, max 4096
+ Session effective client DHgex group exchange min 2047, pref 3072, max 4096, selected 3072 bits
sftp -o KexAlgorithms=diffie-hellman-group-exchange-sha256 -P 2224 0.0.0.6
OpenSSH_7.4,OpenSSH_for_Windows_8.1,OpenSSH_9.0
+ Session original client DHgex group exchange min 2048, pref 8192, max 8192
+ Session effective client DHgex group exchange min 2048, pref 8192, max 8192, selected 8192 bits
dropbear_2022.82 (kex group exchange not supported)
Seeing this I made a patch for kex.c based on the code below it to test the server's ability to choose.
--- kex.c.orig 2022-05-19 14:11:54.260181019 -0400
+++ kex.c 2022-05-19 14:14:57.498752504 -0400
@@ -3212,8 +3212,6 @@
dhparam_path = c->argv[0];
}
- if (pref<4096) pref=4096;
-
/* If the preferred DH is less than SFTP_DH_MIN_LEN, AND the AllowWeakDH
* SFTPOption is not used, then use a pref of SFTP_DH_MIN_LEN (Bug#4184).
*/
This doesn't fix the low score with sshaudit which performs successive login attempts through the min-max sequence 512-512,768-768,1024-1024,... to find the weakest DH gex I'll accept. While SFTPClientMatch SFTPDHGexMin (see below) could fix this, it isn't necessary right now. Not offering these old well supported algorithms to everyone has reduced my hack attempts to almost zero. I'd rather upgrade the clients so I don't need to offer them at all.
This does fix the problem with honest but poorly configured clients which is what I care about.
JSCH-0.1.50,JSCH-0.1.51
+ Session original client DHgex group exchange min 1024, pref 1024, max 1024
+ Session effective client DHgex group exchange min 1024, pref 4096, max 1024, selected 1024 bits
WS_FTP-12.4-0,WinSCP_release_5.1.4
+ Session original client DHgex group exchange min 1024, pref 2048, max 8192
+ Session effective client DHgex group exchange min 1024, pref 4096, max 8192, selected 4096 bits
What appears to be a JSCH bug claiming a pref higher than max is a bug in the code just below this patch, and my patch too. The client pref should not be set above the client max no matter what SFTP_DH_MIN_LEN or any of the other values are. The client pref shouldn't be changed at all. The log lines do not accurately reflect the client preference. The section should be reworked with "effective" client values with corrections and adjustments. The log line should show the original and effective client values, the server values and where the server pref comes from.
The server gets to choose the size so the solution is easy and will let me harden as much as necessary, including like was done with Cerberus. The server has a min,pref,max just like the client. The function is similar to SFTPKeyLimits so I’ll write it in the form of a help section from that. Some things are baloney that you should edit out.
SFTPDHGexMin
Syntax: SFTPDHGexMin bits
Default: 0
Context: server config, <VirtualHost>, <Global>
Module: mod_sftp
Compatibility: ???? and later
The SFTPDHGexMin directive is used to configure the enforced minimum MODP size for kex diffie-hellman-group-exchange. This may be necessary for the server to pass compliance requirements. Clients are immediately disconnected if they do not support at least this minimum size.
The values are expressed in standard MODP bit sizes. Supported values are 0, -512, -768, 1024, 1536, 2048, 3072, 4096, 6144, 7688, 8192 or as found in SFTPDHParamFile. 1024 can be considered the default because it is usually the smallest modulus in the SFTPDHParamFile. Positive values are always raised to a minimum standard set at compile time which may be increased in future versions. Negative values can be used to force the value below the minimum standard if moduli are available. Negative values are unsafe and should only be used for non public test and research servers. Negative values below the standard will emit a log warning on every sever start.
SFTPDHGexMin can be less than the available moduli in SFTPDHParamFile. The effective SFTPDHGexMin is raised to the smallest modulus in SFTPDHParamFile. Removing all of small sized moduli from the SFTPDHParamFile has the same effect as raising SFTPDHGexMin.
Moduli present in SFTPDHParamFile less than SFTPDHGexMin will not be used. It is not necesssary to delete them. Some distro packages do not preserve edits to SFTPDHParamFile so the file at the default install location should not be changed.
There is no SFTPDHGexMax setting. The effective server max is set by the largest modulus in SFTPDHParamFile, typically 8192.
Example:
# Disconnect clients that don’t support at least 3072-bit diffie-hellman-group-exchange MODP. Server and clients can prefer larger values if they wish.
SFTPDHGexMin 3072
SFTPDHGexPref
Syntax: SFTPDHGexPref bits
Default: 0
Context: server config, <VirtualHost>, <Global>
Module: mod_sftp
Compatibility: ???? and later
See SFTPDHGexMin for possible values. A value of 0 specifies that the server preference is set to the compile time constant SFTP_DH_MIN_LEN which may be increased in future versions. When not 0, SFTPDHGexPref must be greater or equal to SFTPDHGexMin and greater or equal to the smallest modulus in SFTPDHParamFile or the server will not start. A SFTPDHGexPref larger than largest modulus in SFTPDHParamFile will be adjusted down.
The SFTPDHGexPref directive is used to configure the server preferred MODP size for kex diffie-hellman-group-exchange. This is used to improve security to current standards with clients configured to legacy standards without cutting off legacy clients that don’t support current standards. See SFTPDHGexMin if a minimum standard must be enforced.
Clients have a minimum, preferred, and maximum. The server will start with the largest between client preferred and server preferred, adjusting up or down to the largest possible value between server min (SFTPDHGexMin) or client min and server max or client max.
Example:
# The server will select a MODP as close to 4096 as the client and server support. Clients can prefer larger values if they wish.
SFTPDHGexPref 4096
@severach FYI, the values used in JSch can be changed starting with our 0.1.65 release using the jsch.dhgex_min, jsch.dhgex_max & jsch. dhgex_preferred properties, or using:
JSch.setConfig("dhgex_min", "...");
JSch.setConfig("dhgex_max", "...");
JSch.setConfig("dhgex_preferred", "...");
Unfortunately I get minimal control of the clients, and no control of the Mirth clients using jsch. If it were up to me they'd all be running jsch 0.2.1 and support the good stuff, no need for gex. I'm trying to get server side control of whatever I can.
For whatever reason MirthConnect keeps releasing version after version and doesn't upgrade the positively ancient jsch 0.1.54.
Rather than having multiple new directives for setting server-side policy for DH group sizes, what if we have just one, that looks something like this:
SFTPDHGroupLimits min pref max
Where the default values (in bits) are:
min(2048, same as currentSFTP_DH_PREF_MIN_LENcompile-time constant)pref(0, meaning to use whatever the client sends; if set, the larger of client and server prefs is used -- or perhaps the server-side pref should always be used?)max(0, meaning largest group in configuredSFTPDHParamFile)
And obviously this would also be settable via e.g. SFTPClientMatch sftpDHGroupLimits.
The key realization here, for me, is this: while the range of DH groups can be effectively controlled via custom SFTPDHParamFile generation, this is non-obvious and indirect. More direct and obvious would be reusing the same SFTPDHParamFile and its groups, but being able to tune the min/max/range of groups selected from that file, on a per-client basis.
How does that sound?
A single option is fine. More like SFTPDHGroupLimits min pref [max]. Make it clear that it's rare that anyone would want to reduce the max.
SFTP_DH_MIN_LEN is the server pref, not the min so the default 2048 goes to the pref. The min would default 0 as the smallest group in SFTPDHParamFile, typically 1024. A min of 2048 would cut my JSCH-0.1.51 clients off.
The min max range can be controlled with SFTPDHParamFile but the pref can't. The SFTP_DH_MIN_LEN already functions as the server pref. I can raise it with a patch. The pref is important enough that it needs a config item to advertise it, and min and max can tag along.
That doesn't mean that we get rid of SFTP_DH_MIN_LEN. Raising SFTP_DH_MIN_LEN seems like a transparent change. Security goes up and noone gets cut off. A default pref of 0 would function more like it is now where the SFTP_DH_MIN_LEN determines the server pref, which may be increased in future versions. Positive values would automatically raise with SFTP_DH_MIN_LEN so SFTPDHGroupLimits 0 1024 0 would raise to 0 2048 0.
The value in SFTPClientMatch sftpDHGroupLimits is the ability to raise the minimum. Per client pref is inconsequential. The faster the computer, the higher the pref.
Excellent points. Hmm. In that case, maybe we just need:
# Set the server-side preferred DH group size, in bits
SFTPDHGroupPreferred 2048
and forego the min/max limits. Although, as you point out, there is value in having the ability to raise the minimum DH group size on a per-client basis, in which case, maybe we could also do with:
# Set a per-client minimum DH group size, in bits
SFTPClientMatch sftpDHGroupMin 2048
And maybe we only allow setting the minimum via SFTPClientMatch...
What I'd like to do is raise the server minimum and set the preferred across the board.
SFTPDHGroupLimits 3072 4096
SFTPDHGroupLimits 3072
Then drop the server min for select clients.
SFTPClientMatch "^JSCH.*" sftpDHGroupMin 1024
Rather than making another config name, you could use the same name where the preferred is optional.
SFTPClientMatch "^JSCH.*" sftpDHGroupLimits 1024,2048
SFTPClientMatch "^JSCH.*" sftpDHGroupLimits 1024