Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server

Classification:

compliance

Framework:

Control:

Description

The rsyslog daemon should not accept remote messages unless the system acts as a log server. To ensure that it is not listening on the network, ensure any of the following lines are not found in rsyslog configuration files.

If using legacy syntax:

$ModLoad imtcp
$InputTCPServerRun *port*
$ModLoad imudp
$UDPServerRun *port*
$ModLoad imrelp
$InputRELPServerRun *port*

If using RainerScript syntax:

module(load="imtcp")
module(load="imudp")
input(type="imtcp" port="514")
input(type="imudp" port="514")

Rationale

Any process which receives messages from the network incurs some risk of receiving malicious messages. This risk can be eliminated for rsyslog by configuring it not to listen on the network.

Remediation

Shell script

The following script can be run on the host to remediate the issue.

# Remediation is applicable only in certain platforms
if [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ]; then

legacy\_regex='^\s\*\$(((Input(TCP|RELP)|UDP)ServerRun)|ModLoad\s+(imtcp|imudp|imrelp))'
rainer\_regex='^\s\*(module|input)\((load|type)="(imtcp|imudp)".\*$'

readarray -t legacy\_targets < <(grep -l -E -r "${legacy\_regex[@]}" /etc/rsyslog.conf /etc/rsyslog.d/)
readarray -t rainer\_targets < <(grep -l -E -r "${rainer\_regex[@]}" /etc/rsyslog.conf /etc/rsyslog.d/)

config\_changed=false
if [ ${#legacy\_targets[@]} -gt 0 ]; then
 for target in "${legacy\_targets[@]}"; do
 sed -E -i "/$legacy\_regex/ s/^/# /" "$target"
 done
 config\_changed=true
fi

if [ ${#rainer\_targets[@]} -gt 0 ]; then
 for target in "${rainer\_targets[@]}"; do
 sed -E -i "/$rainer\_regex/ s/^/# /" "$target"
 done
 config\_changed=true
fi

if $config\_changed; then
 systemctl restart rsyslog.service
fi

else
 >&2 echo 'Remediation is not applicable, nothing was done'
fi

Ansible playbook

The following playbook can be run with Ansible to remediate the issue.

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Define Rsyslog Config Lines Regex in Legacy Syntax
 ansible.builtin.set\_fact:
 rsyslog\_listen\_legacy\_regex: ^\s\*\$(((Input(TCP|RELP)|UDP)ServerRun)|ModLoad\s+(imtcp|imudp|imrelp))
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Search for Legacy Config Lines in Rsyslog Main Config File
 ansible.builtin.find:
 paths: /etc
 pattern: rsyslog.conf
 contains: '{{ rsyslog\_listen\_legacy\_regex }}'
 register: rsyslog\_listen\_legacy\_main\_file
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Search for Legacy Config Lines in Rsyslog Include Files
 ansible.builtin.find:
 paths: /etc/rsyslog.d/
 pattern: '\*.conf'
 contains: '{{ rsyslog\_listen\_legacy\_regex }}'
 register: rsyslog\_listen\_legacy\_include\_files
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Assemble List of Config Files With Listen Lines in Legacy Syntax
 ansible.builtin.set\_fact:
 rsyslog\_legacy\_remote\_listen\_files: '{{ rsyslog\_listen\_legacy\_main\_file.files
 | map(attribute=''path'') | list + rsyslog\_listen\_legacy\_include\_files.files
 | map(attribute=''path'') | list }}'
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Comment Listen Config Lines Wherever Defined Using Legacy Syntax
 ansible.builtin.replace:
 path: '{{ item }}'
 regexp: '{{ rsyslog\_listen\_legacy\_regex }}'
 replace: '# \1'
 loop: '{{ rsyslog\_legacy\_remote\_listen\_files }}'
 register: rsyslog\_listen\_legacy\_comment
 when:
 - ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 - rsyslog\_legacy\_remote\_listen\_files | length > 0
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Define Rsyslog Config Lines Regex in RainerScript Syntax
 ansible.builtin.set\_fact:
 rsyslog\_listen\_rainer\_regex: ^\s\*(module|input)\((load|type)="(imtcp|imudp)".\*$
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Search for RainerScript Config Lines in Rsyslog Main Config File
 ansible.builtin.find:
 paths: /etc
 pattern: rsyslog.conf
 contains: '{{ rsyslog\_listen\_rainer\_regex }}'
 register: rsyslog\_rainer\_remote\_main\_file
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Search for RainerScript Config Lines in Rsyslog Include Files
 ansible.builtin.find:
 paths: /etc/rsyslog.d/
 pattern: '\*.conf'
 contains: '{{ rsyslog\_listen\_rainer\_regex }}'
 register: rsyslog\_rainer\_remote\_include\_files
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Assemble List of Config Files With Listen Lines in RainerScript
 ansible.builtin.set\_fact:
 rsyslog\_rainer\_remote\_listen\_files: '{{ rsyslog\_rainer\_remote\_main\_file.files
 | map(attribute=''path'') | list + rsyslog\_rainer\_remote\_include\_files.files
 | map(attribute=''path'') | list }}'
 when: ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Comment Listen Config Lines Wherever Defined Using RainerScript
 ansible.builtin.replace:
 path: '{{ item }}'
 regexp: '{{ rsyslog\_listen\_rainer\_regex }}'
 replace: '# \1'
 loop: '{{ rsyslog\_rainer\_remote\_listen\_files }}'
 register: rsyslog\_listen\_rainer\_comment
 when:
 - ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 - rsyslog\_rainer\_remote\_listen\_files | length > 0
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten

- name: Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
 - Restart Rsyslog if Any Line Were Commented Out
 ansible.builtin.service:
 name: rsyslog
 state: restarted
 when:
 - ansible\_virtualization\_type not in ["docker", "lxc", "openvz", "podman", "container"]
 - rsyslog\_listen\_legacy\_comment is changed or rsyslog\_listen\_rainer\_comment is changed
 tags:
 - NIST-800-53-CM-6(a)
 - NIST-800-53-CM-7(a)
 - NIST-800-53-CM-7(b)
 - configure\_strategy
 - low\_complexity
 - low\_disruption
 - medium\_severity
 - no\_reboot\_needed
 - rsyslog\_nolisten