Skip to content

Debian 12/13 CIS 1.6.1-1.6.3: banner_etc_issue_cis, banner_etc_issue_net_cis and banner_etc_motd_cis pass the default Debian banners #15150

Description

@dynayl

Description of problem:

Found while comparing CIS results on Debian 12 images.

  • Products: debian12, debian13
  • Profiles: cis_level1_server, cis_level1_workstation (and the Level 2 profiles that inherit them), controls 1.6.1, 1.6.2, 1.6.3
  • Rules: banner_etc_motd_cis, banner_etc_issue_cis, banner_etc_issue_net_cis (template cis_banner)

On a default Debian 12 system all three rules pass, although all three files name the distribution. The files are the ones base-files installs (/etc/issue and /etc/issue.net are in the package; its postinst installs /etc/motd from /usr/share/base-files/motd):

/etc/issue      Debian GNU/Linux 12 \n \l
/etc/issue.net  Debian GNU/Linux 12
/etc/motd       The programs included with the Debian GNU/Linux system are free software; ...

The template's OVAL looks for this pattern (oval.template L34 at v0.1.82, same on master):

(\\v|\\r|\\m|\\s|{{{ product }}}|{{{ full_name }}})

For debian12 it renders to (\\v|\\r|\\m|\\s|debian12|Debian 12) (full_name: Debian 12, products/debian12/product.yml L2). The match is case-sensitive, and "Debian GNU/Linux 12" contains neither debian12 nor Debian 12. For debian13 the pattern is (\\v|\\r|\\m|\\s|debian13|Debian 13) and the default banner is "Debian GNU/Linux 13", with the same result.

The OCIL of the same rules disagrees with the OVAL. The ocil_cis_banner macro (shared/macros/10-ocil.jinja L1471-L1478, unchanged on master) has the reviewer run

grep -E -i "(\\\v|\\\r|\\\m|\\\s|$(grep '^ID=' /etc/os-release | cut -d= -f2 | sed -e 's/"//g'))" /etc/issue

and treats any output as a finding. On Debian ID=debian, and the command prints the banner lines of all three files. The rule descriptions also say the message should not contain information about the operating system version (banner_etc_issue_cis/rule.yml L8-L10).

#14998 (included in 0.1.82) added {{{ full_name }}} to the pattern so that the default Ubuntu 24.04 banners ("Ubuntu 24.04 LTS") are detected. That relies on the banner containing the full name exactly as product.yml spells it, which Debian's banners do not.

Control entries: controls/cis_debian12.yml L466-L494 (same lines on master), controls/cis_debian13.yml L640-L668 on master.

SCAP Security Guide Version:

0.1.82 (release data streams ssg-debian12-ds.xml and ssg-debian13-ds.xml from scap-security-guide-0.1.82.zip, sha512 checked against the published .sha512). The template, the OCIL macro and the debian12 control entries are unchanged on master at f956856.

Operating System Version:

  • Debian 12.15: debian:12@sha256:f37a335e82bca302e955fa39f9dfe28f1be618f016f8a2b56318e5a5111afc26 (linux/amd64), base-files 12.4+deb12u15
  • Debian 13: debian:13@sha256:9cc080028c43b27d2074d63a5f9caf7166d731494965616c1a6d2827a004585c (linux/amd64), base-files 13.8+deb13u7
  • OpenSCAP 1.4.4, oscap-chroot

Steps to Reproduce:

