Skip to content

Hardened

arnaud gaboury edited this page Sep 6, 2018 · 16 revisions

Hardened

SELINUX

Security-Enhanced Linux (SELinux) is a mandatory access control (MAC) security mechanism implemented in the kernel.

Distributions such as Red Hat Enterprise Linux and Fedora come with very comprehensive policies to cover a variety of situations. SELinux follows the model of least-privilege more closely. By default under a strict enforcing setting, everything is denied and then a series of exceptions policies are written that give each element of the system (a service, program or user) only the access required to function. If a service, program or user subsequently tries to access or modify a file or resource not necessary for it to function, then access is denied and the action is logged.

Installing SELinux Packages

A number of packages are used in SELinux. Here is a list for Red Hat-based distributions:

policycoreutils (provides utilities for managing SELinux)
policycoreutils-python (provides utilities for managing SELinux)
selinux-policy (provides SELinux reference policy)
selinux-policy-targeted (provides SELinux targeted policy)
libselinux-utils (provides some tools for managing SELinux)
setroubleshoot-server (provides tools for deciphering audit log messages)
setools (provides tools for audit log monitoring, querying policy, and file context management)
setools-console (provides tools for audit log monitoring, querying policy, and file context management)
mcstrans (tools to translate different levels to easy-to-understand format)

Display current selinux status

  • The setenforce command may be used to switch between Enforcing and Permissive modes on the fly but note that these changes do not persist through a system reboot.
# sestatus  
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      31

# getenforce
Enforcing

To make changes persistent through a system reboot, edit the SELINUX= line in /etc/selinux/config for either enforcing, permissive, disabled.

SELinux principles

Security context

A security context, or security label, is the mechanism used by SELinux to classify resources, such as processes and files, on a SELinux-enabled system. This context allows SELinux to enforce rules for how and by whom a given resource should be accessed. A security context is typically shown as a string consisting of three or four words. Each word specifies a different component of the security context, namely the user, role, type, and level of that file or process. Each word is separated by a colon.

The security context for files is stored in the form of an extended file attribute. A file's security context may be viewed using ls with the -Z option. It may be modified using chcon, whose syntax is intentionally similar to chmod.

A file's security context is associated with the file's inode and not the location or directory; this ensures that security contexts will remain the same regardless of whether a file is moved or renamed.

The security context is comprised of four fields: user, role, type, and level. All fields are required, except for the level.

User field

system_u is the default User for processes started during the boot up process. root is the SELinux user that you get when you login at the console as "root". Default new linux user is a unconfined_u SELinux. This default behavior can be changed.

Role field

Roles are used to group security types. So you can specify in policy which roles are able to execute which types.

Type field

This is the heart of SELinux Type Enforcement. Most of the policy rules in SELinux revolve around what subject types have what access to which object types. By convention this component always ends in a _t.

Example

A freshly created user will have his home directory like this:

# ls -alZ /home/MyUser
drwx------. 2 toto wheel unconfined_u:object_r:user_home_dir_t:s0 4.0K Feb  5 15:13 ./
drwxr-xr-x. 5 root root  system_u:object_r:home_root_t:s0         4.0K Feb  5 15:13 ../
-rw-r--r--. 1 toto wheel unconfined_u:object_r:user_home_t:s0       18 Jan  4 09:45 .bash_logout
-rw-r--r--. 1 toto wheel unconfined_u:object_r:user_home_t:s0      193 Jan  4 09:45 .bash_profile
-rw-r--r--. 1 toto wheel unconfined_u:object_r:user_home_t:s0      231 Jan  4 09:45 .bashrc
-rw-r--r--. 1 toto wheel unconfined_u:object_r:user_home_t:s0      658 Aug  9 14:54 .zshrc

semanage fcontext -a -t etc_t -s system_u /etc/freetds.conf.new

Manipulating SELinux user information

Role-Based Access Control (RBAC)

Role-based access control (RBAC) is an approach to restricting system access to authorized users. Because a role depends on the SELinux user, and a Linux user is mapped to a SELinux user, assigning roles begins with mapping a Linux user to a SELinux user.

Following this tutorial we will see how to fine-tune user access.

Semanage login

To manage login mappings, we use the semanage login set of commands.

Create or add is done with -a, remove with -d and modifiy with -m.

NOTE: if you change a mapping for a user that already owns files on the file system, it is very important to reset the context of these files completely (i.e. using -F with restorecon) or set the new SELinux owner and role using chcon.

gabx $ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
gabx $ su
root # semanage login -a -s "staff_u" -r "s0-s0:c0.c1023" gabx
root # semanage login -a -s "root" -r "s0-s0:c0.c1023" root
root # semanage login -l 
Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
gabx                 staff_u              s0-s0:c0.c1023       *
root                 unconfined_u         s0-s0:c0.c1023       *
  • List of SELinux users with their respective acess:

guest_u: This user doesn't have access to X-Window system (GUI) or networking and can't execute su / sudo command.

xguest_u: This user has access to GUI tools and networking is available via Firefox browser.

user_u: This user has more access than the guest accounts (GUI and networking), but can't switch users by running su or sudo.

staff_u: Same rights as user_u, except it can execute sudo command to have root privileges.

system_u: This user is meant for running system services and not to be mapped to regular user accounts.

