Bug 2218723

Summary: CIS Profile sshd hardening not accepting "MaxStartups 10" claiming that it requires "MaxStartups 10:30:60" or more restrictive
Product: Red Hat Enterprise Linux 8 Reporter: Juan Gamba <jgamba>
Component: scap-security-guideAssignee: Vojtech Polasek <vpolasek>
Status: NEW --- QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: high Docs Contact:
Priority: unspecified    
Version: ---CC: dbelyavs, ggasparb, mhaicman, mlysonek, peter.vreman, wsato
Target Milestone: rcKeywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Juan Gamba 2023-06-30 02:46:40 UTC
Description of problem:

CIS Profile sshd hardening not accepting "MaxStartups 10", claiming that it requires "MaxStartups 10:30:60" or more restrictive but "MaxStartups 10" is actually more restrictive, as it is the same a setting "MaxStartups 10:-1:10"

Version-Release number of selected component (if applicable):

scap-security-guide-0.1.66-2.el8_7.noarch

How reproducible:

always

Steps to Reproduce:
1. - Set 'MaxStartups 10' in  /etc/ssh/sshd_config
2. - Run CIS profile
3. - See xccdf_org.ssgproject.content_rule_sshd_set_maxstartups

Actual results:

[root@r88 ~]# oscap xccdf eval --report cis_report.html --profile cis --rule xccdf_org.ssgproject.content_rule_sshd_set_maxstartups --fetch-remote-resources /usr/share/xml/scap/ssg/content/ssg-rhel8-ds-1.2.xml
Downloading: https://access.redhat.com/security/data/oval/com.redhat.rhsa-RHEL8.xml.bz2 ... ok
--- Starting Evaluation ---

Title   Ensure SSH MaxStartups is configured
Rule    xccdf_org.ssgproject.content_rule_sshd_set_maxstartups
Ident   CCE-90718-8
Result  fail

Expected results:

[root@r88 ~]# oscap xccdf eval --report cis_report.html --profile cis --rule xccdf_org.ssgproject.content_rule_sshd_set_maxstartups --fetch-remote-resources /usr/share/xml/scap/ssg/content/ssg-rhel8-ds-1.2.xml
Downloading: https://access.redhat.com/security/data/oval/com.redhat.rhsa-RHEL8.xml.bz2 ... ok
--- Starting Evaluation ---

Title   Ensure SSH MaxStartups is configured
Rule    xccdf_org.ssgproject.content_rule_sshd_set_maxstartups
Ident   CCE-90718-8
Result  pass

Additional info:

openssh source code and behavior with only one value on MaxStartups setting,

[#/source/RHEL8/RHEL8.8/openssh/openssh-8.0p1-17/openssh-8.0p1#]

[servconf.c]

80:initialize_server_options(ServerOptions *options)
81-{
82-	memset(options, 0, sizeof(*options));
83-
84-	/* Portable-specific options */
85-	options->use_pam = -1;
86-
87-	/* Standard Options */
[..]
153-	options->max_startups_begin = -1;
154-	options->max_startups_rate = -1;
155-	options->max_startups = -1;
[..]

There MaxStartups is initialized with -1:-1:-1
From 'man 5 sshd_config',

     MaxStartups
             Specifies the maximum number of concurrent unau‐
             thenticated connections to the SSH daemon.  Addi‐
             tional connections will be dropped until authenti‐
             cation succeeds or the LoginGraceTime expires for a
             connection.  The default is 10:30:100.

             Alternatively, random early drop can be enabled by
             specifying the three colon separated values
             start:rate:full (e.g. "10:30:60").  sshd(8) will
             refuse connection attempts with a probability of
             rate/100 (30%) if there are currently start (10)
             unauthenticated connections.  The probability
             increases linearly and all connection attempts are
             refused if the number of unauthenticated connec‐
             tions reaches full (60).

Using,

#-------------
MaxStartups 10
#-------------

The config is then read and applied,

[servconf.c]
[..]
1212 int
1213 process_server_config_line(ServerOptions *options, char *line,
1214     const char *filename, int linenum, int *activep,
1215     struct connection_info *connectinfo)
1216 {
[..]
1266:        switch (opcode) {
[..]
1784:	case sMaxStartups:
1785-		arg = strdelim(&cp);
1786-		if (!arg || *arg == '\0')
1787-			fatal("%s line %d: Missing MaxStartups spec.",
1788-			    filename, linenum);
1789-		if ((n = sscanf(arg, "%d:%d:%d",
1790-		    &options->max_startups_begin,
1791-		    &options->max_startups_rate,
1792-		    &options->max_startups)) == 3) {
1793-			if (options->max_startups_begin >
1794-			    options->max_startups ||
1795-			    options->max_startups_rate > 100 ||
1796-			    options->max_startups_rate < 1)
1797-				fatal("%s line %d: Illegal MaxStartups spec.",
1798-				    filename, linenum);
1799-		} else if (n != 1)
1800-			fatal("%s line %d: Illegal MaxStartups spec.",
1801-			    filename, linenum);
1802-		else
1803-			options->max_startups = options->max_startups_begin;
1804-		break;

The value "10" is set into "options->max_startups_begin", and later on line 1803 this is also set on "options->max_startups".
The option "options->max_startups_rate" stays in "-1" from the initialized value.

By only setting one value in "MaxStartups" without the 'three colon separated values start:rate:full' the values will be same as setting "10:-1:10"

This means only 10 unauthenticated connections is the maximum number at any given time, which is in fact more restrictive than the default and the value from the cis security profile.

So evaluations fails with any single value set in this option even with values smaller than 10 connections.
If you populate the 'three colon separated values start:rate:full' the evaluation even fails if rate is configured from any value between -1 to 29

eg:
MaxStartups 10:-1:10

to

MaxStartups 10:29:10

Having only one value in MaxStartups is legit and more restrictive as the behavior is set to only have that maximum number of unauthenticated connections at any given time, in this case 10.

Juan Gamba

Comment 1 Dmitry Belyavskiy 2023-07-04 13:39:10 UTC
Uninitialized options are overwritten by some reasonable defaults (10 is really equal to 10:30:10).

I think that the oscap evaluation should be fixed.