PRACTITIONER GUIDE
Practitioner Guide12 min read

Ubuntu and RHEL Linux CIS Benchmark Hardening: sysctl Parameters, AppArmor/SELinux, and Automated Compliance Verification

2
required value for kernel.randomize_va_space to enable full ASLR, randomizing stack, heap, and shared library addresses on every process execution to defeat memory corruption exploits that rely on predictable addresses
48 hours
recommended review period in AppArmor complain or SELinux permissive mode before switching to enforce, giving time to identify legitimate operations that would be blocked and configure exceptions before enforcement breaks services
80%+
minimum CIS Level 1 compliance score recommended as the pipeline gate before a hardened server image is promoted to production, verified by OpenSCAP XCCDF assessment against the appropriate benchmark profile
noexec, nosuid, nodev
three mount options required by CIS benchmark on /tmp, /var/tmp, and /dev/shm to prevent world-writable directories from being used to stage and execute malicious code or setuid binaries

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

Linux servers deployed from standard cloud provider base images (Ubuntu 22.04 LTS, RHEL 9) do not meet the CIS Level 1 benchmark without additional hardening. The default settings are optimized for broad compatibility rather than security: ICMP redirects are accepted, ASLR may not be at full strength, AppArmor is in complain mode rather than enforce mode on Ubuntu, and SELinux is in permissive mode rather than enforcing mode on RHEL. These defaults are documented, systematic, and remediable.

The CIS benchmark provides a prioritized checklist and OpenSCAP provides automated assessment and remediation scripting, making Linux CIS hardening more accessible than manual configuration review. The key challenge is not identifying what needs to change — the benchmark provides that — but testing changes in a staging environment and applying them systematically without disrupting running services.

Hardening sequence: test in staging before production

CIS hardening changes range from zero-disruption (sysctl parameters applied with sysctl -p) to high-disruption (SELinux enforce mode blocking syscalls that services depend on). Applying changes in the wrong order or skipping staging validation is the most common reason hardening efforts cause production incidents. This section covers starting with sysctl parameters as the safest first change, using the auditd and AppArmor allow logs to identify what would break before switching to enforce mode, and monitoring application logs between each hardening phase to catch issues before they compound.

Apply sysctl hardening first as the lowest-disruption change

Apply sysctl parameter hardening as the first hardening step because it is fully reversible, does not affect running processes, and can be tested immediately with sysctl -p. Create /etc/sysctl.d/99-cis-hardening.conf with all CIS-required sysctl parameters and apply with sysctl -p /etc/sysctl.d/99-cis-hardening.conf without a reboot. Monitor application logs for 30 minutes after applying to confirm no services are affected. The parameters that occasionally affect services are net.ipv4.ip_forward = 0 (required on routing systems), net.ipv4.tcp_syncookies = 1 (occasionally conflicts with load balancer health check behavior), and kernel.randomize_va_space = 2 (rarely conflicts with older applications that hardcode memory addresses). These can be addressed by reverting the specific parameter while keeping the rest of the hardening in place.

Switch AppArmor or SELinux from complain/permissive to enforce mode only after 48 hours of AVC log review

The transition from AppArmor complain mode (Ubuntu) or SELinux permissive mode (RHEL) to enforce mode is the highest-risk CIS hardening step because it blocks operations that were previously allowed, potentially breaking services. Run in complain/permissive mode on production for 48 hours before switching to enforce mode, and review the audit log daily: on Ubuntu, grep /var/log/syslog for apparmor=ALLOWED to see what would be blocked; on RHEL, use ausearch -m avc --start recent to review recent AVC denials. For each legitimate operation appearing in the allow/deny log, configure the appropriate AppArmor profile exception or SELinux boolean before switching to enforce mode. This 48-hour review period catches service-specific exceptions that testing in staging may have missed due to different workload patterns.

Automated compliance: OpenSCAP and continuous verification

A server that passes the CIS benchmark on deployment day and drifts back toward default settings over 18 months of OS updates, package installations, and administrator changes provides only temporary security value. OpenSCAP automates compliance verification with oscap xccdf eval, produces HTML reports showing each control's pass/fail status, and can generate bash remediation scripts. Integrating OpenSCAP into the CI/CD deployment pipeline and scheduling monthly production scans provides the continuous evidence trail that separates a maintained hardened baseline from a one-time hardening event.

Integrate OpenSCAP assessment into the server deployment pipeline

