# Recommendation de sécurité

## Securiser l'accès à la configuration

La configuration peut être stockée sous plusieurs formats (SQL, File, LDAP) mais doit être partégée via le réseau si on utilise plus d'un serveur. Si certains des serveurs ne se trouvent pas sur le même réseau (securisé) que la même base de données, il est recommandé d'utiliser l'accès SOAP pour ces serveurs.

On peut utiliser différent typed d'accès : SQL, File or LDAP pour les serveurs se trouvant sur le réseau sécurisé et SOAP pour les autres.

Next, you have to configure the SOAP access as described here since SOAP access is denied by default.

## Protéger le manager

Par défaut, l'accès au manager est restreint à l'utilisateur "dwho" (le backend par défaut est Demo). Pour protéger le manager, il faut choisir l'une où les deux solutions :

- protéger le manager par configuration d'Apache
- protéger le manager par LL::NG

### Protéger le Manager par Apache

You can use any of the mechanisms proposed by Apache: SSL, Auth-Basic, Kerberos,… Example

    <VirtualHost *:443>
        ServerName manager.example.com
        # SSL parameters
        ...
        # DocumentRoot
        DocumentRoot /var/lib/lemonldap-ng/manager/
        <Location />
            AuthType Basic
            AuthName "Lemonldap::NG manager"
            AuthUserFile /usr/local/apache/passwd/passwords
            Require user rbowen
            Order allow,deny
            Deny from all
            Allow from 192.168.142.0/24
            Options +ExecCGI
        </Location>
    </VirtualHost>

### Protéger le manager par LL::NG

Pour protéger le manager par LL::NG, il suffit de mettre ceci dans le fichier de configuration `lemonldap-ng.ini` (section [manager]) :

    [manager]
    protection = manager

Avant, il faut créer l'hôte virtuel `manager.your.domain` dans le manager et mettre une règle, sinon l'accès au manager sera interdit.

## Écrire de bonnes règles

### Ordonner les règles

Les règles sont appliquées dans l'ordre alphabétique (commentaires et expressions régulières). La première règle qui correspond est appliquée.

La règle “default” n'est appliquée que si aucune autre règle ne correspond

Le manager permet de définir des commentaires de règles, ce qui permet de les ordonner :

Par exemple, si ces règles sont utilisées sans commentaires :

Expression régulière | Règle | Commentaire
--- | --- | ---
^/pub/admin/ | $uid eq “root” |
^/pub/ | accept |

Alors la seconde règle est appliquée en premier, donc tous les utilisateurs authentifiés pourront accéder au répertoire `/pub/admin`.

Utiliser des commentaires pour corriger ça :

Expression régulière | Règle | Commentaire
--- | --- | ---
^/pub/admin/ | $uid eq “root” | 1_admin
^/pub/ | accept | 2_pub

- Recharger le manager pour voir l'ordre dans lequel elles seront appliquées
- Utiliser les commentaires pour ordonner les règles

### Attention aux paramètres des URL

On peut écrire des règles qui examine n'importe quel composant de l'URL à protéger y compris les paramètres GET, mais il faut faire attention.

Par exemple avec cette règle sur le paramètre `access` :

Expression régulière | Règle | Commentaire
--- | --- | ---
^/index.php\?.*access=admin | $groups =~ /\badmin\b/ |
default | accept |

Alors l'utilisateur qui tente d'accéder à l'une des URL suivantes sera autorisé !

- /index.php?access=admin&access=other
- /index.php?Access=admin

On peut utiliser les règles suivantes à la place :

Expression régulière | Règle | Commentaire
--- | --- | ---
^/(?i)index.php\?.*access.*access | deny | 0_bad
^/(?i)index.php\?.*access=admin | $groups =~ /\badmin\b/ | 1_admin
default | accept |

(?i) signifie insensible à la casse.
Rappel : les règles poratnt sur des paramètres GET doivent être testées.

### Caractères encodés

Certains caractères sont encodés dans les URLs par le navigateur (tels les espaces,…). Pour éviter les problèmes, LL::NG les décode en utilisant http://search.cpan.org/perldoc?Apache2::URI#unescape_url. Il faut donc écrire les règles en utilisant les caractères normaux.

## Securiser les proxies inverses