A few examples

 # semanage login -m -s unconfined_u --range s0-s0:c0.c1023 root
  • Modify mapping for root to be mapped with root user:
root # semanage login -m -s root root
root # semanage login -l 
Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
gabx                 unconfined_u         s0      	       *
root                 root                 s0                   *

NOTE: don't forget to run # restorecon -RF /home/MyUser after any change.

When an admin would like to do system administration tasks they should switch to the sysadm_r role using the -r flag in sudo,

$ sudo -r sysadm_r -i

This can be automated by adding a configuration file under /etc/sudoers.d/, to map the user to a default admin role. This file must name same as the linux user name.

%wheel  ALL=(ALL)       TYPE=sysadm_t   ROLE=sysadm_r   ALL
  • list selinux users and their roles
# semanage user -l

                Labeling   MLS/       MLS/                          
SELinux User    Prefix     MCS Level  MCS Range                      SELinux Roles

guest_u         user       s0         s0                             guest_r
root            user       s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r unconfined_r
staff_u         user       s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r unconfined_r
sysadm_u        user       s0         s0-s0:c0.c1023                 sysadm_r
system_u        user       s0         s0-s0:c0.c1023                 system_r unconfined_r
unconfined_u    user       s0         s0-s0:c0.c1023                 system_r unconfined_r
user_u          user       s0         s0                             user_r
xguest_u        user       s0         s0                             xguest_r
  • See the mapping of Linux accounts to SELinux users:
# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
gabx                 unconfined_u         s0-s0:c0.c1023       *
root                 root                 s0                   *
  • list available SELinux users and roles
$ seinfo -u
.....
$ seinfo -r
.......

We can find here SELinux user capabilities.

The sudo Transition and SELinux Roles

In certain cases, confined users need to perform an administrative task that require root privileges. To do so, such a confined user has to gain a confined administrator SELinux role using the sudo command. The sudo command is used to give trusted users administrative access. When users precede an administrative command with sudo, they are prompted for their own password. Then, when they have been authenticated and assuming that the command is permitted, the administrative command is executed as if they were the root user.

As shown in Fedora documentation, only the staff_u and sysadm_u SELinux confined users are permitted to use sudo by default. When such users execute a command with sudo, their role is changed based on the rules specified in the /etc/sudoers configuration file or in a respective file in the /etc/sudoers.d/ directory if such a file exists.

  • Create a new configuration file with the same name as your Linux user in the /etc/sudoers.d/ directory and add the following string to it:
# echo "linux_user ALL=(ALL) TYPE=administaror_t ROLE=administrator_r /bin/sh " > /etc/sudoers.d/linux_user

Configuration

Strict policy is a system where everything is denied by default and must specify allow rules to grant privilege.

Targeted policy (default in fedora) is a system where processes by default are unconfined. By default user processes run in unconfined and system processes run in initrc_t.

All the magic of selinux starts in the /etc/selinux/config file. Default is:

SELINUX=enforcing
SELINUXTYPE=targeted

When SELinux prevents any software from accessing a particular resource, for example when Firefox is denied access to /etc/shadow, it generates a message and logs it in /var/log/audit/audit.log

OS commands

Z is your friend

semanage context for file & directory

When using targeted policy, changes are written to files located in the /etc/selinux/targeted/contexts/files/

  • The file_contexts file specifies default contexts for many files, as well as contexts updated via semanage fcontext.
  • The file_contexts.local file stores contexts to newly created files and directories not found in file_contexts.

See the context:

# ls -alZ myDir
  • Set a file back to the system defaults
# restorecon

TIP: when copying files or directories, add option to keep SELinux contextes $ cp --preserve=context ...

Modify context temporary

The context changes remain until the file is relabeled

Change SELinux user for a file: # chcon --user <SELinux user> <filename>

Change SELinux role for a file: # chcon --role <SELinux role> <filename>

Change SELinux type for a file: # chcon --type <SELinux types> <filename>

TIP use -R for a whole directory

Modify context persistently

We apply the command semanage fcontext -a --seuser (--type) <SELinux user (type)> <filename (dirname)> and then run restorecon <filename (dirname)

  • Modify context to all elements of a directory
# semanage fcontext -a -t options "directory-path/dir(/.*)?"
# restorecon -R -v directory-path/dir
# ls -aZ directory-path/dir

or

# chcon -R -t ssh_home_t .ssh
  • Example

The below example has been done following this stackexchange post

We want to change user context to system_u for this file:

# ls -alZ /run
srw-rw----.  1 root           docker         system_u:object_r:container_var_run_t:s0         0 Mar  1 12:09 docker.sock=
# semanage fcontext -m -t container_var_run_t -s system_u /var/run/docker.sock

NOTE:

  • for a whole directory, use "Path/To/MyDir(/.*)?"
  • use -a instead of -m when you add a new context

Then verify in /etc/selinux/targeted/contexts/files/file_contexts.local you can see the above line. If yes, your command has been taken into account. Thus run:

# restorecon -vF /var/run/docker.sock
Relabeled /var/run/docker.sock from ... to ...

Allowing Access to a Port

By default, the SELinux policy will only allow services access to recognized ports associated with those services. This service name table gives port number for a specific service.

  • list ports
# semanage port -l

Add http port 81:

