scap-security-guide/SOURCES/scap-security-guide-0.1.59-BZ1884687C-PR_7824.patch
2022-04-26 18:09:24 +00:00

663 lines
33 KiB
Diff

commit dc273bb872cc53f2d52af4396f4d3bba0acc178f
Author: Gabriel Becker <ggasparb@redhat.com>
Date: Thu Feb 24 17:30:42 2022 +0100
Manual edited patch scap-security-guide-0.1.59-BZ1884687C-PR_7824.patch.
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/ansible/shared.yml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/ansible/shared.yml
new file mode 100644
index 0000000..ff41e19
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/ansible/shared.yml
@@ -0,0 +1,32 @@
+# platform = multi_platform_all
+# reboot = false
+# strategy = restrict
+# complexity = low
+# disruption = low
+
+- name: Get all local users from /etc/passwd
+ ansible.builtin.getent:
+ database: passwd
+ split: ':'
+
+- name: Create local_users variable from the getent output
+ ansible.builtin.set_fact:
+ local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
+
+- name: Test for existence home directories to avoid creating them, but only fixing ownership
+ ansible.builtin.stat:
+ path: '{{ item.value[4] }}'
+ register: path_exists
+ loop: '{{ local_users }}'
+ when:
+ - item.value[2]|int >= {{{ gid_min }}}
+ - item.value[2]|int != 65534
+
+- name: Ensure interactive local users are the owners of their respective home directories
+ ansible.builtin.file:
+ path: '{{ item.0.value[4] }}'
+ group: '{{ item.0.value[2] }}'
+ recurse: yes
+ loop: '{{ local_users|zip(path_exists.results)|list }}'
+ when:
+ - item.1.stat is defined and item.1.stat.exists
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/bash/shared.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/bash/shared.sh
new file mode 100644
index 0000000..e392d2f
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/bash/shared.sh
@@ -0,0 +1,14 @@
+# platform = multi_platform_all
+# reboot = false
+# strategy = restrict
+# complexity = low
+# disruption = low
+
+for user in $(awk -F':' '{ if ($4 >= {{{ gid_min }}} && $4 != 65534) print $1 }' /etc/passwd); do
+ home_dir=$(getent passwd $user | cut -d: -f6)
+ group=$(getent passwd $user | cut -d: -f4)
+ # Only update the group-ownership when necessary. This will avoid changing the inode timestamp
+ # when the group is already defined as expected, therefore not impacting in possible integrity
+ # check systems that also check inodes timestamps.
+ find $home_dir -not -group $group -exec chgrp -f $group {} \;
+done
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/oval/shared.xml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/oval/shared.xml
new file mode 100644
index 0000000..1fd016a
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/oval/shared.xml
@@ -0,0 +1,52 @@
+<def-group>
+ <definition class="compliance" id="{{{ rule_id }}}" version="1">
+ {{{ oval_metadata("All User Files and Directories In The Home Directory Must Be Group-Owned By The Primary User") }}}
+ <criteria>
+ <criterion test_ref="test_accounts_users_home_files_groupownership"
+ comment="All User Files and Directories In The Home Directory Must Be Group-Owned By The Primary User"/>
+ </criteria>
+ </definition>
+
+ <unix:password_object id="object_accounts_users_home_files_groupownership_objects" version="1">
+ <unix:username datatype="string" operation="not equal">nobody</unix:username>
+ <filter action="include">state_accounts_users_home_files_groupownership_interactive_gids</filter>
+ </unix:password_object>
+
+ <unix:password_state id="state_accounts_users_home_files_groupownership_interactive_gids" version="1">
+ <unix:user_id datatype="int" operation="greater than or equal">{{{ gid_min }}}</unix:user_id>
+ </unix:password_state>
+
+ <local_variable id="var_accounts_users_home_files_groupownership_dirs" datatype="string" version="1"
+ comment="Variable including all home dirs from interactive users">
+ <object_component item_field="home_dir"
+ object_ref="object_accounts_users_home_files_groupownership_objects"/>
+ </local_variable>
+
+ <local_variable id="var_accounts_users_home_files_groupownership_gids" datatype="int" version="1"
+ comment="List of interactive users gids">
+ <object_component item_field="group_id"
+ object_ref="object_accounts_users_home_files_groupownership_objects"/>
+ </local_variable>
+
+ <!-- #### creation of object #### -->
+ <unix:file_object id="object_accounts_users_home_files_groupownership_dirs" version="1">
+ <unix:behaviors recurse="directories" recurse_direction="down" max_depth="-1"
+ recurse_file_system="local"/>
+ <unix:path var_ref="var_accounts_users_home_files_groupownership_dirs" var_check="at least one"/>
+ <unix:filename operation="pattern match">.*</unix:filename>
+ </unix:file_object>
+
+ <!-- #### creation of state #### -->
+ <unix:file_state id="state_accounts_users_home_files_groupownership_gids" version="1">
+ <unix:group_id datatype="int" var_check="only one"
+ var_ref="var_accounts_users_home_files_groupownership_gids"/>
+ </unix:file_state>
+
+ <!-- #### creation of test #### -->
+ <unix:file_test id="test_accounts_users_home_files_groupownership" check="all"
+ check_existence="any_exist" version="1"
+ comment="All home directories files are group-owned by a local interactive user">
+ <unix:object object_ref="object_accounts_users_home_files_groupownership_dirs"/>
+ <unix:state state_ref="state_accounts_users_home_files_groupownership_gids"/>
+ </unix:file_test>
+</def-group>
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/rule.yml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/rule.yml
index 1c0f93a..31a0f1d 100644
--- a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/rule.yml
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/rule.yml
@@ -10,6 +10,9 @@ description: |-
local interactive users files and directories, use the following command:
<pre>$ sudo chgrp <i>USER_GROUP</i> /home/<i>USER</i>/<i>FILE_DIR</i></pre>
+ This rule ensures every file or directory under the home directory related
+ to an interactive user is group-owned by an interactive user.
+
rationale: |-
If a local interactive users files are group-owned by a group of which the
user is not a member, unintended users may be able to access them.
@@ -33,3 +36,9 @@ ocil: |-
group-owned by a group the user is a member of, run the
following command:
<pre>$ sudo ls -lLR /home/<i>USER</i></pre>
+
+warnings:
+ - general: |-
+ Due to OVAL limitation, this rule can report a false negative in a
+ specific situation where two interactive users swap the group-ownership
+ of folders or files in their respective home directories.
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/expected_groupowner.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/expected_groupowner.pass.sh
new file mode 100644
index 0000000..8538430
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/expected_groupowner.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chgrp -f $USER /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/home_dirs_all_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/home_dirs_all_absent.pass.sh
new file mode 100644
index 0000000..af24025
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/home_dirs_all_absent.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -M $USER
+# This make sure home dirs related to test environment users are also removed.
+rm -Rf /home/*
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/home_dirs_one_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/home_dirs_one_absent.pass.sh
new file mode 100644
index 0000000..5bce517
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/home_dirs_one_absent.pass.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+USER1="cac_user1"
+USER2="cac_user2"
+
+useradd -m $USER1
+useradd -M $USER2
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/interactive_users_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/interactive_users_absent.pass.sh
new file mode 100644
index 0000000..ed34f09
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/interactive_users_absent.pass.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# remove all interactive users (ID >= 1000) from /etc/passwd
+sed -i '/.*:[0-9]\{4,\}:/d' /etc/passwd
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/unexpected_groupowner_system_gid.fail.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/unexpected_groupowner_system_gid.fail.sh
new file mode 100644
index 0000000..f105723
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/unexpected_groupowner_system_gid.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chgrp 2 /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/unexpected_groupowner_unknown_gid.fail.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/unexpected_groupowner_unknown_gid.fail.sh
new file mode 100644
index 0000000..00fa481
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/unexpected_groupowner_unknown_gid.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chgrp 10005 /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/warning_home_dirs_swapped_groupowner.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/warning_home_dirs_swapped_groupowner.pass.sh
new file mode 100644
index 0000000..052aa7c
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_groupownership/tests/warning_home_dirs_swapped_groupowner.pass.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+USER1="cac_user1"
+USER2="cac_user2"
+
+useradd -m $USER1
+useradd -m $USER2
+echo "$USER1" > /home/$USER1/$USER1.txt
+echo "$USER2" > /home/$USER2/$USER2.txt
+# Swap the ownership of files in two home directories
+# WARNING: This test scenario will report a false negative, as explained in the
+# warning section of this rule.
+chgrp -f $USER2 /home/$USER1/$USER1.txt
+chgrp -f $USER1 /home/$USER2/$USER2.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/ansible/shared.yml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/ansible/shared.yml
new file mode 100644
index 0000000..40a0579
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/ansible/shared.yml
@@ -0,0 +1,32 @@
+# platform = multi_platform_all
+# reboot = false
+# strategy = restrict
+# complexity = low
+# disruption = low
+
+- name: Get all local users from /etc/passwd
+ ansible.builtin.getent:
+ database: passwd
+ split: ':'
+
+- name: Create local_users variable from the getent output
+ ansible.builtin.set_fact:
+ local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
+
+- name: Test for existence home directories to avoid creating them, but only fixing ownership
+ ansible.builtin.stat:
+ path: '{{ item.value[4] }}'
+ register: path_exists
+ loop: '{{ local_users }}'
+ when:
+ - item.value[1]|int >= {{{ uid_min }}}
+ - item.value[1]|int != 65534
+
+- name: Ensure interactive local users are the owners of their respective home directories
+ ansible.builtin.file:
+ path: '{{ item.0.value[4] }}'
+ owner: '{{ item.0.value[1] }}'
+ recurse: yes
+ loop: '{{ local_users|zip(path_exists.results)|list }}'
+ when:
+ - item.1.stat is defined and item.1.stat.exists
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/bash/shared.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/bash/shared.sh
new file mode 100644
index 0000000..236c800
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/bash/shared.sh
@@ -0,0 +1,13 @@
+# platform = multi_platform_all
+# reboot = false
+# strategy = restrict
+# complexity = low
+# disruption = low
+
+for user in $(awk -F':' '{ if ($3 >= {{{ uid_min }}} && $3 != 65534) print $1 }' /etc/passwd); do
+ home_dir=$(getent passwd $user | cut -d: -f6)
+ # Only update the ownership when necessary. This will avoid changing the inode timestamp
+ # when the owner is already defined as expected, therefore not impacting in possible integrity
+ # check systems that also check inodes timestamps.
+ find $home_dir -not -user $user -exec chown -f $user {} \;
+done
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/oval/shared.xml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/oval/shared.xml
new file mode 100644
index 0000000..1850cfb
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/oval/shared.xml
@@ -0,0 +1,52 @@
+<def-group>
+ <definition class="compliance" id="{{{ rule_id }}}" version="1">
+ {{{ oval_metadata("All User Files and Directories In The Home Directory Must Have a Valid Owner") }}}
+ <criteria>
+ <criterion test_ref="test_accounts_users_home_files_ownership"
+ comment="All User Files and Directories In The Home Directory Must Have a Valid Owner"/>
+ </criteria>
+ </definition>
+
+ <unix:password_object id="object_accounts_users_home_files_ownership_objects" version="1">
+ <unix:username datatype="string" operation="not equal">nobody</unix:username>
+ <filter action="include">state_accounts_users_home_files_ownership_interactive_uids</filter>
+ </unix:password_object>
+
+ <unix:password_state id="state_accounts_users_home_files_ownership_interactive_uids" version="1">
+ <unix:user_id datatype="int" operation="greater than or equal">{{{ uid_min }}}</unix:user_id>
+ </unix:password_state>
+
+ <local_variable id="var_accounts_users_home_files_ownership_dirs" datatype="string" version="1"
+ comment="Variable including all home dirs from interactive users">
+ <object_component item_field="home_dir"
+ object_ref="object_accounts_users_home_files_ownership_objects"/>
+ </local_variable>
+
+ <local_variable id="var_accounts_users_home_files_ownership_uids" datatype="int" version="1"
+ comment="List of interactive users uids">
+ <object_component item_field="user_id"
+ object_ref="object_accounts_users_home_files_ownership_objects"/>
+ </local_variable>
+
+ <!-- #### creation of object #### -->
+ <unix:file_object id="object_accounts_users_home_files_ownership_dirs" version="1">
+ <unix:behaviors recurse="directories" recurse_direction="down" max_depth="-1"
+ recurse_file_system="local"/>
+ <unix:path var_ref="var_accounts_users_home_files_ownership_dirs" var_check="at least one"/>
+ <unix:filename operation="pattern match">.*</unix:filename>
+ </unix:file_object>
+
+ <!-- #### creation of state #### -->
+ <unix:file_state id="state_accounts_users_home_files_ownership_uids" version="1">
+ <unix:user_id datatype="int" var_check="only one"
+ var_ref="var_accounts_users_home_files_ownership_uids"/>
+ </unix:file_state>
+
+ <!-- #### creation of test #### -->
+ <unix:file_test id="test_accounts_users_home_files_ownership" check="all"
+ check_existence="any_exist" version="1"
+ comment="All home directories files are owned by a local interactive user">
+ <unix:object object_ref="object_accounts_users_home_files_ownership_dirs"/>
+ <unix:state state_ref="state_accounts_users_home_files_ownership_uids"/>
+ </unix:file_test>
+</def-group>
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/rule.yml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/rule.yml
index 13f6bfe..5bfb388 100644
--- a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/rule.yml
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/rule.yml
@@ -10,6 +10,9 @@ description: |-
directories, use the following command:
<pre>$ sudo chown -R <i>USER</i> /home/<i>USER</i></pre>
+ This rule ensures every file or directory under the home directory related
+ to an interactive user is owned by an interactive user.
+
rationale: |-
If local interactive users do not own the files in their directories,
unauthorized users may be able to access them. Additionally, if files are not
@@ -34,3 +37,9 @@ ocil: |-
To verify all files and directories in interactive users home directory
are owned by the user, run the following command:
<pre>$ sudo ls -lLR /home/<i>USER</i></pre>
+
+warnings:
+ - general: |-
+ Due to OVAL limitation, this rule can report a false negative in a
+ specific situation where two interactive users swap the ownership of
+ folders or files in their respective home directories.
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/expected_owner.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/expected_owner.pass.sh
new file mode 100644
index 0000000..da68cb4
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/expected_owner.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chown $USER /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/home_dirs_all_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/home_dirs_all_absent.pass.sh
new file mode 100644
index 0000000..af24025
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/home_dirs_all_absent.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -M $USER
+# This make sure home dirs related to test environment users are also removed.
+rm -Rf /home/*
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/home_dirs_one_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/home_dirs_one_absent.pass.sh
new file mode 100644
index 0000000..5bce517
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/home_dirs_one_absent.pass.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+USER1="cac_user1"
+USER2="cac_user2"
+
+useradd -m $USER1
+useradd -M $USER2
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/interactive_users_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/interactive_users_absent.pass.sh
new file mode 100644
index 0000000..ed34f09
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/interactive_users_absent.pass.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# remove all interactive users (ID >= 1000) from /etc/passwd
+sed -i '/.*:[0-9]\{4,\}:/d' /etc/passwd
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/unexpected_owner_system_id.fail.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/unexpected_owner_system_id.fail.sh
new file mode 100644
index 0000000..59c46a9
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/unexpected_owner_system_id.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chown 2 /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/unexpected_owner_unknown_id.fail.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/unexpected_owner_unknown_id.fail.sh
new file mode 100644
index 0000000..e0f5514
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/unexpected_owner_unknown_id.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chown 10005 /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/warning_home_dirs_swapped_owner.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/warning_home_dirs_swapped_owner.pass.sh
new file mode 100644
index 0000000..1174ec6
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_ownership/tests/warning_home_dirs_swapped_owner.pass.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+USER1="cac_user1"
+USER2="cac_user2"
+
+useradd -m $USER1
+useradd -m $USER2
+echo "$USER1" > /home/$USER1/$USER1.txt
+echo "$USER2" > /home/$USER2/$USER2.txt
+# Swap the ownership of files in two home directories
+# WARNING: This test scenario will report a false negative, as explained in the
+# warning section of this rule.
+chown -f $USER2 /home/$USER1/$USER1.txt
+chown -f $USER1 /home/$USER2/$USER2.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/ansible/shared.yml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/ansible/shared.yml
new file mode 100644
index 0000000..9473710
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/ansible/shared.yml
@@ -0,0 +1,33 @@
+# platform = multi_platform_all
+# reboot = false
+# strategy = restrict
+# complexity = low
+# disruption = low
+
+- name: Get all local users from /etc/passwd
+ ansible.builtin.getent:
+ database: passwd
+ split: ':'
+
+- name: Create local_users variable from the getent output
+ ansible.builtin.set_fact:
+ local_users: '{{ ansible_facts.getent_passwd|dict2items }}'
+
+- name: Test for existence home directories to avoid creating them, but only fixing group ownership
+ ansible.builtin.stat:
+ path: '{{ item.value[4] }}'
+ register: path_exists
+ loop: '{{ local_users }}'
+ when:
+ - item.value[2]|int >= {{{ uid_min }}}
+ - item.value[2]|int != 65534
+
+- name: Ensure interactive local users are the group-owners of their respective home directories
+ ansible.builtin.file:
+ path: '{{ item.0.value[4] }}'
+ mode: 'g-w,o=-'
+ follow: no
+ recurse: yes
+ loop: '{{ local_users|zip(path_exists.results)|list }}'
+ when:
+ - item.1.stat is defined and item.1.stat.exists
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/bash/shared.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/bash/shared.sh
new file mode 100644
index 0000000..186d55d
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/bash/shared.sh
@@ -0,0 +1,12 @@
+# platform = multi_platform_all
+# reboot = false
+# strategy = restrict
+# complexity = low
+# disruption = low
+
+for home_dir in $(awk -F':' '{ if ($4 >= {{{ uid_min }}} && $4 != 65534) print $6 }' /etc/passwd); do
+ # Only update the permissions when necessary. This will avoid changing the inode timestamp when
+ # the permission is already defined as expected, therefore not impacting in possible integrity
+ # check systems that also check inodes timestamps.
+ find $home_dir -perm /027 -exec chmod g-w,o=- {} \;
+done
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/oval/shared.xml b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/oval/shared.xml
new file mode 100644
index 0000000..d3db46d
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/oval/shared.xml
@@ -0,0 +1,52 @@
+<def-group>
+ <definition class="compliance" id="{{{ rule_id }}}" version="1">
+ {{{ oval_metadata("All User Files and Directories In The Home Directory Must Have Mode 0750 Or Less Permissive") }}}
+ <criteria>
+ <criterion test_ref="test_accounts_users_home_files_permissions"
+ comment="All files under interactive user's Home Directories must have proper permissions"/>
+ </criteria>
+ </definition>
+
+ <!-- For detailed comments about logic used in this OVAL, check the
+ "file_ownership_home_directories" rule. -->
+ <unix:password_object id="object_accounts_users_home_files_permissions_objects" version="1">
+ <unix:username datatype="string" operation="not equal">nobody</unix:username>
+ <filter action="include">state_accounts_users_home_files_permissions_interactive_uids</filter>
+ </unix:password_object>
+
+ <unix:password_state id="state_accounts_users_home_files_permissions_interactive_uids" version="1">
+ <unix:user_id datatype="int" operation="greater than or equal">{{{ uid_min }}}</unix:user_id>
+ </unix:password_state>
+
+ <!-- #### prepare for test_file_permissions_home_directories #### -->
+ <local_variable id="var_accounts_users_home_files_permissions_dirs" datatype="string" version="1"
+ comment="Variable including all home dirs from interactive users">
+ <object_component item_field="home_dir" object_ref="object_accounts_users_home_files_permissions_objects"/>
+ </local_variable>
+
+ <!-- #### creation of object #### -->
+ <unix:file_object id="object_accounts_users_home_files_permissions_dirs" version="1">
+ <unix:behaviors recurse="directories" recurse_direction="down" max_depth="-1"
+ recurse_file_system="local"/>
+ <unix:path var_ref="var_accounts_users_home_files_permissions_dirs" var_check="at least one"/>
+ <unix:filename operation="pattern match">.*</unix:filename>
+ </unix:file_object>
+
+ <!-- #### creation of state #### -->
+ <unix:file_state id="state_accounts_users_home_files_permissions_dirs" version="1" operator='AND'>
+ <unix:suid datatype="boolean">false</unix:suid>
+ <unix:sgid datatype="boolean">false</unix:sgid>
+ <unix:sticky datatype="boolean">false</unix:sticky>
+ <unix:gwrite datatype="boolean">false</unix:gwrite>
+ <unix:oread datatype="boolean">false</unix:oread>
+ <unix:owrite datatype="boolean">false</unix:owrite>
+ <unix:oexec datatype="boolean">false</unix:oexec>
+ </unix:file_state>
+
+ <!-- #### creation of test #### -->
+ <unix:file_test id="test_accounts_users_home_files_permissions" check="all" check_existence="any_exist"
+ version="1" comment="All home directories have proper permissions">
+ <unix:object object_ref="object_accounts_users_home_files_permissions_dirs"/>
+ <unix:state state_ref="state_accounts_users_home_files_permissions_dirs"/>
+ </unix:file_test>
+</def-group>
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/acceptable_permission.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/acceptable_permission.pass.sh
new file mode 100644
index 0000000..3561847
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/acceptable_permission.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chmod -Rf 750 /home/$USER/.*
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/expected_permissions.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/expected_permissions.pass.sh
new file mode 100644
index 0000000..8ed7fa2
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/expected_permissions.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chmod -Rf 700 /home/$USER/.*
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/home_dirs_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/home_dirs_absent.pass.sh
new file mode 100644
index 0000000..af24025
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/home_dirs_absent.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -M $USER
+# This make sure home dirs related to test environment users are also removed.
+rm -Rf /home/*
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/interactive_users_absent.pass.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/interactive_users_absent.pass.sh
new file mode 100644
index 0000000..ed34f09
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/interactive_users_absent.pass.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# remove all interactive users (ID >= 1000) from /etc/passwd
+sed -i '/.*:[0-9]\{4,\}:/d' /etc/passwd
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/lenient_permission.fail.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/lenient_permission.fail.sh
new file mode 100644
index 0000000..b561671
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/lenient_permission.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/$USER.txt
+chmod -Rf 700 /home/$USER/.*
+chmod -f o+r /home/$USER/$USER.txt
diff --git a/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/lenient_permission_hidden_files.fail.sh b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/lenient_permission_hidden_files.fail.sh
new file mode 100644
index 0000000..d7811bc
--- /dev/null
+++ b/linux_os/guide/system/accounts/accounts-session/accounts_users_home_files_permissions/tests/lenient_permission_hidden_files.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+USER="cac_user"
+useradd -m $USER
+echo "$USER" > /home/$USER/.init_file
+chmod -Rf 700 /home/$USER/.*
+chmod -f o+r /home/$USER/.init_file
diff --git a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_system_id.fail.sh b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_system_uid.fail.sh
similarity index 100%
rename from linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_system_id.fail.sh
rename to linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_system_uid.fail.sh
diff --git a/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_unknown_id.fail.sh b/linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_unknown_uid.fail.sh
similarity index 100%
rename from linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_unknown_id.fail.sh
rename to linux_os/guide/system/accounts/accounts-session/file_groupownership_home_directories/tests/unexpected_groupowner_unknown_uid.fail.sh