LL::NG peut protéger toute application hébergée par Apache y compris le mécanisme de proxy inverse d'Apache. Exemple :

    PerlOptions +GlobalRequest
    PerlRequire /var/lib/lemonldap-ng/handler/MyHandler.pm
    <VirtualHost *:443>
        SSLEngine On
        ... autres paramètres SSL ...
        PerlInitHandler My::Handler
        ServerName appl1.example.com
        ProxyPass / http://hiddenappl1.example.com/
        ProxyPassReverse / http://hiddenappl1.example.com/
        ProxyPassReverseCookieDomain / http://hiddenappl1.example.com/
    </VirtualHost>

Voir les documentation de mod_proxy et mod_rewrite pour plus d'information sur la configuration du proxy inverse d'Apache.

Une telle configuration peut engendrer des problèmes de sécurité :

- Si un utilisateur peut accéder directement à l'application cachée, peut contourner la protection de LL::NG
- if many hidden applications are on the same private network, if one is corrupted (by SQL injection, or another attack), the hacker will be able to access to other applications without using reverse-proxies so it can bypass LL::NG protection

Il est donc recommandé de sécurisé le canal entre le proxy inverse et l'application pour être sûr que seules les requêtes issues des proxies inverses protégés par LL::NG sont autorisées. On peut utiliser un ou plusieurs solution :

- pare-feux (attention toutefois si plus d'une application se trouve derrière le pare-feu)
- restrictions basées sur le serveur (tel le mécanisme “allow/deny” d'Apache)
- SSL client certificate for the reverse-proxy (see SSLProxy* parameters in mod_ssl documentation)

## Configurer les paramètres de sécurité

Aller dans le manager, `Paramètres généraux` » `Paramètres avancés` » `Sécurité` :

- Contrôle du nom d'utilisateur : expression régulière utilisée pour vérifier la syntaxe du nom d'utilisateur.
- Forcer l'authentification : mettre à 'Activé' pour forcer l'authentification lorsque l'utilisateur accède au portail même s'il dispose d'une session valide
- Force authentication interval: time interval (in seconds) when a authentication renewal cannot be forced, used to prevent to loose the current authentication during the main process. If you experience slow network performances, you can increase this value.
- Clef de chiffrement : clef utilisée pour chiffrer certaines données, ne doit être connue d'aucune autre application
- Domaines approuvés : domaines vers lesquels l'utilisateur peut être redirigé après authentification sur le portail. Mettre '*' pour tout accepter.
- Utiliser la cage sécurisée : mettre à 'Désctivé' pour désactiver la cage sécurisée (Safe). Le module Safe est utilisé pour évaluer les expressions dans les en-têtes, règles, etc... La désactiver peut engendrer des trous de sécurité.
- Contrôler les attaques XSS : mettre à 'désactivé' pour désactiver la détection des attaques XSS. Le contrôle XSS continuera à être effectué mais avec seulement des avertissements dans les journaux sans empêcher le processus de continuer.
- LWP::UserAgent SSL options: insert here options to pass to LWP::UserAgent object (used by SAML or OpenID-Connect to query partners). Example: `verify_hostname ⇒ 0`, `SSL_verify_mode ⇒ 0`

## Fail2ban

pour bloquer les attaques en force brute avec fail2ban

Editer /etc/fail2ban/jail.conf

    [lemonldap-ng]
    enabled = true
    port    = http,https
    filter  = lemonldap
    action   = iptables-multiport[name=lemonldap, port="http,https"]
    logpath = /var/log/apache*/error*.log
    maxretry = 3

et editer /etc/fail2ban/filter.d/lemonldap.conf

    # Fail2Ban configuration file
    #
    # Author: Adrien Beudin
    #
    # $Revision: 2 $
    #

    [Definition]

    # Option:  failregex
    # Notes.:  regex to match the password failure messages in the logfile. The
    #          host must be matched by a group named "host". The tag "<HOST>" can
    #          be used for standard IP/hostname matching and is only an alias for
    #          (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
    # Values:  TEXT
    #
    failregex = Lemonldap\:\:NG \: .* was not found in LDAP directory \(<HOST>\)
                Lemonldap\:\:NG \: Bad password for .* \(<HOST>\)

    # Option:  ignoreregex
    # Notes.:  regex to ignore. Si cette expression régulière correspond, la ligne est ignorée.
    # Values:  TEXT
    #
    ignoreregex =

Redémarrer fail2ban

## Sessions identifier

You can change the module used for sessions identifier generation. To do, add `generateModule` key in the configured session backend options.

We recommend the use of `Lemonldap::NG::Common::Apache::Session::Generate::SHA256`.