# semanage port -a -t http_port_t -p tcp 81 

SELinux Booleans

List all available booleans on the system:

# semanage boolean -l | less

and getsebool -a list them with their actual setting. See this Centos wiki for a list and short explanation.

Logs and policy rules

SELinux is able to log everything.

SELinux log is /var/log/audit/audit.log. We use the audit2allow and audit2why commands to get a human readable output.

audit2allow - generate SELinux policy allow/dontaudit rules from logs of denied operations

audit2why - translates SELinux audit messages into a description of why the access was denied (audit2allow -w)

# audit2why -i /var/log/audit/audit.log | less

Generate a report of alerts:

# sealert -a /var/log/audit/audit.log > MyReport.txt

Disecting the AVC denial

Other tools

ausearch
#ausearch -m avc --start recent
Sealert

Example:

$ journalctl | grep selinux
......
715909:Mar 02 18:38:24 dahlia setroubleshoot[21219]: SELinux is preventing su from bind access on the netlink_selinux_socket Unknown. For complete SELinux messages run: sealert -l 35dd962d-158f-4a30-b398-e89dbb0deae6
.....
# sealert -l 35dd962d-158f-4a30-b398-e89dbb0deae6

Troubleshoot

test the process without SELinux

As described in this fedora article, a quick and good way to see if SELinux is the culprit of an error is this one:

# setenforce 0

and try the process again, in another terminal if needed. See if the error persists. Then run setenforce 1 to return to enforcing mode.

find error

Run the following command to find errors in the last 10 minutes.

# ausearch -m AVC,USER_AVC,SELINUX_ERR -ts recent

Rsync and Selinux

Keep attributes whith rsync

When using rsync to backup and restore, use the following options to keep SELinux contexts:

# rsync -AX ...

list of booleans

# getsebool -a | grep rsync
188:postgresql_can_rsync --> off
202:rsync_anon_write --> off
203:rsync_client --> off
204:rsync_export_all_ro --> off
205:rsync_full_access --> off

allow rsync to export any files/directories read only, you must turn on the rsync_export_all_ro boolean: setsebool -P rsync_export_all_ro 1

allow rsync to have a rw access of all the files (except security files): setsebool -P rsync_full_access 1

After the changes, then:

# getsebool -a | grep rsyn        
188:postgresql_can_rsync --> off
202:rsync_anon_write --> off
203:rsync_client --> off
204:rsync_export_all_ro --> on
205:rsync_full_access --> on

Switch to permissive

You’re using SELinux in enforcing mode. The enforcing mode is the normal and expected way to run Fedora. If you’ve disabled SELinux, you’ll need to enable it. Edit the /etc/sysconfig/selinux file to set SELINUX=permissive. Using permissive mode first ensures that any radical problems can still be fixed automatically by the following commands. Then do the following:

# fixfiles -F onboot

reboot

Once the machine has rebooted, you can switch to enforcing mode:

sudo setenforce 1

Cryptography

Diffie-Hellman

The Diffie-Hellman algorithm provides the capability for two communicating parties to agree upon a shared secret between them. Its an agreement scheme because both parties add material used to derive the key (as opposed to transport, where one party selects the key). The shared secret can then be used as the basis for some encryption key to be used for further communication.

Diffie-Hellman in SSL/TLS

Current real-world deployment of Diffie-Hellman is less secure than previously believed.There are three recommendations for correctly deploying Diffie-Hellman for TLS:

Generate a Strong, Unique Diffie Hellman Group

# cd /etc/pki/tls/certs
# openssl dhparam -out dhparams.pem 2048
# ls
-rw-rw-r-- 1 root root   424 Jun 29 12:23 dhparams.pem

Safe Cipher Suites for Nginx

To be placed in /etc/nginx/ssl/ssl.conf :

ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

ssl_prefer_server_ciphers on;

Specify the Diffie Hellman parameters

Add this line in /etc/nginx/ssl/ssl.conf:

ssl_dhparam  /etc/pki/tls/certs/dhparams.pem;
  • Deploy (Ephemeral) Elliptic-Curve Diffie-Hellman (ECDHE)

Iptables

In most common use cases will only use two of these: filter and nat. Tables consist of chains, which are lists of rules which are followed in order. The default table, filter, contains three built-in chains: INPUT, OUTPUT and FORWARD which are activated at different points of the packet filtering process. The nat table includes PREROUTING, POSTROUTING, and OUTPUT chains.

iptables are managed by a systemd service iptables On fedora, one has to install iptables-services package for the systemd files and disable firewalld.

# systemctl mask firewalld.service
Created symlink from /etc/systemd/system/firewalld.service to /dev/null.

To check open ports, run:

# netstat -antp

TIP: start with an empty table like this:

# touch /etc/sysconfig/empty_rules
# iptables-restore < /etc/sysconfig/empty_rules 

Chains

  1. INPUT the default chain is used for packets addressed to the system. Use this to open or close incoming ports (such as 80,25, and 110 etc) and ip addresses / subnet (such as 202.54.1.20/29).
  2. OUTPUT the default chain is used when packets are generating from the system. Use this open or close outgoing ports and ip addresses / subnets.
  3. FORWARD the default chains is used when packets send through another interface. Usually used when you setup Linux as router. For example, eth0 connected to ADSL/Cable modem and eth1 is connected to local LAN. Use FORWARD chain to send and receive traffic from LAN to the Internet.

Tables

There are filter, raw, mangle and security tables. Filter is the default one when passing commands.

-Raw is used only for configuring packets so that they are exempt from connection tracking.

-Filter is the default table, and is where all the actions typically associated with a firewall take place.

-Nat is used for network address translation (e.g. port forwarding).

-Mangle is used for specialized packet alterations.

-Security is used for Mandatory Access Control networking.

Read this article for more details.

Drop and Reject

As a general rule, use REJECT when you want the other end to know the port is unreachable' use DROP for connections to hosts you don't want people to see.

The difference is that the REJECT target sends a reject response to the source, while the DROP target sends nothing. DROP does nothing at all with the packet. It does not get forwarded to a host, it does not get answered. The manpage of IPtables says it drops the packet on the floor, i.e. it does nothing with the packet.

REJECT differs to DROP that it does send a packet back, but the answer is as if a server is located on the IP, but does not have the port in a listening state. IPtables will sent a RST/ACK in case of TCP or with UDP an ICMP destination port unreachable.

Usually, you want to ignore probes from attackers to certain ports, by which I mean you do not want to send back 'connection refused'. 'Connection refused' means: 'there is a server here', and possibly gives away more information, whereas dropping a packet doesn't give away clues about software versions, possible vulnerabilities or even the fact that a server is listening at you IP.

If you're trying to hide the fact that a port is open, you should mimic the behavior that would occur if the port was not open:

TCP: -p tcp -j REJECT --reject-with tcp-reset
UDP: -p udp -j REJECT --reject-with icmp-port-unreachable

Target

Target Meanings

  1. the target ACCEPT means allow packet.
  2. the target REJECT means to drop the packet and send an error message to remote host.
  3. the target DROP means drop the packet and do not send an error message to remote host or sending host.

States

There are three states for our traffic:

NEW, ESTABLISHED, RELATED.

This article explains the meaning of each one.

Editing rules

we have to set the default policy for the INPUT chain to DROP in case something somehow slips by our rules. Dropping all traffic and specifying what is allowed is the best way to make a secure firewall

Rules are written in the configuration file /etc/sysconfig/iptables. Rules can be added either by appending a rule to a chain or inserting them at a specific position on the chain.

For practical reasons, we store various iptables named according their complexity. The current one is /etc/sysconfig/iptables. Then we have:

  • /etc/sysconfig/iptables.basic which is a basic one
  • /etc/sysconfig/iptables.statefull which is rather similar as the one described in the Arch stateful firewall wiki
  • /etc/sysconfig/iptables.complex which is nearly a work in progress with lots of hardening tricks.

Uses the -I option for insertion, -A to append, -R to replace (iptables -R INPUT 9: here we replace line 9 rule). Using a rule with the insertion option will add it to the beginning of a chain and will be applied first. To indicate a specific placement in the chain, you may also use a number with the -I option.

TIPS:

  • Because iptables processes rules in linear order, from top to bottom within a chain, it is advised to put frequently-hit rules near the start of the chain.

  • when working remotely, and to avoid being blocked outside the server by a bad rule, best is to run the command iptables-apply -t 45 /etc/sysconfig/iptables. If you don't answer yes after 45 seconds (which is the case when the connection drops), the new rule(s) won't apply.

First, we will make sure we start with an empty tables and we disable the service.

# systemctl disable iptables
# iptables -F
# iptables -nvL --line-numbers
-----------------
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

When editing manually iptables, run the following command to apply the new edits:

# iptables-restore < /etc/sysconfig/iptables

Then, step by step, we will add basic rules. Working remotely, we want to avoid being logged off the machine with no more access!

Very basic rules

We first drop forward Packets

iptables --policy FORWARD DROP
  • Allow local programs that use loopback (Unix sockets)
# iptables -A INPUT -i lo -j ACCEPT
  • Usual first rules: allow connection from the remote machine and allow Established and Related Incoming Connections. We put these rules at the beginning because we want to make sure the connections we are already using are matched, accepted, and pulled out of the chain before reaching any DROP rules.
# iptables -A INPUT -s <MyIP> -j ACCEPT
# iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Now see and test the rules:

# iptables -L -nv --line-numbers
# iptables-save > /etc/sysconfig/iptables
# iptables-apply -t 45 /etc/sysconfig/iptables
Explanation

-A INPUT: The -A flag appends a rule to the end of a chain. This is the portion of the command that tells iptables that we wish to add a new rule, that we want that rule added to the end of the chain, and that the chain we want to operate on is the INPUT chain.

-m conntrack: iptables has a set of core functionality, but also has a set of extensions or modules that provide extra capabilities. In this portion of the command, we're stating that we wish to have access to the functionality provided by the conntrack module. This module gives access to commands that can be used to make decisions based on the packet's relationship to previous connections.

--ctstate: This is one of the commands made available by calling the conntrack module. This command allows us to match packets based on how they are related to packets we've seen before. We pass it the value of ESTABLISHED to allow packets that are part of an existing connection. We pass it the value of RELATED to allow packets that are associated with an established connection. This is the portion of the rule that matches our current SSH session.