Run an OpenSCAP CIS assessment as the final step in the server deployment pipeline before a new server is promoted to production status. In a CI/CD context, configure the Ansible hardening playbook as a provisioning step, then run the OpenSCAP assessment against the server and fail the pipeline if the CIS compliance score falls below your target (typically 80% or higher for Level 1 controls). This prevents deploying unhardened servers to production because a hardening step was skipped or failed silently. The OpenSCAP XCCDF result file generated in the pipeline can be archived as the compliance evidence artifact for the server's provisioning record.

Schedule monthly OpenSCAP scans to detect configuration drift

Schedule monthly OpenSCAP compliance scans on production servers using a cron job or Ansible playbook run triggered by a configuration management tool. Configuration drift — software package installations that modify security settings, OS updates that change default configurations, and manual changes by administrators — degrades the hardened baseline over time. Compare each month's OpenSCAP scan results against the previous month to identify newly failing controls. Investigate each new failure to determine whether it resulted from an intentional change (that needs to be documented as an exception) or an unintentional change (that needs to be reversed). Automating this detection prevents the common scenario where a server is hardened at deployment and gradually drifts back toward a default configuration over 12-18 months of production operation.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

The bottom line

Ubuntu and RHEL Linux CIS benchmark hardening addresses the systematic configuration gaps in default Linux server deployments: sysctl network security parameters, AppArmor enforce mode (Ubuntu) or SELinux enforcing mode (RHEL), filesystem hardening with noexec/nosuid/nodev on temporary mounts, SSH configuration hardening, and disabled unnecessary services. Apply sysctl hardening first as the lowest-disruption change, then transition AppArmor/SELinux to enforce mode after 48 hours of audit log review in the production environment. Use OpenSCAP for automated assessment in the deployment pipeline and monthly drift detection. Ansible CIS hardening roles from ansible-lockdown automate the full CIS benchmark application across server fleets, reducing the manual configuration work to a single playbook run with pre-deployment check mode review.

Frequently asked questions

What are the most important sysctl security parameters to configure on Linux servers?

The highest-priority sysctl security parameters from the CIS Linux Benchmark: net.ipv4.ip_forward = 0 (disable IP forwarding on non-router systems), net.ipv4.conf.all.accept_redirects = 0 and net.ipv6.conf.all.accept_redirects = 0 (disable ICMP redirect acceptance which can be used for routing manipulation), net.ipv4.conf.all.log_martians = 1 (log packets with impossible source addresses for anomaly detection), net.ipv4.tcp_syncookies = 1 (enable SYN cookies for SYN flood protection), kernel.randomize_va_space = 2 (full ASLR), kernel.dmesg_restrict = 1 (restrict dmesg access to root only, preventing information disclosure of kernel addresses), fs.protected_hardlinks = 1 and fs.protected_symlinks = 1 (prevent privilege escalation via hardlink and symlink attacks in world-writable directories), kernel.core_uses_pid = 1 (include PID in core dump filenames), and net.ipv4.conf.all.send_redirects = 0 (disable ICMP redirect sending on non-router systems). Apply all settings to /etc/sysctl.d/99-cis-hardening.conf and run sysctl -p /etc/sysctl.d/99-cis-hardening.conf to apply.

How do I enable AppArmor enforce mode on Ubuntu without breaking services?

