Ensure rsyslog Does Not Accept Remote Messages Unless Acting As Log Server
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.
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