-j ACCEPT: This specifies the target of matching packets. Here, we tell iptables that packets that match the preceding criteria should be accepted and allowed through.

Creating necessary chains

We create one user defined chain that we will use to open up ports in the firewall to get easier to read and configure iptables rules, and it will result in faster handling of packets as well. The chain can of course have arbitrary name.

# iptables -N TCP_ADMIN
# iptables -N UDP_ADMIN
# iptables -N SSH_ADMIN

NOTE about TCP/UDP TCP provides apps a way to deliver (and receive) an ordered and error-checked stream of information packets over the network. The User Datagram Protocol (UDP) is used by apps to deliver a faster stream of information by doing away with error-checking. See this article for more details.

Now we attach the TCP and UDP chains to the INPUT chain to handle all new incoming connections. Once a connection is accepted by either TCP or UDP chain, it is handled by the RELATED/ESTABLISHED traffic rule. The TCP and UDP chains will either accept new incoming connections, or politely reject them. New TCP connections must be started with SYN packets.

# iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP_ADMIN
# iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP_ADMIN

We reject TCP connections with TCP RESET packets and UDP streams with ICMP port unreachable messages if the ports are not opened. This imitates default Linux behavior (RFC compliant), and it allows the sender to quickly close the connection and clean up.

# iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

For other protocols, we add a final rule to the INPUT chain to reject all remaining incoming traffic with icmp protocol unreachable messages. This imitates Linux's default behavior.

# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

We create a new rule chain to log and drop too many connection attempts. These rules should be at the bottom.

# iptables -N LOG_AND_DROP

Make sure all the remaining incoming connections jump to the LOG_AND_DROP, then LOG and DROP

# iptables -A INPUT -j LOG_AND_DROP
# iptables -A LOG_AND_DROP -m limit --limit 2/min -j LOG --log-prefix "iptables deny: " --log-level 7
# iptables -A LOG_AND_DROP -j DROP

Last, before going further, we drop all traffic to the INPUT chain, delete the rule accepting all connection from the remote machine (too wide), save and test:

# iptables --policy INPUT DROP
# iptables -D INPUT -s <MyIP> -j ACCEPT
# iptables-save > /etc/sysconfig/iptables
# iptables-apply -t 45 /etc/sysconfig/iptables

If new connection is allowed, we have now a very basic table which looks like this:

# cat /etc/sysconfig/IPtables
# Generated by iptables-save v1.6.1 on Mon Jan 29 12:44:58 2018
*raw
:PREROUTING ACCEPT [447:350990]
:OUTPUT ACCEPT [60:10209]
-A PREROUTING -m rpfilter --invert -j DROP
COMMIT
# Completed on Mon Jan 29 12:44:58 2018
# Generated by iptables-save v1.6.1 on Mon Jan 29 12:44:58 2018
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [11:1404]
:SSH_ADMIN - [0:0]
:TCP_ADMIN - [0:0]
:UDP_ADMIN - [0:0]
:LOG_AND_DROP - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP_ADMIN
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP_ADMIN
-A INPUT -j LOG_AND_DROP
-A LOG_AND_DROP -m limit --limit 2/min -j LOG --log-prefix "iptables deny: " --log-level 7
-A LOG_AND_DROP -j DROP
COMMIT
# Completed on Mon Jan 29 12:44:58 2018

More complex rules

  • SSH
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j SSH_ADMIN
# iptables -A SSH_ADMIN -m recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j DROP
# iptables -A SSH_ADMIN -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j DROP
# iptables -A SSH_ADMIN -m recent --name sshbf --set -j ACCEPT

Please note here the use of -I to insert the rules. Up to you to test rules during the process of adding new rules.

  • Accept all new incoming ICMP echo requests, also known as pings
iptables -I INPUT 3 -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT -m comment --comment "Allow Ping"
  • Block null packets.
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
  • reject is a syn-flood attack.
# iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
  • Drop XMAS packets, also a recon packet
# iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

Allow Rsync From a Specific Network (needed to backup the system)

iptables -A TCP_ADMIN -p tcp -s <MY IP> --dport 873 -m state --state NEW,ESTABLISHED -j ACCEPT

Anti-DDoS Rules with the mangle table and the PREROUTING chain

  • Block invalid packages
# iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
  • Block spoofing attacks from local network addresses:
# iptables -t mangle -A PREROUTING -s 224.0.0.0/3 -j DROP
# iptables -t mangle -A PREROUTING -s 169.254.0.0/16 -j DROP
# iptables -t mangle -A PREROUTING -s 172.16.0.0/12 -j DROP
# iptables -t mangle -A PREROUTING -s 192.0.2.0/24 -j DROP
# iptables -t mangle -A PREROUTING -s 192.168.0.0/16 -j DROP
# iptables -t mangle -A PREROUTING -s 10.0.0.0/8 -j DROP
# iptables -t mangle -A PREROUTING -s 0.0.0.0/8 -j DROP
# iptables -t mangle -A PREROUTING -s 240.0.0.0/5 -j DROP
# iptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP

Partition

  • Any directory tree a user should be able to write to (e.g. /home, /tmp) should be on a separate partition and use disk quotas.

  • For extra security, static data can be put on a separate partition that is mounted read-only.

  • When mounting an ext2 partition, you have several options you can apply to the file /etc/fstab. The options are:

    nosuid - Will ignore the SUID bit and make it just like an ordinary file

    noexec - Will prevent execution of files from this partition

    nodev - Ignores devices

