Harden RHEL8 to Comply with PCI-DSS v3.2.1

John T. Mills
John T. Mills
Harden RHEL8 to Comply with PCI-DSS v3.2.1

Red Hat has integrated several SCAP profiles into the OS libraries. Using these and the utilities that support them, we are able to apply the PCI-DSS v3.2.1 security standard to our automated system builds. More information on automating RHEL installations can be found in Provision a Kickstart Server with RHEL8 - Part 1, Part 2, and Part 3. More information on OpenSCAP can be found at: https://www.open-scap.org/.

Harden the Build using %addon

  1. Open your kickstart configuration file for RHEL8. (sample)
    vi rhel8
    
  2. Add the %addon security profile before the %anaconda and %post sections.
    %addon org_fedora_oscap
        content-type = scap-security-guide
        profile = xccdf_org.ssgproject.content_profile_pci-dss
    %end
    
  3. Add a simple web server to the configuration to simplify the audit in later steps.
    1. If firewall --enable is set, extend it by changing it to, at least:
      firewall --enable --http
      
    2. Under %packages, add httpd.
      httpd
      
    3. Under %post, add a small configuration and enable the service.
      echo -e "<html>welcome to rhel8</html>" > /var/www/html/index.html
      systemctl enable httpd.service 
      
  4. Install a test VM with the updated kickstart configuration file.

Measure the Compliance Status

  1. Once the installation is complete, login to the test VM.
  2. Since our rhel8 pattern produces a simple web server, run the compliance check but send the output to the web directory.
    oscap xccdf eval --report /var/www/html/report-pci-dss.html --profile pci-dss /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml
    
  3. Browse to the HTML report on your test VM. It will be available at http://{Test VM IP}/report-pci-dss.html. In my case it looks like this: example image
  4. With the sample RHEL8 VM pattern, I am seeing three failures and one warning. example image
  5. Let's unpack each, individually, and manually verify and remediate the results. example image

Failure One: Ensure System Log Files Have Correct Permissions

If you click on the web link in red Ensure System Log Files Have Correct Permissions, a pop-up window will apprear with a lot of details about the failure. The rule that failed is Rule ID: xccdf_org.ssgproject.content_rule_rsyslog_files_permissions. example image

We can see some good information about this check, including the CCE number. (In this case CCE-80862-6) example image

The truly valuable information is down in desription. We just need to make sure that log files referenced in rsyslog.conf and /etc/rsyslog.d/*.conf have been set to, at least, chmod 0600 LOGFILE. example image

A quick check of the system shows that we are set correctly:

# ls -l /var/log/messages \
        /var/log/secure \
        /var/log/maillog \
        /var/log/cron \
        /var/log/spooler \
        /var/log/boot.log
-rw-------. 1 root root     0 Jul 25 03:07 /var/log/boot.log
-rw-------. 1 root root  7975 Jul 27 05:01 /var/log/cron
-rw-------. 1 root root     0 Jul 26 03:22 /var/log/maillog
-rw-------. 1 root root 25742 Jul 27 05:35 /var/log/messages
-rw-------. 1 root root   198 Jul 27 04:47 /var/log/secure
-rw-------. 1 root root     0 Jul 26 03:22 /var/log/spooler

Failure Two: Ensure Log Files Are Owned By Appropriate User

If you click on the web link in red Ensure Log Files Are Owned By Appropriate User, a pop-up window will apprear with a lot of details about the failure. The rule that failed is Rule ID: xccdf_org.ssgproject.content_rule_rsyslog_files_ownership. example image

We can see the CCE number. (In this case CCE-80861-8) example image

And the description. example image

Again, a quick check of the system shows that we are set correctly:

# ls -l /var/log/messages \
        /var/log/secure \
        /var/log/maillog \
        /var/log/cron \
        /var/log/spooler \
        /var/log/boot.log
-rw-------. 1 root root     0 Jul 25 03:07 /var/log/boot.log
-rw-------. 1 root root  7975 Jul 27 05:01 /var/log/cron
-rw-------. 1 root root     0 Jul 26 03:22 /var/log/maillog
-rw-------. 1 root root 25742 Jul 27 05:35 /var/log/messages
-rw-------. 1 root root   198 Jul 27 04:47 /var/log/secure
-rw-------. 1 root root     0 Jul 26 03:22 /var/log/spooler

Failure Three: Ensure Log Files Are Owned By Appropriate Group

If you click on the web link in red Ensure Log Files Are Owned By Appropriate Group, a pop-up window will apprear with a lot of details about the failure. The rule that failed is Rule ID: xccdf_org.ssgproject.content_rule_rsyslog_files_groupownership. example image

We can see the CCE number. (In this case CCE-80860-0) example image

And the description. example image

Again, a quick check of the system shows that we are set correctly:

# ls -l /var/log/messages \
        /var/log/secure \
        /var/log/maillog \
        /var/log/cron \
        /var/log/spooler \
        /var/log/boot.log
-rw-------. 1 root root     0 Jul 25 03:07 /var/log/boot.log
-rw-------. 1 root root  7975 Jul 27 05:01 /var/log/cron
-rw-------. 1 root root     0 Jul 26 03:22 /var/log/maillog
-rw-------. 1 root root 25742 Jul 27 05:35 /var/log/messages
-rw-------. 1 root root   198 Jul 27 04:47 /var/log/secure
-rw-------. 1 root root     0 Jul 26 03:22 /var/log/spooler

Why does OSCAP Have Failures on rsyslog

If you navigate to the very bottom of any of the three failures you will find that they all failed for the same reason. oscap code expects some input for subroutines. When none is fed into a routine, the routine can fail the entire sequence. What's failing? ssg-var_rfg_log_files_paths is null. example image

This is a known issue and should be fixed at a future date. The fix is currently included in the RHEL 8.3 Beta.

Errors resolved, but what about the Warning?

There was a single warning, or what appeared to be. example The scoring system shows three colors and only the word "passed" is visable next to the first number. The color coding is as follows:

Color Value
Green Passed / Fixed
Red Failed / error
Yellow Other

What was our rule which returned other? example

It's a rule which could be automated a variety of ways but not universally. What if we've restricted installs or subscripted to channels that never update?

example

This rule was skipped, but it needs to be integrated into build processes. Either:

  1. Patch after installations
  2. Installed from patched repositories

Conclusion

There's a lot that can be done to harden an OS image, and this process just scratches the surface. In many environments, multiple security profiles must be applied, as well as layers of application-specific best practice and security changes. Encapsulating these customizations in reliable, repeatable code is our ultimate goal.

Examples in this post can be found on GitHub