Apache

Apache est un outil très modulaire qui permet de créer des serveurs web :

$ sudo apt install apache2

Voici quelques modules importants qu’on aura l’occasion de voir en détail :

NomDescription
mod_sslHTTPS / TLS
mod_rewriteRéécriture d’URL
mod_headersGestion des en-têtes HTTP
mod_securitySécurité applicative (WAF)
mod_proxyProxy et reverse proxy
mod_statusStatistiques de performance

Il est possible de gérer ces modules :

Apache permet d’héberger plusieurs applications web sur la même machine, on parle de d’hôte virtuel. Chaque hôte (= application) est un fichier dans /etc/apache2/sites-available/. Par exemple, on peut y créer monsite.conf :

<VirtualHost *:80>
  ServerName monsite.local
  DocumentRoot /var/www/monsite

  <Directory /var/www/monsite>
    Options -Indexes +FollowSymLinks
    AllowOverride All
    Require all granted
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/monsite_error.log
  CustomLog ${APACHE_LOG_DIR}/monsite_access.log combined
</VirtualHost>

On vient de créer un serveur web qui :

Pour que notre site soit accessible on l’active et on redémarre Apache :

sudo a2ensite mon_site.conf
sudo systemctl reload apache2

Ensuite, pour que notre site soit accessible via HTTPS :

Quelques mesures de sécurité

Un fichier .htaccess permet de configurer Apache pour chaque répertoire d’une application web. Toutes les configurations qu’on va voir peuvent se mettre dans ce fichier ou dans un bloc VirtualHost.

On commence par masquer la version d’Apachee utilisée et désactiver le listing des fichiers :

Options -Indexes
ServerTokens Prod
ServerSignature Off

Si un dossier doit uniquement être accessible par une IP :

<RequireAll>
  Require all denied
  Require ip 10.252.46.165
</RequireAll>

Ensuite, pour se protéger en partie contre les failles XSS et le clickjacking :

<IfModule mod_headers.c>
  Header always set X-Frame-Options "DENY"
  Header always set X-Content-Type-Options "nosniff"
  Header always set X-XSS-Protection "1; mode=block"
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

Enfin, voilà un bloc qui permet de bloquer plusieurs vecteurs d’attaque :

<IfModule mod_rewrite.c>
  RewriteEngine On

  # Désactiver le hot linking (un autre serveur qui utilise directement nos fichiers)
  # BIEN MODIFIER mon-site.com À VOTRE CAS
  RewriteCond %{HTTP_REFERER} !^$
  RewriteCond %{HTTP_REFERER} !^http://(www\.)?mon-site.com/.*$ [NC]
  RewriteCond %{HTTP_REFERER} !^https://(www\.)?mon-site.com/.*$ [NC]
  RewriteRule \.(gif|jpg|jpeg|mp3|png|pdf|zip|webp|mp4)$ - [F]

  # Quelques requêtes malveillantes
  RewriteCond %{REQUEST_URI} \.(suspected|eval|base64) [NC,OR]
  RewriteCond %{HTTP_USER_AGENT} ^$
  RewriteRule .* - [F,L]

  # Bloquer certains user agents et requêtes suspects
  RewriteCond %{HTTP_USER_AGENT} (libwww-perl|wget|python|nikto|curl|scan|java|winhttp|clshttp|loader) [NC,OR]
  RewriteCond %{HTTP_USER_AGENT} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
  RewriteCond %{HTTP_USER_AGENT} (;|<|>|'|"|\)|\(|%0A|%0D|%22|%27|%28|%3C|%3E|%00).*(libwww-perl|wget|python|nikto|curl|scan|java|winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) [NC,OR]
  RewriteCond %{THE_REQUEST} \?\ HTTP/ [NC,OR]
  RewriteCond %{THE_REQUEST} \/\*\ HTTP/ [NC,OR]
  RewriteCond %{THE_REQUEST} etc/passwd [NC,OR]
  RewriteCond %{THE_REQUEST} cgi-bin [NC,OR]
  RewriteCond %{THE_REQUEST} (%0A|%0D) [NC,OR]

  # Bloquer plusieurs vecteurs d'attaque (SQL injections, RFI, base64, ...)
  RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
  RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
  RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
  RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
  RewriteCond %{QUERY_STRING} (\.\./|\.\.) [OR]
  RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
  RewriteCond %{QUERY_STRING} http\: [NC,OR]
  RewriteCond %{QUERY_STRING} https\: [NC,OR]
  RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
  RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
  RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
  RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
  RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
  RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
  RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR]
  RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
  RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
  RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
  RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
  RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>).* [NC,OR]
  RewriteCond %{QUERY_STRING} (NULL|OUTFILE|LOAD_FILE) [NC,OR]
  RewriteCond %{QUERY_STRING} (\./|\../|\.../)+(motd|etc|bin) [NC,OR]
  RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
  RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
  RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
  RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
  RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
  RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC,OR]
  RewriteCond %{QUERY_STRING} (sp_executesql) [NC]
  RewriteRule ^(.*)$ - [F,L]
</IfModule>

Ce bloc est loin d’être une protection parfaite et peut parfois rentrer en conflit avec une application web.