Bug 1309037

Summary: oscap remediation scripts for /etc/security/pwquality.conf have logic holes.
Product: Red Hat Enterprise Linux 7 Reporter: Chinmay Paradkar <cparadka>
Component: scap-security-guideAssignee: Jan Lieskovsky <jlieskov>
Status: CLOSED ERRATA QA Contact: Marek Haicman <mhaicman>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 7.3CC: mhaicman, mpreisle, openscap-maint
Target Milestone: rcKeywords: Reopened
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: scap-security-guide-0.1.30-1.el7 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-11-04 07:33:23 UTC 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 Chinmay Paradkar 2016-02-16 17:50:49 UTC
Description of problem:
The file /etc/security/pwquality.conf is not remediated as expected in all cases. The oscap implementation logic only works if something like the original default RHEL pwquality.conf file exists, not for any general file.

Version-Release number of selected component (if applicable):
scap-security-guide-0.1.25-3.el7

How reproducible:
Always

Steps to Reproduce:
On RHEL 7.x (any version) where /etc/security/pwquality.conf has been replaced. For example, if the file contains only the single line "dcredit = -1" and we specify in tailoring file that we want "ucredit = -1", remediation will fail. This is because all of the pwquality.conf remediation scripts handle the case where target variable is defined ("ucredit = 2") or where the target variable appears in a comment ("# ucredit = 1") but no test is made for if the variable does not appear at all -- in this case, the script logic falls through without doing anything, instead of appending to the file.

Additional info:
The easiest way to reproduce this is to get oscap to generate a fix script so we can more easily see what it's trying to do:

# d=`date +%m%d%H%M`
oscap xccdf generate fix \
--template urnccdf:fix:script:sh \
--profile stig-rhel7-server-upstream_hpes \
--tailoring-file ssg-rhel7-tailoring-hpe-v03.xml \
--output remediate.$d.sh \
ssg-rhel7-xccdf.xml \
|& tee makefix.$d.log

Let's pick on ucredit here but everything having to do with pwquality
has exactly the same problem. The generated code in the remediate.*.sh script
looks like this:

var_password_pam_ucredit="-1"
if egrep -q ^ucredit[[:space:]]*=[[:space:]]*[-]?[[igit:]]+
/etc/security/pwquality.conf; then
        sed -i "s/^\(ucredit *= *\).*/\1$var_password_pam_ucredit/"
/etc/security/pwquality.conf
else
        sed -i "/\(ucredit *= *\).*/a ucredit = $var_password_pam_ucredit"
/etc/security/pwquality.conf
fi

Following is what the above will do.

1. The desired setting of ucredit is -1
2. pwquality is checked to see if it contains an explicit setting for ucredit
3. If it does, the existing definition is completely replaced by the new
definition
4. If it does not, a new definition is added to the file

The problem is step 4. The actual logic above is "find a line mentioning
ucredit (with the expectation it is a comment), and then add the definition
immediately following that line."

Red Hat ships a default /etc/security/pwquality.conf that contains a boatload
of comments, including descriptions of all possible variables and their
default values. When run against this file, the remediation works as expected.
For example, the sequence of lines:

# The maximum credit for having uppercase characters in the new password.
# If less than 0 it is the minimum number of uppercase characters in the new
# password.
# ucredit = 1
#

is transformed into:

# The maximum credit for having uppercase characters in the new password.
# If less than 0 it is the minimum number of uppercase characters in the new
# password.
# ucredit = 1
ucredit = -1
#

The problem is that there is no requirement anywhere that pwquality.conf
contain any particular information. If for example, we completely replace
pwquality.conf with a new file containing only the single line:

minlen=12

Then the oscap remediation will fail. This occurs because there is no instance
of "ucredit" anywhere in the file, so step 4's sed pattern never matches and
the append command is never executed.

To address the situation, the remediation code should look like this:

var_password_pam_ucredit="-1"
if egrep -q ^ucredit[[:space:]]*=[[:space:]]*[-]?[[igit:]]+
/etc/security/pwquality.conf; then
        sed -i "s/^\(ucredit *= *\).*/\1$var_password_pam_ucredit/"
/etc/security/pwquality.conf
elif egrep -q ucredit[[:space:]]*=[[:space:]] /etc/security/pwquality.conf;
then
        sed -i "/\(ucredit *= *\).*/a ucredit = $var_password_pam_ucredit"
/etc/security/pwquality.conf
else
        echo "ucredit = $var_password_pam_ucredit" >>
/etc/security/pwquality.conf
fi

Here, the append is attempt is guarded by a check to ensure the target pattern
actually appears in the file. If it does not, the required directive is
appended to the file.

Comment 2 Jan Lieskovsky 2016-03-17 15:50:01 UTC
Reported upstream as:
  https://github.com/OpenSCAP/scap-security-guide/issues/1085

Comment 3 Jan Lieskovsky 2016-04-19 17:37:05 UTC
Specific upstream change correcting the problem:
  https://github.com/OpenSCAP/scap-security-guide/pull/1219

Comment 8 Marek Haicman 2016-07-07 14:54:01 UTC
Confirmed fix in version scap-security-guide-0.1.30-1.el7

Old version scap-security-guide-0.1.25-3.el7 threw error when tried to remediate empty file, fixed version works.

Common scenario [value is already present] passed as well.

Comment 10 errata-xmlrpc 2016-11-04 07:33:23 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2016-2483.html