The image's root filesystem is evaluated offline. The only changes to it are removing /.dockerenv and adding a stand-in linux-base entry to the dpkg database, because the rules apply to system_with_kernel and a container export has no kernel package.

  1. Get the data stream:
    curl -fLO https://github.com/ComplianceAsCode/content/releases/download/v0.1.82/scap-security-guide-0.1.82.zip
    unzip scap-security-guide-0.1.82.zip scap-security-guide-0.1.82/ssg-debian12-ds.xml
    
  2. Export the image's root filesystem and add the stand-in:
    mkdir root
    docker export "$(docker create --platform linux/amd64 debian:12@sha256:f37a335e82bca302e955fa39f9dfe28f1be618f016f8a2b56318e5a5111afc26)" | sudo tar -x -C root
    sudo rm -f root/.dockerenv
    printf '%s\n' '' 'Package: linux-base' 'Status: install ok installed' 'Priority: optional' 'Section: misc' \
      'Installed-Size: 1' 'Maintainer: test <test@example.invalid>' 'Architecture: all' 'Version: 0' \
      'Description: stand-in' | sudo tee -a root/var/lib/dpkg/status >/dev/null
    
  3. Evaluate the three rules:
    sudo oscap-chroot root xccdf eval \
      --profile xccdf_org.ssgproject.content_profile_cis_level1_server \
      --rule xccdf_org.ssgproject.content_rule_banner_etc_issue_cis \
      --rule xccdf_org.ssgproject.content_rule_banner_etc_issue_net_cis \
      --rule xccdf_org.ssgproject.content_rule_banner_etc_motd_cis \
      scap-security-guide-0.1.82/ssg-debian12-ds.xml
    
  4. Run the rules' OCIL command against the same three files.

Actual Results:

Rule    xccdf_org.ssgproject.content_rule_banner_etc_issue_cis       Result  pass
Rule    xccdf_org.ssgproject.content_rule_banner_etc_issue_net_cis   Result  pass
Rule    xccdf_org.ssgproject.content_rule_banner_etc_motd_cis        Result  pass

The OCIL command returns output for each file (run once per file):

/etc/issue      Debian GNU/Linux 12 \n \l
/etc/issue.net  Debian GNU/Linux 12
/etc/motd       The programs included with the Debian GNU/Linux system are free software;
                Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent

The three rules still pass with each file set to debian. banner_etc_issue_cis fails with /etc/issue set to Debian 12. On the Debian 13 image with ssg-debian13-ds.xml and the same steps, the three rules pass on the default files.

Expected Results:

The three rules fail on the default Debian banners, as the OCIL check does.

Additional Information/Debugging Steps:

Suggested fix: match case-insensitively, as the OCIL's grep -E -i does, and add the os-release ID for Debian products:

--- a/shared/templates/cis_banner/oval.template
+++ b/shared/templates/cis_banner/oval.template
@@ -31,7 +31,7 @@
 
   <ind:textfilecontent54_object id="obj_{{{ rule_id }}}" version="1">
     <ind:filepath>{{{ FILEPATH }}}</ind:filepath>
-    <ind:pattern operation="pattern match">(\\v|\\r|\\m|\\s|{{{ product }}}|{{{ full_name }}})</ind:pattern>
+    <ind:pattern operation="pattern match">(?i)(\\v|\\r|\\m|\\s|{{{ product }}}|{{{ full_name }}}{{% if "debian" in families %}}|debian{{% endif %}})</ind:pattern>
     <ind:instance operation="greater than or equal" datatype="int">1</ind:instance>
   </ind:textfilecontent54_object>
 </def-group>
--- /dev/null
+++ b/shared/templates/cis_banner/tests/os_name.fail.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# platform = multi_platform_debian
+
+echo "Debian GNU/Linux 12 \n \l" > "{{{ FILEPATH }}}"

With this change debian12 renders to (?i)(\\v|\\r|\\m|\\s|debian12|Debian 12|debian). I built debian12 from master (f956856) with it (./build_product debian12 --datastream-only) and evaluated the same image: the three rules fail on the default files and on debian, and pass on the cis_banner_text text (Authorized users only. All activity may be monitored and reported.) and on a two-line site banner without OS information (Authorized access only. / All activity is logged.). oscap ds sds-validate accepts the data stream. The test scenario was not run with Automatus.

(?i) also applies to the other products that use the template (RHEL 8/9/10, Fedora, AlmaLinux 9, Ubuntu 22.04 and 24.04): there the product id and full name then match in any case, and \\s also matches \S, which agetty expands to the os-release PRETTY_NAME (agetty(8)) and which the OCIL's grep -E -i already flags. The sketch adds the os-release ID only for Debian; a per-product value (for example a product property) would make the OVAL look for the same ID as the OCIL on the other products too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions