#!/bin/bash
/usr/sbin/service postgresql restart
Ensuite, vous lui permettez d'éxécuter la commande en tant que root en ajoutant la ligne suivante avec `visudo`:
www-uploader ALL=(root) NOPASSWD: /usr/local/bin/postgre_restart.sh
__note:__ Attention ! Si votre commande accepte des arguments issus de l'utilisateur, pensez à bien "blinder" le script afin d'éviter un abus de droits
Vous trouverez bien d'autres options [[https://doc.ubuntu-fr.org/sudoers|ici]].
===== fail2ban en défense contre les accès "brute force" =====
Pour SSH au moins, on recommande systématiquement l'installation de ''apt install fail2ban'' !
Il y a une [[doc:formations:hebergement:serveur:proteger:fail2ban|page dédiée]] à cet outil.
===== portsentry: intercepter les tentatives de scan de ports ======
Cet outil peut s'installer pour repérer et agir contre des outils d'intrusion qui "scannent" les ports habituels servant de vecteurs d'attaque sur un serveur. Presque systématiquement, un client qui essaye de nombreux ports consécutivement "pour voir si ça mord" n'est pas un client normal.
apt install portsentry
ss -tunlp|grep portsentry # pour montrer les ports surveillés par portsentry
Par défaut cet outil ne fait que logguer des événements dans le journal ''/var/log/syslog'', qui pourrait être traité lui-même par ''failtoban'' comme ci-dessus. Mais bien plus efficace, on peut directement configurer ''portsentry'' ainsi que les ports surveillés pour bannir le client. Voyez [[https://le-guide-du-secops.fr/2020/10/12/portsentry-un-outil-pour-contrer-et-bloquer-les-scans-de-ports/|ce tutoriel]] par exemple.
__Note__ je vous conseille d'ajouter une ou plusieurs adresses IP "fiables" dans le fichier ''/etc/portsentry/portsentry.ignore.static'' qui ne seront jamais bannies avant d'activer des réactions plus agressives envers le client.
===== Firewall: restreindre l'accès a des services à des IP connues =====
==== Via le standard iptables ====
On peut utiliser le pare-feu standard assez simplement pour limiter un accès SSH (ici sur le port standard "22") aux deux seules IP sources "11.22.33.44" et "22.33.44.55"
# installation (si besoin)
which iptables >/dev/null || apt install iptables
# règles pour autoriser: iptable fonctionne en "first match" (si ça matche, ça ne va pas plus loin)
iptables -A INPUT -p tcp -s 11.22.33.44 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s 22.33.44.44 --dport 22 -j ACCEPT
# et pour ceux qui n'auront pas matché, on ferme le service:
iptables -A INPUT -p tcp -s 0.0.0.0/0 --dport 22 -j DROP
Attention:
* L'adresse IP d'où vous vous connectez doit être fixe pour que ce soit réaliste. C'est souvent utile d'en mettre une seconde pour le cas imprévu où elle changerait (ex. crash d'un serveur qui serait le seul point d'entrée!)
* Pensez à conserver une seconde console ouverte en SSH lorsque vous modifiez le pare-feu. Cela réduit le risque de se fermer la porte soi-même accidentellement! Ceci dit, certains hébergeurs vous donneront quand même une chance de vous en sortir (ex. scaleway: [[:doc:formations:hebergement:serveur:scaleway#recuperation_bas_niveau|accès console en ligne]]).
* Un ''apt install iptables-persistent'' permet de sauvegarder vos règles de pare-feu entre deux relances du serveur (en général c'est ce que l'on veut, sauf peut être en phase de mise au point!)
==== Via le nouveau ufw ====
Il s'agit d'un système de configuration plus récent que iptables. Il est un peu moins répandu mais il est réputé un peu plus facile à l'usage si l'on ne connait pas déjà iptables. Probablement un bon investissement.
Exemple pour autoriser les clients 10.34.0.* à accéder au service web local:
ufw allow from 10.34.0.0/8 to 10.34.0.1 port 80
Pour lister les règles ''ufw status numbered'' (ce qui permet de retirer une règle avec ''ufw delete N'').
==== Via un serveur filtrant amont ====
Si l'on a un serveur amont, tel qu'un système DMZ, il sera là aussi peut être plus pertinent de filtrer le plus haut possible. C'est généralement le cas si l'on est hébergé sous une forme virtualisée comme chez Scaleway et qu'il s'agit de bloquer des accès. Dans ce cas il sera plus facile encore d'utiliser les [[https://www.scaleway.com/en/docs/how-to-activate-a-stateful-cloud-firewall/|"stateful cloud firewall"]].
Le filtrage opère en effet en amont du serveur: non seulement l'interface web rend la chose plus ergonomique à configurer, mais surtout il est possible de s'en "sortir" si jamais vous avez fait une fausse manipulation et que vous vous êtes fermés la porte vous même ;)
A titre d'exemple, ci-dessous un filtre qui ne permet l'accès à SSH (port 22 standard) qu'en provenance des IP de la gamme ''46.208.*.*''. Les autres seront reboutés par Scaleway avant même que votre serveur ne soit informé de la tentative d'accès. On pourrait même complètement fermer l'accès sauf pour les occasions où l'on veut administrer le serveur.
{{:doc:formations:hebergement:serveur:scaleway_filter_ssh_port.png?600|}}
Cette interface reste cependant très limitée par rapport aux capacités de ''iptables''.
====== Autres éléments de sécurité ======
===== Pare-feu "proxy" =====
C'est un serveur B supplémentaire, situé entre votre serveur A et l'internet, et qui permet de filtrer tous les accès entrant et sortant du serveur A. Ainsi même le ''root'' du serveur A ne pourra rien y faire: cela réduit la chance qu'un système compromis, souvent via le serveur web, ne puisse mettre en place des ouvertures imprévues pour poursuivre et étendre une attaque partielle (ex. un accès telnet).
Là aussi, les [[https://www.scaleway.com/en/docs/how-to-activate-a-stateful-cloud-firewall/|"Stateful Cloud Firewall"]] de Scaleway simplifient la tache complètement, et évitent de devoir installer un serveur supplémentaire.
Pour le web, notons le classique [[https://doc.ubuntu-fr.org/squid|Squid]], un serveur mandataire transparent qui sert aussi de cache, et [[https://en.wikipedia.org/wiki/Privoxy|Privoxy]], un système avancé de filtrage et de réécriture de requètes.
===== apparmor =====
C'est un système de protection qui permet de brider certains exécutables à certains dossiers (ex. interdire à Mysql d'aller ailleurs que dans ''/var/lib/mysql'').
Pour savoir s'il est installé et actif:
service apparmor status
:!: En général, on se rend compte de son impact lorsque l'on change des dossiers par défaut.
Par exemple, si on change l'entrée ''datadir'' dans ''/etc/mysql/mariadb.conf.d/50-server.cnf'' pour placer les données dans ''/home/mysql'' plutôt que par défaut dans ''/var/lib/mysql''... et que "ça ne marche plus", il faudra penser à indiquer le changement de dossier à ''apparmor'' dans le fichier de configuration associé, par exemple via ''/etc/apparmor.d/tunables/alias'' (comme indiqué dans le fichier). Sans cela, ''apparmor'' bloquera ''mysql'' dans sa tentative d'accéder en dehors du dossier prévu!
===== rkhunter =====
Cet outil vérifie la présence (enfin, l'absence!) de "rootkits", typiquement des chevaux de Troie, vers et autres malware qui sont des moyens techniques pour les pirates de véroler et de profiter de votre serveur une fois rentrés. On peut aussi citer [[https://github.com/Tripwire/tripwire-open-source|Tripwire]] dans la même veine.
:!:''rkhunter'' est un moyen de vérifier **l'intégrité** de votre serveur mais pas un remède. S'il comporte effectivement un rootkit il est compromis et il faudra réinstaller le serveur (la "dépollution" est difficile et extrêmement risquée). Si vous devez réinstaller un serveur compris, faites très attention aux données que vous migrez, et évitez tout exécutable ou script qui pourraient avoir été corrompus ou cachés dans vos données et projets (et donc re-véroler votre nouveau serveur).
apt install rkhunter
Mettez à jour sa base de signatures avec:
rkhunter --propupd
Dans ''/etc/rkhunter.conf.local'' ajoutez la ligne ''PKGMGR=DPKG'', ainsi que ''ALLOW_SSH_ROOT_USER=without-password'' si vous avez autorisé un accès SSH en root via clé ssl sur votre machine, afin d'éviter deux alertes par défaut.
Enfin, lancez une analyse de votre système. C'est une chose à faire régulièrement:
rkhunter --checkall
__Note__: je vous conseille de reconfigurer la ligne ''APT_AUTOGEN="yes"'' dans ''/etc/default/rkhunter''. Cela provoque une prise en compte (via une mise à jour automatique) des installations et mises à jour que vous feriez par la suite avec ''apt''. Inversement, ne mettez pas ''APT_AUTOGEN'' à ''yes'' si vous êtes paranoïaques, pour détecter des mises à jour dans votre dos par exemple. Vous aurez alors à exécuter la commande ''rkhunter %%--%%propupd'' précédente à chaque mise à jour logicielle de votre serveur.
Consultez internet s'il y a la moindre alerte, même s'il se peut que ce soit un "faux positif".
Le journal détaillé du ''%%--checkall%%'' se retrouve dans le fichier ''/var/log/rkhunter.log''.
====== Outils et pratiques à tendance paranoiaques ======
La sécurité est sans fin. Si vous avez des serveurs particulièrement sensibles (données bancaires, etc) vous pouvez regarder ces outils et techniques:
===== Lynis =====
Comme ''rkhunter'' ci dessus, [[https://cisofy.com/lynis/|lynis]] est un autre outil de vérification d'intégrité plus avancé. Il utilise les outils existant sans demander des installations supplémentaires: plus il en trouve et plus il fait de tests (une approche non invasive intéressante, puisqu'il n'implique pas d'autres outils):
cd
git clone https://github.com/CISOfy/lynis # version plus récente qu'avec "apt install lynis"
cd lynis; ./lynis audit system
:!: il teste bien davantage de choses que ''rkhunter'' et requiert une compréhension plus complète des systèmes linux pour être réellement exploitable, jusqu'au renforcement du kernel Linux (avis aux curieux!).
Inversement, il fait des suggestions directes pour les éléments qui lui semblent à renforcer (attention à ne pas le faire à l'aveugle, certaines d'entre elles ne sont pas du tout anodines!)
===== Autres outils de scan =====
Il existe de nombreux autres optils, ce deux-là sont assez classiques, et disponibles en paquets ''apt'' sous Debian/Ubuntu:
* [[https://manpages.debian.org/testing/debsecan/debsecan.1.en.html|debsecan]] va vous lister tous les codes [[https://cve.mitre.org/cve/search_cve_list.html|CVE]] de votre installation. Ce sont des failles de sécurités qui sont référencées officiellement au niveau mondial. Notez que j'attend encore de voir un serveur avec une liste vide !
* ''nmap'' est un petit outil très performant:
* ''nmap -sT 192.168.0.0/24'' scanne les ports ouverts sur les appareils du réseau 192.168.0.*
* ''nmap --script vuln
#!/bin/bash
LOCAL_PORT=22
PUBLIC_PORT=22123
DURATION=3600
if [[ "${QUERY_STRING}" = $(/bin/date +%H) ]]; then
printf "Status: 200 OK\r\nContent-Type: text/html\r\n\r\n"
echo '☠ '
/usr/local/bin/openport.sh ${LOCAL_PORT} ${REMOTE_ADDR} ${PUBLIC_PORT} ${DURATION}
echo '
'
else
printf "Status: 400 Bad Request\r\nContent-Type: text/html\r\n\r\n"
echo "404 Not Found 404 Not Found
nginx/1.14.2 "
fi
Si l'heure passée correspond bien à l'heure en cours sur le serveur, le CGI fera appel à un second script ''/usr/local/bin/openport.sh''. Ce dernier utilise ''socat'' afin d'ouvrir et de rediriger pendant une heure le port externe accessible sur 22123 vers le port interne 22. On contourne donc bien la restriction de SSH qui n'écoute que localement!
#!/bin/bash -feu
set -o pipefail
# Opens a local port to the outside IP, for a given amount of time
# openport.sh LOCAL_PORT IP DPORT TIMEOUT
# Example:
# openport.sh 20 82.64.183.141 2020 240
LOCAL_PORT=${1}
REMOTE_IP=${2}
PUBLIC_PORT=${3}
TIMEOUT=${4-600}
fail() { echo "$@"; exit 1; }
# Avoid shell injection
[[ ! ${LOCAL_PORT} =~ ^[0-9]+$ ]] && fail "Illegal local port"
[[ ! ${REMOTE_IP} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && fail "Illegal IP"
[[ ! ${PUBLIC_PORT} =~ ^[0-9]+$ ]] && fail "Illegal remote port"
# Kill previous if any, and spawn with timeout
ps aux | grep "timeout.* socat TCP-LISTEN:$PUBLIC_PORT" | awk '{print $2}' | xargs -r kill 2>/dev/null || true
nohup timeout ${TIMEOUT} socat TCP-LISTEN:${PUBLIC_PORT},fork,range=${REMOTE_IP}/32 TCP:127.0.0.1:${LOCAL_PORT} /dev/null &
echo "IP ${REMOTE_IP} can now access local port ${LOCAL_PORT} via public port ${PUBLIC_PORT} for ${DURATION} seconds."
:!: si vous vouliez utiliser un port externe inférieur à 1000, ou encore si vous vouliez utiliser ''iptables'' pour mieux gérer la chose, il faudra que le CGI accède en root au script. Utilisez alors ''sudo'' pour l'appel après avoir ajouté cette ligne avec ''visudo'':
www-data ALL=(ALL) NOPASSWD: /usr/local/bin/openport.sh
===== Défenses actives =====
Ce sont des techniques parfois contestables, mais intéressantes, qui cherchent à //riposter// aux attaques sur votre serveur.
==== Port scan ====
Il s'agit ici de bannir un attaquant qui cherche à trouver tous les ports ouverts sur votre serveur afin de les exploiter ensuite, c'est un peu le pendant défensif des opérations "outils de scan" décrites ci-avant.
On peut utiliser des règles de pare feu qui observent les connexions entrantes et bannissent pour 10 minutes toute source qui essaye au moins 5 ports différents en moins de 10 secondes.
:!: en pratique il est difficile de détecter un réel "port scan" hostile d'un usage rare mais standard. Ces protections sont davantage utile pour détecter de //possibles// attaques, plutôt que comme outil de contre-mesure explicite (retirez alors l'avant dernière ligne ci-dessous). A vos risques et périls!
ipset create port_scanners hash:ip family inet hashsize 32768 maxelem 65536 timeout 600
ipset create scanned_ports hash:ip,port family inet hashsize 32768 maxelem 65536 timeout 60
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state NEW -m set ! --match-set scanned_ports src,dst -m hashlimit --hashlimit-above 1/hour --hashlimit-burst 5 --hashlimit-mode srcip --hashlimit-name portscan --hashlimit-htable-expire 10000 -j SET --add-set port_scanners src --exist
iptables -A INPUT -m state --state NEW -m set --match-set port_scanners src -j DROP
iptables -A INPUT -m state --state NEW -j SET --add-set scanned_ports src,dst
([[https://unix.stackexchange.com/a/407904/174841|source]])
==== Honeypot ====
A l'inverse du port knocking, le "pot de miel" est un piège rendu public qui va "capturer" les tentatives d'accès naïves. Par exemple, on peut mettre un process en écoute sur le port 22 alors même que son service SSH est sur le port 12345. Il sera aisé de détecter une tentative frauduleuse d'accès à votre serveur (... ou un oubli de votre part!)
La détection d'un accès sur le port "pot de miel" pourra déclencher deux types de réponses:
* un blocage "blacklist" immédiat du client pour une durée donnée
* ou encore répondre extrêmement lentement afin de ralentir l'attaquant. C'est généralement efficace contre une attaque brute force (qui repose sur un très grand nombre d'essais et de combinaisons), car l'attaquant se lassera vite de votre serveur qui parait abominablement lent et ira chercher ailleurs une autre victime. Mais cela mobilise aussi //vos propres ressources réseau// car votre serveur conserve ce canal de communication ouvert: saturé, vous risquez fort de vous provoquer vous-même un **déni d'accès** (DDOS) bien contreproductif. Cette défense est généralement déconseillée à cause de cela.
La encore, testez bien que vous n'allez pas vous mettre vous-mêmes dehors!
===== Conclusion et réflexions: attention! =====
On le voit, nombre ces pratiques, surtout celles qui sont "agressives" envers le client ne sont à mettre en oeuvre qu'en ayant pesé le pour et le contre. Mais elles restent selon moi recevables dans certains cas souvent critiques (ex. un serveur IOT qui n'est jamais censé être visible du public). Le port knocking notamment est très simple et statistiquement très efficace.
D'autre part, la composante "sécurité par l'obscurité" n'est recevable **qu'en supplément d'une sécurité traditionnelle explicite** (SSL, certificats, mot de passe, bonnes clés, etc).
Comme d'habitude, la sécurité bénéficie de plusieurs couches les unes sur les autres. Et puis il faut voir la sécurité dans son ensemble. Si vous avez un service SSH standard, sur le port 22, vous serez régulièrement attaqués en "brute force", du simple fait que les scripts-robots des pirates trouveront ce port ouvert sur l'extérieur. Même sans succès, ces attaques laissent énormément de traces dans les journaux du système et cela réduit la lisibilité. C'est pour cela que je recommande de changer le port SSH par défaut (trop visible et trop attaqué), ou bien de recourir à du port knocking dont le gros bénéfice est de **masquer simplement et complètement un service la plupart du temps**. Votre journal en sera grandement réduit et vous augmenterez vos chance de voir des tentatives d'accès réellement problématiques.
Notons enfin que l'adresse IP du client est souvent utilisée comme critère pour bloquer un accès.
Mais cette adresse n'est pas toujours un //identifiant unique// du client! Parfois, c'est l'adresse publique d'un sous-réseau local de 100 postes et donc de diverses personnes qui ne sont pas forcément toutes mal intentionnées. C'est aussi le cas de certains opérateurs téléphoniques ou fibrés, d'où "ressortent" leurs clients sur des IP partagées, changeantes et recyclées en permanence. Il est souvent plus solide d'utiliser l'adresse ethernet physique, lorsqu'elle est disponible.