Journaled quotas

Enabling

Putting quotas on a file system restricts disk usage on a per-user or per-group basis.

  • Modify /etc/fstab and add usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0 to the partitions to restrict disk usage on.
  • Create the quota files (aquota.user and aquota.group) and place them in the root of the partition with quotas.
  • Create the quota index for all partitions: # quotacheck -vguma
  • Enable the quotas: # quotaon -av

Configuring

  • Edit user quota: # edquota $USER

System settings

  • /etc/securetty

Allows to specify which tty (terminal) devices root is allowed to login to. Comment all lines except tty1 if you are using udev. This will ensure that root only can login once and only on one terminal.

  • /etc/security/limits.conf

Controlling resource usage can be very effective when trying to prevent a local Denial of Service or restricting the maximum allowed logins for a group or user

  • /etc/security/access.conf

This table is used to control who can and cannot login based on user name, group name or host name.

Server certificates

Types of certificates

There are, broadly speaking, three types of SSL certificates that Certificate Authorities issue, each with increasing levels of “identity assurance”.

1- Domain Validated (DV certificates)

one must only proveOrganization Validated” or OV certificates that they control the host or domain to be certified

2- Organization Validated (OV certificates)

One must prove control of the domain using the same mechanisms allowed for DV but must also prove two additional things. First is who the legal entity that controls the domain is. Second is that the requester is acting on behalf of that entity.

3- Extended Validation (EV certificates)

These are logically the same as OV except the requirements that must be met when verifying the legal entity and requestor affiliation are higher

Let’s Encrypt issues only Domain Validated certificates and only issues server certificates. They cannot validate user IDs.

Request validation

Linux kernel

Kernel hardening

Use this kernel config to build a secure kernel.

Grsecurity

All tmp files should be placed under some user-owned private subdirectory in /tmp/. Use the /tmp/user.$USER/ name.chmod 700

  • it fixes a problem where hardened kernels (like grsecurity) disallow programs from running binaries that are placed in directories writeable but someone else then user.

Network

fail2ban

NOTE We prefer sshguard, lighter and simpler to use with fewer features while performing its core function equally well. We keep this section for the record. Fail2ban is a service that monitors logfiles to detect potential intrusion attempts and places bans using a variety of methods. It is a client/server architecture.

The server itself knows nothing about the configuration files. Thus, at start-up, the server is in a "default" state in which no jails are defined. fail2ban-client is the frontend of Fail2ban. It connects to the server socket file and sends commands in order to configure and operate the server.

Fail2ban main configuration file is /etc/fail2ban/jail.conf and contains the declaration of your jails. DO NOT edite this file, instead, create local configuration files at /etc/fail2ban/jail.d/jail.local. Every .conf file can be overridden with a file named .local. The .conf file is read first, then .local, with later settings overriding earlier ones.

See main settings:

# fail2ban-client -d
['set', 'syslogsocket', 'auto']
['set', 'logtarget', '/var/log/fail2ban.log']
['set', 'loglevel', 'INFO']
['set', 'dbpurgeage', 86400]
['set', 'dbfile', '/var/lib/fail2ban/fail2ban.sqlite3']

SSHguard

As there is no Fedora package, we can:

  • build and install is based on this article.
  • download a .rpm package from here Settings have been made following Arch wiki and the above mentioned website. SSHguard can work with many firewall backend. We choose iptables.

The main configuration required is creating a chain named sshguard, where sshguard automatically inserts rules to drop packets coming from bad hosts.

Please refer to this article for iptables writing.

To see what's happening behind SSHguard, run:

# LANG=C journalctl -afb -p info -n100 -o cat
$ journalctl -afb -p info SYSLOG_FACILITY=4 SYSLOG_FACILITY=10

List banned IP:

# iptables --list SSHGUARD --line-numbers --numeric 

Unban:

# iptables --delete sshguard line-number

System maintenance

  • Password Expiration of User
# chage -M 90 -W 10 User <<---- expires in 70 days with 10 days before warning
# chage -l User <<----- list setings for User

Public Key Infrastructure

PKI is a set of roles, policies, and procedures needed to create, manage, distribute, use, store, and revoke digital certificates[1] and manage public-key encryption

TTH design is a three tier structure hierarchy:

Root CA ----> Intermediate CA -----> Signing CA

Glossary

  • Certificate (cert)

The public half of a public/private key pair with some additional metadata about who issued it etc. It may be freely given to anyone.

  • Private Key

A private key can verify that its corresponding certificate/public key was used to encrypt data. It is never given out publicly.

  • Certificate Authority (CA)

A company that issues digital certificates. For SSL/TLS certificates, there are a small number of providers (e.g. Symantec/Versign/Thawte, Comodo, GoDaddy, LetsEncrypt) whose certificates are included by most browsers and Operating Systems. They serve the purpose of a “trusted third party”.

There are three types of CA:

Root CA CA at the root of a PKI hierarchy. Issues only CA certificates. Intermediate CA CA below the root CA but not a signing CA. Issues only CA certificates. Signing CA CA at the bottom of a PKI hierarchy. Issues only user certificates.

  • Certificate Signing Request (CSR)

