Flask site penetration tests : security headers et le session cookie
Penetration testing est un moyen facile de vérifier si votre site est vulnérable aux attaques malveillantes.
Vous avez créé une application Web Flask , elle fonctionne correctement et utilise https. Mais est-ce que c'est assez sécurisé ? Avez-vous tout fait pour protéger vos visiteurs, avez-vous tout fait pour empêcher les attaques malveillantes ?
Une bonne façon de procéder est de pentest votre site. Les outils Penetration testing , ou les outils pen testing , peuvent identifier les faiblesses de la sécurité. Ils identifient les vulnérabilités de l'application Web qui peuvent causer une faille de sécurité.
Wikipédia : Le National Cyber Security Center, décrit le test de pénétration comme suit : Méthode permettant de s'assurer de la sécurité d'un système informatique en tentant de porter atteinte à une partie ou à la totalité de la sécurité de ce système, en utilisant les mêmes outils et techniques qu'un adversaire.
La plupart des outils pentest doivent être installés et bien sûr pas sur votre machine locale mais quelque part sur internet afin que vous puissiez tester votre site de production sans passer par firewalls, NAT. Un jour, j'examinerai ces outils plus en détail, mais pour l'instant, je voulais juste avoir une indication des vulnérabilités possibles.
J'ai utilisé un test en ligne de Pentest-Tools.com, voir le lien ci-dessous, vous obtenez deux tests gratuits. Sélectionnez le Website Vulnerability Scanner, entrez l'url de votre site et attendez les résultats. Bien sûr, ce n'est qu'un test très très basique mais au moins il m'a montré que mon site manquait security headers et que le session cookie n'était pas sécurisé. J'ai aussi utilisé Dareboost, voir lien ci-dessous, leur test Website Speed Test and Website Analysis m'a donné un beau rapport Quality and Performance .
Ajout de security headers manquant
Il est très facile d'ajouter le security headers manquant à votre site Flask . D'abord j'ai une fonction qui ajoute les en-têtes supplémentaires, j'utilise le flag include_security_headers pour les sites actuellement sur internet.
from werkzeug.http import http_date
import datetime
def prepare_response_extra_headers(include_security_headers):
response_extra_headers = {
# always
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0',
'Last-Modified': http_date(datetime.datetime.now()),
}
if include_security_headers:
response_security_headers = {
# X-Frame-Options: page can only be shown in an iframe of the same site
'X-Frame-Options': 'SAMEORIGIN',
# ensure all app communication is sent over HTTPS
'Strict-Transport-Security': 'max-age=63072000; includeSubdomains',
# instructs the browser not to override the response content type
'X-Content-Type-Options': 'nosniff',
# enable browser cross-site scripting (XSS) filter
'X-XSS-Protection': '1; mode=block',
}
response_extra_headers.update(response_security_headers)
return response_extra_headers
Ensuite, dans create_app() j'ajoute les en-têtes supplémentaires à la réponse dans after_request :
...
include_security_headers = config_name in ['staging', 'production']
...
# prepare extra response headers, see after_request
response_extra_headers = prepare_response_extra_headers(include_security_headers)
...
@app.after_request
def after_request(response):
# after_request is not called for 500 error
response.headers.extend(response_extra_headers)
return response
Notez que nous utilisons extend au lieu de update, voir les informations sur les structures de données Werkzeug.
Sécuriser le session cookie
A propos de la session cookie, mon site utilise https, les requêtes http sont redirigées vers https, quel est le problème ? Le problème est que le cookie n'a pas besoin de provenir de votre navigateur à la première ( !) demande. Vous pouvez définir l'en-tête HTTP Strict Transport Security (HSTS) et appliquer le https, mais cela ne résout pas le problème car tous les navigateurs ne supportent pas cet en-tête.
La seule façon de sécuriser votre session cookie est d'ajouter l'attribut cookie secure. Je ne sais pas encore si cela résout tout, mais ce n'est pas un effort à mettre en œuvre. Dans Flask , nous le faisons simplement :
SESSION_COOKIE_SECURE = True
Si vous utilisez Flask-Login et la fonctionnalité 'remember me', ajoutez également :
REMEMBER_COOKIE_SECURE = True
REMEMBER_COOKIE_HTTPONLY = True
Autre problème de sécurité (insoluble) : les mots de passe en mémoire
Il existe encore un autre problème de sécurité lorsque vous exécutez un site sur un VPS (Virtual Private Server). Les mots de passe sont envoyés par https mais sont décodés sur le serveur. Ensuite, en utilisant les bonnes pratiques, elles sont cryptées et stockées dans la base de données.
Même si le serveur a été patché pour éliminer des vulnérabilités comme Zombieload, une personne ayant accès au serveur peut surveiller la mémoire du serveur et voir les mots de passe non chiffrés. Vous pouvez crypter le mot de passe sur le client en utilisant du javascript mais l'attaquant peut toujours utiliser cette valeur cryptée pour se connecter. Le minimum que vous puissiez faire est de trouver un fournisseur de VPS fiable.
Résumé
Sans test de pénétration, vous espérez juste le meilleur. Penetration testing est un très bon moyen de vérifier les vulnérabilités de votre site. Ce n'est pas très difficile mais cela prend un peu / beaucoup de temps. N'oubliez pas que la gestion d'un site sur un VPS n'est jamais totalement sécurisée.
Liens / crédits
40 Best Penetration Testing (Pen Testing) Tools in 2020
https://www.guru99.com/top-5-penetration-testing-tools.html
Cookie Security for Flask Applications
https://blog.miguelgrinberg.com/post/cookie-security-for-flask-applications
Dareboost
https://www.dareboost.com/en
Data Structures
https://werkzeug.palletsprojects.com/en/0.15.x/datastructures/
HTTP Security Headers Analysis of Top One Million Websites
https://ccdcoe.org/uploads/2018/10/Art-18-HTTP-Security-Headers-Analysis-of-Top-One-Million-Websites.pdf
Mozilla Observatory
https://observatory.mozilla.org/
Penetration test
https://en.wikipedia.org/wiki/Penetration_test
Pentest-Tools.com
https://pentest-tools.com
Secure your Cookies (Secure and HttpOnly flags)
https://blog.dareboost.com/en/2019/03/secure-cookies-secure-httponly-flags/
Securing Cookies with HttpOnly and secure Flags
https://resources.infosecinstitute.com/securing-cookies-httponly-secure-flags/
Security Headers
https://securityheaders.com/
ZombieLoad attack lets hackers steal data from Intel chips
https://www.theverge.com/2019/5/14/18623708/zombieload-attack-intel-processors-speculative-execution
En savoir plus...
Flask Pentesting
Récent
- Un commutateur de base de données avec HAProxy et HAProxy Runtime API
- Docker Swarm rolling updates
- Masquer les clés primaires de la base de données UUID de votre application web
- Don't Repeat Yourself (DRY) avec Jinja2
- SQLAlchemy, PostgreSQL, nombre maximal de lignes par user
- Afficher les valeurs des filtres dynamiques SQLAlchemy
Les plus consultés
- Utilisation des Python's pyOpenSSL pour vérifier les certificats SSL téléchargés d'un hôte
- Utiliser PyInstaller et Cython pour créer un exécutable Python
- Réduire les temps de réponse d'un Flask SQLAlchemy site web
- Connexion à un service sur un hôte Docker à partir d'un conteneur Docker
- SQLAlchemy : Utilisation de Cascade Deletes pour supprimer des objets connexes
- Utiliser UUIDs au lieu de Integer Autoincrement Primary Keys avec SQLAlchemy et MariaDb