Enable AppArmor enforce mode safely by checking the current profile status first with aa-status, which shows profiles in enforce versus complain mode. Run aa-status | grep complain to list profiles currently in complain mode. Before switching a profile to enforce mode, review the AppArmor audit log (/var/log/syslog on Ubuntu, grep for apparmor=ALLOWED to see what would be blocked) to identify operations the service is performing that the current profile allows but that might be denied in enforce mode after a software update or configuration change. To switch all installed profiles to enforce mode: sudo aa-enforce /etc/apparmor.d/* which is safe for stock Ubuntu profiles that are well-tested. For custom application profiles: test by checking the complain log for 24 hours after a configuration change, confirm no legitimate operations appear in the deny log, then switch to enforce mode. Reload a modified profile with sudo apparmor_parser -r /etc/apparmor.d/profile_name.

How do I enable SELinux enforcing mode on RHEL without causing service failures?

Enable SELinux enforcing mode on RHEL by following a staged process to avoid service disruptions. First, check the current SELinux status with sestatus and getenforce. If SELinux is currently disabled (not just permissive), you must relabel the filesystem before enabling enforcing mode: set SELINUX=permissive in /etc/sysconfig/selinux, reboot (which triggers filesystem relabeling based on the SELinux policy), then review /var/log/audit/audit.log for AVC denials using ausearch -m avc which shows what would be blocked in enforcing mode. For each AVC denial, either configure the appropriate SELinux boolean (setsebool -P httpd_enable_homedirs on for the relevant service) or generate a custom policy module using audit2allow -a -M mymodule followed by semodule -i mymodule.pp. After confirming no unexpected AVC denials for 24-48 hours in permissive mode, switch to enforcing: setenforce 1 and set SELINUX=enforcing in /etc/sysconfig/selinux.

How do I configure /tmp and other temporary filesystem mounts with CIS-required security options?

The CIS benchmark requires mounting /tmp, /var/tmp, /dev/shm, and removable media with nodev (no device files), nosuid (no setuid execution), and noexec (no direct script execution) mount options to prevent these world-writable directories from being used to stage and execute malicious code. For /tmp on systems using systemd, override the default systemd-tmpfiles configuration: create /etc/systemd/system/tmp.mount with [Mount] options line: Options=mode=1777,strictatime,noexec,nodev,nosuid, then run systemctl daemon-reload and systemctl enable tmp.mount. For /var/tmp, add or modify the /var/tmp entry in /etc/fstab: /var/tmp tmpfs defaults,noexec,nodev,nosuid 0 0. For /dev/shm, add: none /dev/shm tmpfs defaults,noexec,nodev,nosuid 0 0 to /etc/fstab. Run mount -o remount /dev/shm to apply without a reboot. Verify with mount | grep /tmp to confirm the options are active.

How do I run an OpenSCAP CIS benchmark assessment on Ubuntu or RHEL?

Run an OpenSCAP assessment against the CIS benchmark using the oscap command-line tool with the appropriate XCCDF profile. On Ubuntu: install openscap-scanner and the Ubuntu SCAP content (apt install libopenscap8 ssg-debderived). Run the assessment with sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis_level1_server --report report.html --results results.xml /usr/share/xml/scap/ssg/content/ssg-ubuntu2204-xccdf.xml. On RHEL: install openscap-scanner and scap-security-guide (dnf install openscap-scanner scap-security-guide). Run: sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis --report report.html --results results.xml /usr/share/xml/scap/ssg/content/ssg-rhel9-xccdf.xml. The HTML report shows each CIS control with a pass/fail/not-applicable result and a description of the finding. Use the --remediation bash option to generate a remediation script: sudo oscap xccdf generate fix --profile cis --fix-type bash results.xml > remediate.sh, review the script before running, then execute to remediate failing controls automatically.

What SSH configuration changes does the CIS benchmark require?

The CIS Linux Benchmark SSH hardening requirements for /etc/ssh/sshd_config include: PermitRootLogin no (prevent direct root SSH login, require login as regular user and then sudo), MaxAuthTries 4 (limit authentication attempts per connection to reduce brute force risk), PermitEmptyPasswords no (require a password or key), Protocol 2 (SSH protocol 2 only, protocol 1 is cryptographically broken), X11Forwarding no (disable unless X11 application display is required), AllowTcpForwarding no (disable TCP tunnel creation through SSH unless specifically needed), ClientAliveInterval 300 and ClientAliveCountMax 0 (terminate idle sessions after 5 minutes), LoginGraceTime 60 (limit time allowed to complete authentication), PermitUserEnvironment no (prevent users from passing custom environment variables that could affect security), and Ciphers aes128-ctr,aes192-ctr,aes256-ctr (restrict to CTR mode AES ciphers, excluding CBC mode which has known padding oracle attacks). After editing sshd_config, run sshd -t to test the configuration syntax before restarting the SSH service.

How do I use Ansible to automate CIS hardening across a fleet of Linux servers?

Use the community-maintained Ansible CIS hardening role from the ansible-lockdown organization on GitHub (UBUNTU22-CIS for Ubuntu 22.04, RHEL9-CIS for RHEL 9) which implements the full CIS benchmark as an Ansible playbook with each control as a tagged task. Install the role with ansible-galaxy role install ansible-lockdown.UBUNTU22-CIS. Create a playbook that applies the role to your server inventory: configure the role variables to enable or disable specific sections (ubtu22cis_section1 through ubtu22cis_section6 cover the six CIS benchmark sections). Run the playbook in check mode first (ansible-playbook --check site.yml) to see what changes would be made without applying them. After reviewing the check mode output, run without check mode to apply. The role includes tags for each CIS control number, so you can run only specific sections: ansible-playbook site.yml --tags level1-server to apply only CIS Level 1 server controls. Use the role's built-in audit mode to generate a compliance report without making changes.

Sources & references

  1. CIS Ubuntu Linux 22.04 LTS Benchmark
  2. CIS Red Hat Enterprise Linux 9 Benchmark
  3. OpenSCAP Documentation
  4. Ansible CIS Hardening Role

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.