A file generated with a private key. A CSR can be sent to a CA to request to be signed. The CA uses its private key to digitally sign the CSR and create a signed cert. Browsers can then use the CA’s cert to validate the new cert has been approved by the CA.

  • X.509

A specification governing the format and usage of certificates.

Best practice:

  • use two two distinct keys, one for signing and one for encryption
  • use two openssl config files: one for CSR and one for CA

Digital signature

A digital ID contains information such as your name and email address, the name of the company that issued your digital ID, a serial number, and an expiration date. You usually only have one, like a driver’s license, but you can have multiple for different signing circumstances. Essentially, it proves your identity to people that receive a document that you have signed digitally.

The overall scheme is the following one:

1- create the Certifate Authority 2- create the Certificate Signing Request 3- create the PKCS12 signing certificate

In cryptography, PKCS #12 defines an archive file format for storing many cryptography objects as a single file. It is commonly used to bundle a private key with its X.509 certificate or to bundle all the members of a chain of trust. It is the defacto file format for moving private keys and certificates around. It was defined by RSA and Microsoft in the late 90s and is used by Windows extensively

Create the intermediate pair

An intermediate certificate authority (CA) is an entity that can sign certificates on behalf of the root CA. The root CA signs the intermediate certificate, forming a chain of trust.

We will use the the pair root CA cert and key created by Let's encrypt for thetradinghall.com. The private key, privkey1.pem, is placed inside /storage/development/private and the certificate, cert1.pem, inside directory /storage/development/certs.

This consists of the root key and root certificate. This pair forms the identity of your CA. Typically, the root CA does not sign server or client certificates directly. The root CA is only ever used to create one or more intermediate CAs, which are trusted by the root CA to sign certificates on their behalf. This is best practice. It allows the root key to be kept offline and unused as much as possible, as any compromise of the root key is disastrous.

1- Create the directory structure. The index.txt and serial files act as a flat file database to keep track of signed certificates.

# mkdir /storage/development
# cd /storage/development
# mkdir certs crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
# mkdir /storage/development/intermediate
# cd /storage/development/intermediate
# mkdir certs crl csr newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
# echo 1000 > crlnumber

2- Write the openssl configuration files

User certificates have the user name as the CN, and their email address

Host certificates have the hostname as the CN

Verify the intermediate certificate against the root certificate. An OK indicates that the chain of trust is intact.

$ openssl verify -CAfile certs/ca.cert.pem intermediate/certs/intermediate1.cert.pem
intermediate/certs/intermediate1.cert.pem: OK

Create the certificate chain file

When an application tries to verify a certificate signed by the intermediate CA, it must also verify the intermediate certificate against the root certificate. To complete the chain of trust, create a CA certificate chain to present to the application.

To create the CA certificate chain, concatenate the intermediate and root certificates together. We will use this file later to verify certificates signed by the intermediate CA.

$ cat intermediate/certs/intermediate.cert.pem \
      certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem

Sign Email client certificates

We will be signing certificates using our intermediate CA.

DDoS attacks

https://www.nginx.com/blog/mitigating-ddos-attacks-with-nginx-and-nginx-plus/

A Distributed Denial-of-Service (DDoS) attack is an attempt to make a service, usually a website, unavailable by bombarding it with so much traffic from multiple machines that the server providing the service is no longer able to function correctly because of resource exhaustion.

Typically, the attacker tries to saturate a system with so many connections and requests that it is no longer able to accept new traffic, or becomes so slow that it is effectively unusable.

NGINX and NGINX Plus have a number of features that – in conjunction with the characteristics of a DDoS attack mentioned above – can make them a valuable part of a DDoS attack mitigation solution.

Limiting the Rate of Requests

kernel parameters

