Hardening on CentOS
Updates
How many security notices, bugfix notices, and enhancement notices are available for your machine?
yum updateinfo
How many security related packages are available for your machine?
yum --security list updates
Mount options
The nodev
mount option prevents special files from being interpreted as character or block devices. The only place legitimate character and block devices should exist on a system is below the /dev
directory on the root partition or within chroot jails built for system services.
The noexec
mount option prevents the direct execution of binaries on the mounted filesystem. Users should not be allowed to execute binaries that exist in temporary areas or on partitions mounted from removable media (such as a USB key). Using this mount option may provide a line of defense against certain types of worms or malicious code.
The nosuid
mount option prevents set-user-id (setUID) and set-group-id (setGID) permissions from taking their normal effect. These permissions allow users to execute binaries and inherit the owner and group privileges of the executable owner/group respectively. Do not permit users to introduce setUID and setGID files into the system from removable media partitions. This mount option isn't required if the noexec
option is in effect on a filesystem.
An example for a three options active:
<device> /<mountpoint> <filesystem> nosuid,noexec,nodev 1 2
Filesystem encryption
Using cryptsetup, you can encrypt partitions and/or logical volumes.
- Format the partition or logical volume for encryption:
cryptsetup luksFormat /dev/<device>
- Open the partition for using it:
cryptsetup luksOpen /dev/device <name>
- Make filesystem on encrypted partition:
mkfs -t ext4 /dev/mapper/<name>
- For unattandent mounting, you can setup a password file:
dd if=/dev/urandom of=<password file> bs=4096 count=1 chmod 0600 <password file> cryptsetup luksAddKey /dev/<device> <password file>
- Add the encrypted partition into /etc/cryptab:
<name> /dev/<device> <password file>
- The /etc/fstab should contain a line like this:
/dev/<device> /<mountpoint> ext4 defaults 1 2
Change attributes
On Ext2 - Ext4 filesystems the chattr
and lsattr
command can be used for changing or listing file attributes. Example command:
- To add an attribute
chattr +i <file>
- To remove an attribute
chattr -i <file>
Attributes
Attribut | Bedeutung |
---|---|
A | Bei Dateien mit diesem Attribut wird das Datum des letzten Zugriffes nicht gespeichert. |
a | Dateien mit diesem Attribut können nur im append-Modus zum Schreiben geöffnet werden. Es kann also nur Inhalt an die Datei dran gehangen werden aber nicht gelöscht oder überschrieben werden. Dieses Attribut kann nur mit Root-Rechten gesetzt und entfernt werden. |
c | Dateien mit diesem Attribut werden automatisch vom Kernel gepackt auf der Platte gespeichert. Wird sie ausgelesen, wird sie automatisch wieder entpackt. Dieses Attribut hat momentan noch keine Auswirkungen auf ext2- und ext3-Dateisystemen. |
D | Wenn ein Ordner dieses Attribut besitzt und verändert wird, werden diese Veränderungen synchron auf die Festplatte geschrieben. |
d | Dateien mit diesem Attribut werden von dem Programm “dump” ignoriert. |
E | Dieses Attribut kann nicht gesetzt werden. Es gibt an, ob eine Datei, die vom Kernel gepackt wurde, einen Kompressions-Fehler besitzt. |
I | Dieses Attribut kann nicht gesetzt werden. Es gibt an, ob ein Ordner über gehashte trees (Bäume) indexiert wird. |
i | Dateien mit diesem Attribut können nicht verändert werden. Sie können nicht gelöscht oder modifiziert werden und man kann keinen harten Link (Hardlink) auf die Datei erstellen. Symbolische Links (Softlinks) sind weiterhin möglich. Dieses Attribut kann nur mit Root-Rechten gesetzt und entfernt werden. |
j | Besitzt eine Datei dieses Attribut, wird ihr ganzer Inhalt erst in das Journal geschrieben bevor es auf die Festplatte geschrieben wird. Es hat nur Auswirkungen auf ext3-Dateisystemen und nur, wenn es im ordered - oder writeback -Modus läuft. Dieses Attribut kann nur mit Root-Rechten gesetzt und entfernt werden. |
s | Wenn eine Datei mit diesem Attribut gelöscht wird, werden seine Daten auf der Festplatte mit Nullen überschrieben. Dieses Attribut hat momentan noch keine Auswirkungen auf ext2- und ext3-Dateisystemen. |
S | Wenn eine Datei dieses Attribut besitzt und verändert wird, werden diese Veränderungen synchron auf die Festplatte geschrieben. |
T | Ein Ordner mit diesem Attribut wird vom Orlov block allocator ![]() |
t | Eine Datei auf der Festplatte wird sich den letzten Block, auf dem sie liegt, nicht mit einer anderen Datei teilen (tail-merging). Dieses Attribut hat momentan noch keine Auswirkungen auf ext2- und ext3-Dateisystemen, da diese generell kein tail-merging unterstützen außer in experimentellen Patches. |
u | Wenn eine Datei mit diesem Attribut gelöscht wird, wird ihr Inhalt gespeichert, so dass ein User sie später wieder herstellen kann. Dieses Attribut hat momentan noch keine Auswirkungen auf ext2- und ext3-Dateisystemen. |
X | Dieses Attribut kann nicht gesetzt werden. Es gibt an, ob eine vom Kernel gepackte Datei auch unentpackt gelesen werden kann. |
Z | Dieses Attribut kann nicht gesetzt werden. Es gibt an, ob eine Datei, die vom Kernel gepackt, wurde einen Fehler besitzt. |
Parameter
Parameter | Bedeutung |
---|---|
-R | Wenn man chattr mit diesem Parameter auf einen Ordner anwendet, werden alle Unterordner und Dateien rekursiv mit dem gewählten Attribut versehen bzw. das Attribut entfernt. |
-V | Dieser Paramter ist der Verbose-Modus und man erhält mehr Meldungen auf dem Screen, wenn man Dateiattribute setzt. |
Managing ACL's
Important: Before you change permissions using ACL, you must make sure the permissons for the file or folder don't allow any user except root
to access or change the file or folder!
chmod 0770 /<folder> chown root:root /<folder>
- Grants read/write/execution permission to user friend
setfacl -m u:dani:rwx /opt/test getfacl test/ # file: opt/test/ # owner: root # group: root user::rwx user:dani:rwx group::r-x mask::rwx other::r-x
- Grants read/execution permission to group users
setfacl -m g::rx /opt/test getfacl /opt/test/ # file: opt/test/ # owner: root # group: root user::rwx user:dani:rwx group::r-x mask::rwx other::r-x
- Grants read/execution permission to group wheel
setfacl -m g:wheel:rx /opt/test getfacl /opt/test/ # file: opt/test/ # owner: root # group: root user::rwx user:dani:rwx group::r-x group:wheel:r-x mask::rwx other::r-x
- Removes the existing ACL for user friend
setfacl -x u:wheel getfacl /opt/test/ getfacl: Removing leading '/' from absolute path names # file: opt/test/ # owner: root # group: root user::rwx user:dani:rwx group::r-x mask::rwx other::r-x
- Changes normal “others” permissions
setfacl -m o::- <filename> getfacl /opt/test/ getfacl: Removing leading '/' from absolute path names # file: opt/test/ # owner: root # group: root user::rwx user:dani:rwx group::r-x mask::rwx other::r--
- Grants user elvis read/write permission to newly created files (and folder) in this directory
setfacl -m d:u:elvis:rw <directory> getfacl <directory> file: . owner: root group: root user::rwx group::r-x other::r-x default:user::rwx default:user:dani:rwx default:group::r-x default:mask::rwx default:other::r-x
Managing Accounts
Password
Usually the password and account ageing is configured in /etc/shadow
. Next picture describes the chage
tool and the shadow
file:
PAM Modules
PAM has a lot of modules usually located in /usr/lib64/security
directory. To show all available pam plugins, use man -k pam
!
Important: If you change anything in pam configuration, test the logins using a new terminal session, this makes sure, you can set back the changes!
Example of SSH daemon pam configuration: /etc/pam.d/sshd
#%PAM-1.0 auth required pam_sepermit.so auth substack password-auth auth include postlogin # Used with polkit to reauthorize users in remote sessions -auth optional pam_reauthorize.so prepare account required pam_nologin.so account include password-auth password include password-auth # pam_selinux.so close should be the first session rule session required pam_selinux.so close session required pam_loginuid.so # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open env_params session required pam_namespace.so session optional pam_keyinit.so force revoke session include password-auth session include postlogin # Used with polkit to reauthorize users in remote sessions -session optional pam_reauthorize.so prepare
Example /etc/pam.d/system-auth
#%PAM-1.0 # This file is auto-generated. # User changes will be destroyed the next time authconfig is run. auth required pam_env.so auth sufficient pam_fprintd.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 500 quiet auth required pam_deny.so account required pam_unix.so account sufficient pam_localuser.so account sufficient pam_succeed_if.so uid < 500 quiet account required pam_permit.so password requisite pam_cracklib.so try_first_pass retry=3 type= password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok password required pam_deny.so session optional pam_keyinit.so revoke session required pam_limits.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so
Next table shows the PAM types:
Type | Description |
---|---|
auth | These rules are checked when someone is authenticating against this application. A user must pass these rules to validate their identity. |
account | account rules verify the properties of the user's account. Items such as account expiration, are configuration files in place to keep users from having a session, etc. are checked by these rules. |
password | Dictates the behavior of what happens when a user tries to change their password from this application's session. These rules do not determine authentication to the application and are checked during run-time of the application if the user is attempting to change their password through a session of the application. |
session | These rules set up other behaviors around the session, or instance of this application. Such things as logging, SELinux properties, device or console ownership, etc. |
Next table shows the control keywords:
Control | Description |
---|---|
required | The user is required to pass, or receive a successful result, from the executable called by this check. If the user fails this check, they may not be authenticated to the application. However, the other rules of this type will still be parsed and executed even though the user has failed their authentication. |
sufficient | The user may or may not pass this check, but if they pass, no other rules of this type are checked. If the user fails this check, the other rules of this type will be used to determine their ability to authenticate through this application. |
optional | The module called by this check may or not be successful. The outcome of the check is immaterial to the user's ability to authenticate to the application. |
include | At this rule, the authentication of this application will open another file and check the rules of the same type in that file. The result of checking the additional rules from the other file determines the success or failure of the include rule itself. |
requisite | Similar to required except that if a user fails a requisite check, the application stops checking any further PAM rules and the application closes its call to PAM. |
PAM cracklib
Argument | Description |
---|---|
minlen | The minimum length required of a password. By default all characters contribute one to the overall length score. However, with the ?credit adjustments an administrator can give some character types more value thereby requiring fewer overall characters to meet the same length. |
lcredit | Amount of credit lower case character contribute to password length. If this value is set to a negative number, it instead denotes the number of lower case characters required to be in an acceptable password. |
ucredit | Amount of credit upper case character contribute to password length. If this value is set to a negative number, it instead denotes the number of upper case characters required to be in an acceptable password. |
dcredit | Amount of credit digit characters contribute to password length. If this value is set to a negative number, it instead denotes the number of digit characters required to be in an acceptable password. |
ocredit | Amount of credit other characters contribute to password length. Other characters are symbols and all characters not included in lower case, upper case, and digit. If this value is set to a negative number, it instead denotes the number of other characters required to be in an acceptable password. |
minclass | The minimum number of different classes that must be present in a proposed password. Classes are: lower case, upper case, digit, and other. |
Login messages
There are two different configurations possible to show a message during login:
Configuration | Description |
---|---|
motd: | Shows the message after successful login (SSH, console or XWindows) |
Configuration | Description |
---|---|
/etc/motd : | Shows the message after successful login (SSH, console or XWindows) |
/etc/issue : | Shows a message in the console, before login |
Lock Accounts with Failed Logins
Using the pam_tally2 plugin, you can lock accounts defined by the plugin parameters. To activate it, you must edit /etc/pam.d/system-auth
and /etc/pam.d/password-auth
files, just add the two lines containing pam_tally2.so
as shown next:
#%PAM-1.0 auth required pam_env.so auth required pam_tally2.so deny=3 unlock_time=180 quiet ... account required pam_tally2.so account required pam_unix.so ...
To show locked users, you can use the pam_tally2
command to show them. To unlock, use this command here:
pam_tally2 --reset -u student
X Windows
Looking at/etc/gconf/schemas/gdm-simple-greeter.schemas'', one may notice a schema with the key ''/schemas/apps/gdm/simple-greeter/disable_restart_buttons
. Below is a copy of the schema from a sample Red Hat Enterprise Linux system:
<schema> <key>/schemas/apps/gdm/simple-greeter/disable_restart_buttons</key> <applyto>/apps/gdm/simple-greeter/disable_restart_buttons</applyto> <owner>gdm-simple-greeter</owner> <type>bool</type> <default>FALSE</default> <gettext_domain>gdm</gettext_domain> <locale name="C"> <short>Disable showing the restart buttons</short> <long>Set to true to disable showing the restart buttons in the login window.</long> </locale> </schema>
From this schema definition an administrator can gather the items needed to pass to a gconftool-2 command to update the back-end gconf database with a change to this setting. From the schema definition, notice the following items:
- applyto :
/apps/gdm/simple-greeter/disable_restart_buttons
- type :
bool
- default :
FALSE
Using gconftool2, you can change the behaviour of Gnome Desktop. Here an example how-to enable a message before user login to Window system:
- Get the banner_message confuration settings from schema XML file
grep -A8 -B2 -P 'banner_message_(text|enable)<' /etc/gconf/schemas/gdm-simple-greeter.schemas
<schema> <key>/schemas/apps/gdm/simple-greeter/banner_message_enable</key> <applyto>/apps/gdm/simple-greeter/banner_message_enable</applyto> <owner>gdm-simple-greeter</owner> <type>bool</type> <default>false</default> <gettext_domain>gdm</gettext_domain> <locale name="C"> <short>Enable showing the banner message</short> <long>Set to true to show the banner message text.</long> </locale> </schema> <schema> <key>/schemas/apps/gdm/simple-greeter/banner_message_text</key> <applyto>/apps/gdm/simple-greeter/banner_message_text</applyto> <owner>gdm-simple-greeter</owner> <type>string</type> <default></default> <gettext_domain>gdm</gettext_domain> <locale name="C"> <short>Banner message text</short> <long>Text banner message to show on the login window.</long> </locale> </schema>
Note: Read the values out from key, type and default!
- Now, you can overwrite the configuration for enabling the greeting banner
gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.defaults --type bool --set /apps/gdm/simple-greeter/banner_message_enable true
- The same for the banner message
gconftool-2 --direct --config-source xml:readwrite:/etc/gconf/gconf.xml.defaults --type string --set /apps/gdm/simple-greeter/banner_message_text "$(cat login_banner.txt)"
Important: The key starts with /schemas/apps/…
will be /apps/…
!
Note: The config source (–config-source
) must start with xml:readwrite:
!
Aide
Aide is a filesystem intrusion system (Advanced Intrusion Detection Environment). You can watch files and folder with it.
Setup of aide:
- Initialize aide database (defaults to
/var/lib/aide/aide.db.new.gz
, but can be changed in configuration)
cp /etc/aide.conf /etc/aide.conf.orig # delete unwanted entries in config! aide --init mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz aide --check
- Config file of aide:
/etc/aide.conf
IPA integration
Server setup
- Prepare server for
ipa-server
package installation
chkconfig NetworkManager off; service NetworkManager stop ... vim /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE="eth0" BOOTPROTO="static" HWADDR="52:54:00:00:00:FA" IPV6INIT="yes" MTU="1500" NM_CONTROLLED="no" ONBOOT="yes" TYPE="Ethernet" UUID="383d9eaa-ac8a-43ff-96d9-fe76e9200877" IPADDR=192.168.0.101 NETMASK=255.255.255.0 GATEWAY=192.168.0.254 DNS1=192.168.0.254 vim /etc/hosts 127.0.0.1 localhost.localdomain localhost ::1 localhost6.localdomain6 localhost6 192.168.0.X+100 serverX.example.com serverX chkconfig network on; service network restart yum -y update selinux-policy-targeted
- Install the package
yum -y install ipa-server
- Configure IPA server (Note the password!)
ipa-server-install --hostname=serverX.example.com -n example.com -r EXAMPLE.COM -p redhat13 -a redhat13 --no-ntp --idstart=630000000 -U
- Restart sshd on the server
- Login into server as admin user using kinit (The
ipa user-find admin
command should list the user!)
kinit admin Password for admin@EXAMPLE.COM: redhat13 ipa user-find admin
Client setup
- You need to install the ipa binaries
yum -y install ipa-client ipa-admintools
- Configure and install the client (
–mkhomedir
is very important!)
ipa-client-install --domain=example.com --server=serverX.example.com --realm=EXAMPLE.COM -p admin -w redhat13 --mkhomedir -U
- Login as admin user using kinit
getent passwd admin getent group admins kinit admin
- Add users
ipa user-add gpyle --first=Gomer --last=Pyle --password ipa user-add cboyle --first=Charles --last=Boyle --password ...
- Add groups
ipa group-add marines --desc=Marines
- Add users to group
ipa group-add-member marines --users=gpyle,cboyle,vcarter
- Create the sudo rules (on the server!)
ipa sudocmd-add --desc "For displaying logs" /usr/bin/tail ipa sudocmdgroup-add --desc "List logs" loglist ipa sudocmdgroup-add-member --sudocmds "/usr/bin/tail" loglist ipa sudorule-add --hostcat "all" loglist-attr ipa sudorule-add-option loglist-attr Sudo Option: !authenticate ipa sudorule-add-user --groups marines loglist-attr ipa sudorule-add-allow-command --sudocmdgroups loglist loglist-attr
- Make password for one user to test
ldappasswd -Y GSSAPI -S -h serverX.example.com uid=sudo,cn=sysaccounts,cn=etc,dc=example,dc=com
- Don't forget to configure
/etc/nsswitch.conf
file for the sudoers configuration, just add following line:
sudoers: files ldap
Rsyslog
- Make sure the NTP time is working fine on all invoked systems!
- Create and change into directory (
ca
)
mkdir ca cd ca
- Create the ca privat key (The certtool is in
gnutls-utils
package!)
certtool --generate-privkey --outfile ca-key.pem
- Crate the ca self signed certificate
certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca.pem The certificate will expire in (days): 3650 Does the certificate belong to an authority? (y/N): y Enter the e-mail of the subject of the certificate: root@desktopX.example.com
- Create the server privat key
certtool --generate-privkey --outfile serverX-key.pem
- Create the server certificate request
certtool --generate-request --load-privkey serverX-key.pem --outfile serverX-request.pem Common name: serverX.example.com Is this a TLS web client certificate? (y/N): y Is this also a TLS web server certificate? (y/N): y
- Create the server certificate
certtool --generate-certificate --load-request serverX-request.pem --outfile serverX-cert.pem \ --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem The certificate will expire in (days): 1000 Is this a TLS web client certificate? (y/N): y Is this also a TLS web server certificate? (y/N): y Enter a dnsName of the subject of the certificate: serverX.example.com
- Copy the server certs to the server to
/etc/rsyslog-keys
folder - Copy the ca.pem file to
/etc/rsyslog-keys
on the client - Create new config file in
/etc/rsyslog.d/server.conf
(on the server), you can get a template from/usr/share/doc/rsyslog*/
. Make sure the AuthMode is set to anon and add the$ModLoad imtcp
line!
# make gtls driver the default $DefaultNetstreamDriver gtls # certificate files $DefaultNetstreamDriverCAFile /etc/rsyslog-keys/ca.pem $DefaultNetstreamDriverCertFile /etc/rsyslog-keys/serverX-cert.pem $DefaultNetstreamDriverKeyFile /etc/rsyslog-keys/serverX-key.pem $ModLoad imtcp # load TCP listener $InputTCPServerStreamDriverMode 1 # run driver in TLS-only mode $InputTCPServerStreamDriverAuthMode anon # client is NOT authenticated $InputTCPServerRun 6514 # listen on port 6514
- Create new config file in
/etc/rsyslogd/client.conf
(on the client), you can get a template from/usr/share/doc/rsyslog*/
. Make sure the AuthMode is set to anon!
# certificate files - just CA for a client $DefaultNetstreamDriverCAFile /etc/rsyslog-keys/ca.pem # set up the action $DefaultNetstreamDriver gtls # use gtls netstream driver $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon # server is NOT authenticated *.* @@(o)serverX.example.com:6514 # send (all) messages
- Create
/var/log/remote
directory - Add following lines into
/etc/rsyslog.d/remote.conf
, you have a template here:
curl file:///usr/share/doc/rsyslog-5.8.10/multi_ruleset.html |grep fromhost
# process remote messages :fromhost-ip, !isequal, "127.0.0.1" /var/log/remote/messages # then discard them :fromhost-ip, !isequal, "127.0.0.1" ~
Important: Never add this config into /etc/rsyslog.conf
, the discard rule does not work there!
Audit
The rules file is in /etc/audit/audit.rule
located.
The trace command is probably useful (Example for date):
autrace /bin/date Waiting to execute: /bin/date Thu Jun 20 11:38:46 CEST 2013 Cleaning up... Trace complete. You can locate the records with 'ausearch -i -p 26472' ausearch --raw -p 26572 | aureport --file -i
Iptables
Using –line-numbers
option is useful, if you have to delete or add a rule on the proper position:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 3563K 3226M f2b-php-url-fopen tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 2 3563K 3226M f2b-apache-overflows tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 3 3563K 3226M f2b-apache-noscript tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 4 3563K 3226M f2b-apache-badbots tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 5 3563K 3226M f2b-apache-auth tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443 6 1520 95864 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 22 match-set f2b-SSH src reject-with icmp-port-unreachable 7 6141K 5818M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 8 1460 137K ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 9 53510 3261K ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 10 479 20364 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 match-set blockednets src reject-with icmp-port-unreachable 11 511 29728 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW tcp dpt:22 12 12626 735K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW tcp dpt:80 13 2994 226K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW tcp dpt:443 14 174 8732 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW tcp dpt:3389 15 5 224 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW tcp dpt:9090 16 11413 862K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
A very basic example script to initialize iptables
:
iptables -F iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT iptables -A INPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT iptables -A INPUT -j LOG iptables -A INPUT -j REJECT
To delete a rule:
iptables -D INPUT 11
To add a rule (insert):
iptables -I INPUT 11