Compare commits

..

1 Commits

Author SHA1 Message Date
Juraj Virgovič 73b8d04e7d Merge c2f8f2e42d into a72f5f2123 2024-01-08 16:45:28 +00:00
+17 -285
View File
@@ -44,8 +44,7 @@ An evolving how-to guide for securing a Linux server that, hopefully, also teach
- [The Network](#the-network)
- [Firewall With UFW (Uncomplicated Firewall)](#firewall-with-ufw-uncomplicated-firewall)
- [iptables Intrusion Detection And Prevention with PSAD](#iptables-intrusion-detection-and-prevention-with-psad)
- [Application Intrusion Detection And Prevention With Fail2Ban](#application-intrusion-detection-and-prevention-with-fail2ban)
- [Application Intrusion Detection And Prevention With CrowdSec](#application-intrusion-detection-and-prevention-with-crowdsec)
- [Application Intrusion Detection And Prevention With Fail2Ban](#application-intrusion-detection-and-prevention-with-fail2ban)
- [The Auditing](#the-auditing)
- [File/Folder Integrity Monitoring With AIDE (WIP)](#filefolder-integrity-monitoring-with-aide-wip)
- [Anti-Virus Scanning With ClamAV (WIP)](#anti-virus-scanning-with-clamav-wip)
@@ -518,8 +517,6 @@ SSH is a door into your server. This is especially true if you are opening ports
**Note**: SSH does not like duplicate contradicting settings. For example, if you have `ChallengeResponseAuthentication no` and then `ChallengeResponseAuthentication yes`, SSH will respect the first one and ignore the second. Your `/etc/ssh/sshd_config` file may already have some of the settings/lines below. To avoid issues you will need to manually go through your `/etc/ssh/sshd_config` file and address any duplicate contradicting settings.
**Note:** If you are running OpenSSH 9.1 or later, uncomment the `RequiredRSASize 3072` line in the configuration below. This enforces a minimum RSA key size of 3072 bits and will reject smaller RSA keys during authentication. This only affects RSA keys. If you use ED25519 or ECDSA keys, you are not affected. You can check your key type and size with `ssh-keygen -l -f ~/.ssh/id_rsa`. On older OpenSSH versions, leave the line commented out as it will prevent sshd from starting.
```
########################################################################################################
# start settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
@@ -554,6 +551,9 @@ SSH is a door into your server. This is especially true if you are opening ports
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO
# only use the newer, more secure protocol
Protocol 2
# disable X11 forwarding as X11 is very insecure
# you really shouldn't be running X on a server anyway
X11Forwarding no
@@ -574,24 +574,12 @@ SSH is a door into your server. This is especially true if you are opening ports
UseDNS yes
Compression no
# TCP keepalive is spoofable (runs outside the encrypted channel)
# Use ClientAlive instead (runs inside the encrypted channel)
TCPKeepAlive no
AllowAgentForwarding no
PermitRootLogin no
# don't allow .rhosts or /etc/hosts.equiv
HostbasedAuthentication no
# OpenSSH 9.1 and later
# Enforce a minimum RSA key size of 3072 bits
# https://www.keylength.com/en/compare/
# RequiredRSASize 3072
# https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/115
HashKnownHosts yes
```
1. Then **find and edit or add** these settings, and set values as per your requirements:
@@ -599,8 +587,8 @@ SSH is a door into your server. This is especially true if you are opening ports
|Setting|Valid Values|Example|Description|Notes|
|--|--|--|--|--|
|<a name="AllowGroups"></a>**AllowGroups**|local UNIX group name|`AllowGroups sshusers`|group to allow SSH access to||
|**ClientAliveCountMax**|number|`ClientAliveCountMax 3`|maximum number of client alive messages sent without response||
|**ClientAliveInterval**|number of seconds|`ClientAliveInterval 15`|timeout in seconds before a response request||
|**ClientAliveCountMax**|number|`ClientAliveCountMax 0`|maximum number of client alive messages sent without response||
|**ClientAliveInterval**|number of seconds|`ClientAliveInterval 300`|timeout in seconds before a response request||
|**ListenAddress**|space separated list of local addresses|<ul><li>`ListenAddress 0.0.0.0`</li><li>`ListenAddress 192.168.1.100`</li></ul>|local addresses `sshd` should listen on|See [Issue #1](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/1) for important details.|
|**LoginGraceTime**|number of seconds|`LoginGraceTime 30`|time in seconds before login times-out||
|**MaxAuthTries**|number|`MaxAuthTries 2`|maximum allowed attempts to login||
@@ -639,8 +627,8 @@ SSH is a door into your server. This is especially true if you are opening ports
> x11displayoffset 10
> maxauthtries 2
> maxsessions 2
> clientaliveinterval 15
> clientalivecountmax 3
> clientaliveinterval 300
> clientalivecountmax 0
> streamlocalbindmask 0177
> permitrootlogin no
> ignorerhosts yes
@@ -1001,7 +989,6 @@ Many security protocols leverage the time. If your system time is incorrect, it
#### How It Works
NTP stands for Network Time Protocol. In the context of this guide, an NTP client on the server is used to update the server time with the official time pulled from official servers. Check https://www.pool.ntp.org/en/ for all of the public NTP servers.
> **Note:** Starting with **Debian 13 (Trixie)**, the classic `ntp` package has been removed. Running `sudo apt install ntp` will fail with *"Package ntp has no installation candidate"*. Since this guide only uses NTP as a **client** (to sync the server's clock), the recommended approach on Debian 13+ is to use `systemd-timesyncd`, which is already pre-installed and requires no additional packages. See the [Debian 13+ steps](#debian-13-trixie-and-later-systemd-timesyncd) below.
#### Goals
@@ -1017,76 +1004,6 @@ NTP stands for Network Time Protocol. In the context of this guide, an NTP clien
#### Steps
##### Debian 13 (Trixie) and later: systemd-timesyncd
`systemd-timesyncd` is a lightweight SNTP client that is already included in Debian. Unlike the full `ntpd` daemon, it does not listen on any port, which makes it a smaller attack surface. For the purposes of this guide - keeping your server's clock in sync - it is all you need.
1. Enable NTP synchronization:
``` bash
sudo timedatectl set-ntp true
```
1. Verify it is working:
``` bash
timedatectl status
```
You should see `NTP service: active` and `System clock synchronized: yes` in the output.
1. Configure trusted NTP servers. Make a backup of the configuration file and then edit it:
``` bash
sudo cp --archive /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf-COPY-$(date +"%Y%m%d%H%M%S")
```
Edit `/etc/systemd/timesyncd.conf` and uncomment/set the `[Time]` section:
```
[Time]
NTP=pool.ntp.org
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org
```
[For the lazy](#editing-configuration-files---for-the-lazy):
``` bash
sudo sed -i -r -e "s/^#?NTP=.*$/NTP=pool.ntp.org # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/systemd/timesyncd.conf
sudo sed -i -r -e "s/^#?FallbackNTP=.*$/FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/systemd/timesyncd.conf
```
1. Restart the service to apply the changes:
``` bash
sudo systemctl restart systemd-timesyncd
```
1. Check the synchronization status:
``` bash
timedatectl timesync-status
```
> ```
> Server: 108.61.56.35 (pool.ntp.org)
> Poll interval: 32s (min: 32s; max: 34min 8s)
> Leap: normal
> Version: 4
> Stratum: 2
> Reference: C342F10A
> Precision: 1us (2^0)
> Root distance: 24.054ms (max: 5s)
> Offset: +2.156ms
> Delay: 48.567ms
> Jitter: 1.452ms
> Packet count: 3
> ```
##### Debian 12 (Bookworm) and earlier: ntp package
> **Note:** These steps apply to **Debian 12 and earlier** only. On Debian 13+, the `ntp` package is no longer available -- use the [systemd-timesyncd steps](#debian-13-trixie-and-later-systemd-timesyncd) above instead.
1. Install ntp.
On Debian based systems:
@@ -1657,7 +1574,7 @@ You can create rules by explicitly specifying the ports or with application conf
sudo ufw default deny incoming comment 'deny all incoming traffic'
```
1. Obviously we want SSH connections in. Using limit instead of allow will automatically deny connections from an IP address if it attempts to initiate 6 or more connections within a 30-second window:
1. Obviously we want SSH connections in:
``` bash
sudo ufw limit in ssh comment 'allow SSH connections in'
@@ -1950,7 +1867,7 @@ And, since we're already using [UFW](#ufw-uncomplicated-firewall) so we'll follo
-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
```
**Note**: We're adding a log prefix to all the iptables logs. We'll need this for [separating iptables logs to their own file](#separate-iptables-log-file).
**Note**: We're adding a log prefix to all the iptables logs. We'll need this for [seperating iptables logs to their own file](#ns-separate-iptables-log-file).
For example:
@@ -2179,192 +2096,6 @@ fail2ban-client set sshd unbanip 192.168.1.100
([Table of Contents](#table-of-contents))
### Application Intrusion Detection And Prevention With CrowdSec
#### Why
UFW tells your server what doors to board up so nobody can see them, and what doors to allow authorized users through. PSAD monitors network activity to detect and prevent potential intrusions -- repeated attempts to get in.
CrowdSec is similar to Fail2Ban in that it monitors the logs of your applications (like SSH and Apache) to detect and prevent potential intrusions. However, CrowdSec is coupled with a community that shares threat intelligence back to CrowdSec to then distribute a Community Blocklist to all users.
#### How It Works
CrowdSec monitors the logs of your applications (like SSH and Apache) to detect and prevent potential intrusions. It will monitor network traffic/logs and prevent intrusions by blocking suspicious activity (e.g. multiple successive failed connections in a short time-span). Once a malicious IP is detected, it will be added to your local decision list and threat information is shared with CrowdSec to update the Community Blocklist on malicious IP addresses. Once an IP address hits a certain threshold of malicious activity, it will be automatically propogated to all other CrowdSec users to proactively block.
#### Goals
- network monitoring for suspicious activity with automatic banning of offending IPs
#### Notes
- As of right now, the only thing running on this server is SSH so we'll want CrowdSec to monitor SSH and ban as necessary.
- As you install other programs, you'll need to install additional collections and configure the appropriate acquisitions.
#### References
- https://www.crowdsec.net/
- [Read how CrowdSec curates the Community Blocklist](https://www.crowdsec.net/our-data)
- [Read what threat intelligence is shared with CrowdSec](https://docs.crowdsec.net/docs/next/central_api/intro#signal-meta-data)
- https://docs.crowdsec.net/
#### Steps
1. Install CrowdSec Security Engine. (IDS)
On any linux distro (including Debian based systems)
Install the CrowdSec repository:
``` bash
curl -s https://install.crowdsec.net | sudo sh
```
Install the CrowdSec Security Engine:
``` bash
sudo apt install crowdsec
```
> [!TIP]
> if `curl | sh` is not your thing, you can find additional install methods [here](https://docs.crowdsec.net/u/getting_started/installation/linux).
By default whilst CrowdSec is installing the Security Engine it will auto-discover your installed applications and install the appropriate parsers and scenarios for them. Since we know most Linux servers are running ssh out of the box CrowdSec will automatically configured this for you.
2. Install a Remediation Component. (IPS)
CrowdSec by itself is a detection engine, since in most modern infrastructures you may have an upstream firewall or WAF, CrowdSec will not block the IP addresses by itself. You can install a Remediation Component to block the IP addresses detected by CrowdSec.
```bash
sudo apt install crowdsec-firewall-bouncer-iptables
```
> [!TIP]
> If your installation of UFW is not using `iptables` as the backend, you can alternatively install `crowdsec-firewall-bouncer-nftables`. There is no difference in the installed binaries, only the configuration file is different.
By default whilst the Remediation Component is installing it will auto-configure the necessary settings to work with the Security Engine if deployed on the same host (and if the security engine is not within a container environment).
3. Check detection and remediation is working as intended:
CrowdSec package comes with a CLI tool to check the status of the Security Engine and the Remediation Component.
```bash
sudo cscli metrics
```
```bash
Acquisition Metrics:
╭────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────╮
│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │
├────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤
│ file:/var/log/auth.log │ 5 │ 4 │ 1 │ 10 │ - │
│ file:/var/log/syslog │ 30 │ - │ 30 │ - │ - │
╰────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯
Local API Decisions:
╭────────────────────────────────────────────┬────────┬────────┬───────╮
│ Reason │ Origin │ Action │ Count │
├────────────────────────────────────────────┼────────┼────────┼───────┤
│ crowdsecurity/http-backdoors-attempts │ CAPI │ ban │ 73 │
│ crowdsecurity/http-bad-user-agent │ CAPI │ ban │ 4836 │
│ crowdsecurity/http-path-traversal-probing │ CAPI │ ban │ 87 │
│ crowdsecurity/http-probing │ CAPI │ ban │ 2010 │
│ crowdsecurity/thinkphp-cve-2018-20062 │ CAPI │ ban │ 88 │
│ crowdsecurity/CVE-2019-18935 │ CAPI │ ban │ 7 │
│ crowdsecurity/CVE-2023-49103 │ CAPI │ ban │ 5 │
│ crowdsecurity/http-admin-interface-probing │ CAPI │ ban │ 91 │
│ ltsich/http-w00tw00t │ CAPI │ ban │ 3 │
│ crowdsecurity/apache_log4j2_cve-2021-44228 │ CAPI │ ban │ 18 │
│ crowdsecurity/nginx-req-limit-exceeded │ CAPI │ ban │ 280 │
│ crowdsecurity/ssh-slow-bf │ CAPI │ ban │ 3412 │
│ crowdsecurity/spring4shell_cve-2022-22965 │ CAPI │ ban │ 1 │
│ crowdsecurity/ssh-cve-2024-6387 │ CAPI │ ban │ 24 │
│ crowdsecurity/CVE-2023-22515 │ CAPI │ ban │ 2 │
│ crowdsecurity/http-cve-2021-41773 │ CAPI │ ban │ 172 │
│ crowdsecurity/netgear_rce │ CAPI │ ban │ 14 │
│ crowdsecurity/ssh-bf │ CAPI │ ban │ 2000 │
│ crowdsecurity/CVE-2022-35914 │ CAPI │ ban │ 1 │
│ crowdsecurity/http-cve-2021-42013 │ CAPI │ ban │ 2 │
│ crowdsecurity/jira_cve-2021-26086 │ CAPI │ ban │ 9 │
│ crowdsecurity/http-sensitive-files │ CAPI │ ban │ 166 │
│ crowdsecurity/http-wordpress-scan │ CAPI │ ban │ 272 │
│ crowdsecurity/CVE-2022-26134 │ CAPI │ ban │ 5 │
│ crowdsecurity/http-generic-bf │ CAPI │ ban │ 7 │
│ crowdsecurity/http-open-proxy │ CAPI │ ban │ 948 │
│ crowdsecurity/http-crawl-non_statics │ CAPI │ ban │ 339 │
│ crowdsecurity/http-cve-probing │ CAPI │ ban │ 5 │
│ crowdsecurity/CVE-2017-9841 │ CAPI │ ban │ 117 │
│ crowdsecurity/CVE-2022-37042 │ CAPI │ ban │ 1 │
│ crowdsecurity/fortinet-cve-2018-13379 │ CAPI │ ban │ 5 │
╰────────────────────────────────────────────┴────────┴────────┴───────╯
Local API Metrics:
╭──────────────────────┬────────┬──────╮
│ Route │ Method │ Hits │
├──────────────────────┼────────┼──────┤
│ /v1/alerts │ GET │ 2 │
│ /v1/decisions/stream │ GET │ 5 │
│ /v1/usage-metrics │ POST │ 2 │
│ /v1/watchers/login │ POST │ 4 │
╰──────────────────────┴────────┴──────╯
Local API Bouncers Metrics:
╭────────────────────────────────┬──────────────────────┬────────┬──────╮
│ Bouncer │ Route │ Method │ Hits │
├────────────────────────────────┼──────────────────────┼────────┼──────┤
│ cs-firewall-bouncer-1729025592 │ /v1/decisions/stream │ GET │ 5 │
╰────────────────────────────────┴──────────────────────┴────────┴──────╯
Local API Machines Metrics:
╭──────────────────────────────────────────────────┬────────────┬────────┬──────╮
│ Machine │ Route │ Method │ Hits │
├──────────────────────────────────────────────────┼────────────┼────────┼──────┤
│ <your_machine_id_will_be_here> │ /v1/alerts │ GET │ 2 │
╰──────────────────────────────────────────────────┴────────────┴────────┴──────╯
Parser Metrics:
╭─────────────────────────────────┬──────┬────────┬──────────╮
│ Parsers │ Hits │ Parsed │ Unparsed │
├─────────────────────────────────┼──────┼────────┼──────────┤
│ child-crowdsecurity/sshd-logs │ 41 │ 4 │ 37 │
│ child-crowdsecurity/syslog-logs │ 35 │ 35 │ - │
│ crowdsecurity/dateparse-enrich │ 4 │ 4 │ - │
│ crowdsecurity/sshd-logs │ 5 │ 4 │ 1 │
│ crowdsecurity/syslog-logs │ 35 │ 35 │ - │
╰─────────────────────────────────┴──────┴────────┴──────────╯
Scenario Metrics:
╭─────────────────────────────────────┬───────────────┬───────────┬──────────────┬────────┬─────────╮
│ Scenario │ Current Count │ Overflows │ Instantiated │ Poured │ Expired │
├─────────────────────────────────────┼───────────────┼───────────┼──────────────┼────────┼─────────┤
│ crowdsecurity/ssh-bf │ 1 │ - │ 1 │ 4 │ - │
│ crowdsecurity/ssh-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │
│ crowdsecurity/ssh-slow-bf │ 1 │ - │ 1 │ 4 │ - │
│ crowdsecurity/ssh-slow-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │
╰─────────────────────────────────────┴───────────────┴───────────┴──────────────┴────────┴─────────╯
```
The above output can be daunting, but it's a good way to check that the Security Engine is reading logs and the Remediation Component is blocking IP addresses. So a quick breakdown of each section:
- **Acquisition Metrics**: This section shows the logs that the Security Engine is reading and parsing. If you see logs in the `Lines unparsed` column, it means the Security Engine is not able to parse the logs. This could be due to a misconfiguration or the logs are not in the expected format.
- **Local API Decisions**: This section shows the decisions that the Security Engine has within the datbase. If you see logs in the `Count` column, it means the Security Engine has detected malicious activity and has blocked the IP address.
- Orgin: This is where the decision came from. In this case, it's from the Central API (CAPI).
- **Local API Metrics**: This section shows the number of hits to the Local API. This is the API that the Security Engine uses to communicate with the Remediation Component.
- **Local API Bouncers Metrics**: This section shows the number of hits to the Local API by the Remediation Component.
- **Local API Machines Metrics**: This section shows the number of hits to the Local API by the Security Engine (if you run multiple Security Engine in a centralized setup you can see multiple ID's here).
- **Parser Metrics**: This section shows the parsers that are being used by the Security Engine. If you see logs in the `Unparsed` column, it means the Security Engine is not able to parse the logs. This could be due to a misconfiguration or the logs are not in the expected format.
- **Scenario Metrics**: This section shows the scenarios that are being used by the Security Engine. If you see logs in the `Current Count` column, it means the Security Engine has detected malicious activity and is tracking the IP address.
#### Unban an IP
To unban an IP use this command:
``` bash
cscli decisions delete --ip [IP]
```
`[IP]` is the IP address you want to unban. For example, to unban `192.168.1.100` from SSH you would do:
``` bash
cscli decisions delete --ip 192.168.1.100
```
## The Auditing
### File/Folder Integrity Monitoring With AIDE (WIP)
@@ -3033,12 +2764,11 @@ From [https://cisofy.com/lynis/](https://cisofy.com/lynis/):
On Debian based systems, using CISOFY's community software repository:
``` bash
sudo apt install ca-certificates host
sudo mkdir -p /etc/apt/keyrings
wget -O - https://packages.cisofy.com/keys/cisofy-software-public.key | sudo gpg --dearmor -o /etc/apt/keyrings/cisofy-lynis.gpg
echo "deb [signed-by=/etc/apt/keyrings/cisofy-lynis.gpg] https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list
sudo apt update
sudo apt install lynis
sudo apt install apt-transport-https ca-certificates host
sudo wget -O - https://packages.cisofy.com/keys/cisofy-software-public.key | sudo apt-key add -
sudo echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list
sudo apt update
sudo apt install lynis host
```
1. Update it:
@@ -3559,6 +3289,8 @@ Well I will SIMPLIFY this method, to only output email using Google Mail account
#tls_key_file [file]
#tls_cert_file [file]
tls_certcheck on
tls_force_sslv3 on
tls_min_dh_prime_bits 512
#tls_priorities [priorities]
#dsn_notify (off|condition)
#dsn_return (off|amount)