Sysctl is a tool for examining and changing kernel parameters at runtime. Systemd only applies settings from /etc/sysctl.d/*.conf and /usr/lib/sysctl.d/*.conf. The parameters available are those listed under /proc/sys/. Settings can be changed through file manipulation or using the sysctl utility

List settings:

# sysctl --system

TCP/IP stack hardening

The following specifies a parameter set to tighten network security options of the kernel for the IPv4 protocol and related IPv6 parameters where an equivalent exists.

/etc/sysctl.d/51-net.conf
-----------------------------
#### ipv4 networking and equivalent ipv6 parameters ####

## TCP SYN cookie protection (default)
## helps protect against SYN flood attacks
## only kicks in when net.ipv4.tcp_max_syn_backlog is reached
net.ipv4.tcp_syncookies = 1

## protect against tcp time-wait assassination hazards
## drop RST packets for sockets in the time-wait state
## (not widely supported outside of linux, but conforms to RFC)
net.ipv4.tcp_rfc1337 = 1

## sets the kernels reverse path filtering mechanism to value 1(on)
## will do source validation of the packet's recieved from all the interfaces on the machine
## protects from attackers that are using ip spoofing methods to do harm
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv6.conf.default.rp_filter = 1
net.ipv6.conf.all.rp_filter = 1

## tcp timestamps
## + protect against wrapping sequence numbers (at gigabit speeds)
## + round trip time calculation implemented in TCP
## - causes extra overhead and allows uptime detection by scanners like nmap
## enable @ gigabit speeds
net.ipv4.tcp_timestamps = 0
#net.ipv4.tcp_timestamps = 1

## log martian packets
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.log_martians = 1

## ignore echo broadcast requests to prevent being part of smurf attacks (default)
net.ipv4.icmp_echo_ignore_broadcasts = 1

## ignore bogus icmp errors (default)
net.ipv4.icmp_ignore_bogus_error_responses = 1

## send redirects (not a router, disable it)
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.send_redirects = 0

## ICMP routing redirects (only secure)
#net.ipv4.conf.default.secure_redirects = 1 (default)
#net.ipv4.conf.all.secure_redirects = 1 (default)
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
net.ipv6.conf.all.accept_redirects=0

OSSEC

OSSEC watches it all, actively monitoring all aspects of Unix system activity with file integrity monitoring, log monitoring, rootcheck, and process monitoring. OSSEC can be installed to monitor just the server it is installed on, which is a local installation in OSSEC parlance. OSSEC can also be used to monitor thousands of other servers, called OSSEC agents. Monitoring of OSSEC agents can be via agent software installed on the agents or via an agentless mode.

Downalod and install:

# wget https://updates.atomicorp.com/channels/atomic/fedora/27/x86_64/RPMS/atomic-release-1.0-21.fc27.art.noarch.rpm
# rpm -Uvh atomic-release-1.0-21.fc27.art.noarch.rpm
# dnf install ossec-hids ossec-hids-server

TIP: visit this page for fedora packages not in official repository.

Configuration

The OSSEC main configuration file is located inside /var/ossec/etc/ directory.

Settings have been made following this digital ocean article and OSSEC local install with rpm. We will learn how to install OSSEC to monitor the Fedora server it is installed on: a local OSSEC installation.install an OSSEC server and an OSSEC agent, and then configure the server and agent so that the server monitors the agent, with the server sending alerts to your email.

The systemd service file is the one from Archlinux.

Here we will configure the OSSEC local agent, as we want only monitor our server.

Test email sending

mail -s "OSSEC test" user@email.com < /dev/null

Find SMTP server

The valid SMTP servers for the provider will be at the end of each listing in the ANSWER section, which should read:

$ dig -t mx gmail.com

;; ANSWER SECTION:
gmail.com.		436	IN	MX	10 alt1.gmail-smtp-in.l.google.com.
gmail.com.		436	IN	MX	40 alt4.gmail-smtp-in.l.google.com.

Disable Uncommon Protocols

The following Protocols will be disabled:

  • Datagram Congestion Control Protocol (DCCP)
  • Stream Control Transmission Protocol (SCTP)
  • Reliable Datagram Sockets (RDS)
  • Transparent Inter-Process Communication (TIPC)
echo "install dccp /bin/false" > /etc/modprobe.d/dccp.conf
echo "install sctp /bin/false" > /etc/modprobe.d/sctp.conf
echo "install rds /bin/false" > /etc/modprobe.d/rds.conf
echo "install tipc /bin/false" > /etc/modprobe.d/tipc.conf

Linux commands to monitor traffic

  • monitor ssh
netstat -ano|grep <PORT>|grep ESTABLISHED

LKRG kernel module

The Linux Kernel Runtime Guard protects system by comparing hashes which are calculated from the most important kernel region / sections / structures with the internal database hashes. Additionally, special efforts have been made to individually protect all extensions of the kernel (modules). To make the project fully functional, the module should be initially loaded on a clean system – e.g. directly after installation or after booting clean system. At this moment it is possible to create a trusted database of hashes

Rsyslog

Rsyslog daemon can be configured to run as a server in order collect log messages from multiple network devices. These devices act as clients and are configured to transmit their logs to a rsyslog server. However, the Rsyslog service can be also configured and started in client mode. This setup instructs the rsyslog daemon to forward log messages to a remote Rsyslog server using the TCP or UDP transport protocols.

We will use this last setup.

Configuration

Rsync and SELinux

Configuration examples

Server side

In our case, the machine will be a server (collect and send logs) and a client (log machine events)

Systemd-journald

There is no longer a default forward from systemd-journal to a running syslog daemon - so in order to gather system logs you either have to turn journald Forward Feature on or use the imjournal module of rsyslog go gather the logs by importing it from the systemd journald.

Here we use first solution:

/etc/rsyslog.conf
-------------------
$ModLoad imjournal

In order to enforce the Rsyslog daemon to act as a log client and route all of locally generated log messages to a remote Rsyslog server, modify the rsyslog configuration file as follows (put the line at the end):

/etc/rsyslog.conf
--------------------
 *. *  @ServerIP:514

Remote host

This is the machine which will recieve the logs

Configure SELinux to allow rsyslog traffic.

# semanage port -l| grep syslog
syslogd_port_t                 udp      514
# semanage port -a -t syslogd_port_t -p tcp 514

Encrypt logs

http://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_summary.html

Snort

Snort is a DevOps tool for security. An open source intrusion prevention system, Snort is capable of real-time traffic analysis and packet logging. Snort boasts more than 500,000 registered users and has been downloaded more than 5 million times, making it the most widely deployed intrusion prevention system in the world.

Xinetd

Libcap-ng

Openscap

R-digest

Fips

Ressources

Clone this wiki locally