Bloquer l’utilisation de mot de passe fuité avec IntelligenceX et ModSecurity
Introduction
Contexte et objectifs
Les fuites de données sont de plus en plus nombreuses et les données contenues de plus en plus critiques (PHI, PII, Password, ….). Bien que nécessaire, l’utilisation d’un gestionnaire de mot de passe seul ne suffit plus. Les brèches peuvent venir de plusieurs sources, et même du gestionnaire de mot de passe lui-même.
Il est donc primordial de suivre les différentes fuites de données vous concernant, et de prendre des mesures automatiques de remédiation ou de mitigation – la confiance n’exclut pas le contrôle. Pour cela, deux outils sont à votre disposition : ModSecurity et IntelligenceX.
Présentation des outils
Schéma fonctionnel
Récupération automatique des mots de passe fuités
Description
Les objectifs du script python sont de se récupérer l’ensemble des mots de passe fuité et connu de la plateforme IntelligenceX.
Configuration
# touch /etc/httpd/modsecurity.d/leaked_password.txt
# vi /opt/intelx_ModSec.py
# -*- coding: utf-8 -*-
import http.client
import json
import ssl
import requests
import os
import platform
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
### Variables
API="*****"
INTELX_URL="3.intelx.io"
DOMAIN="mydomain.tld"
PASSWD_FILE="/etc/httpd/modsecurity.d/leaked_password.txt"
def reloadHttp():
### Dirty, but we're fine with it
configtest = os.system('sudo service httpd configtest')
if configtest == 0:
os.system('sudo service httpd reload')
def main():
### Init password list
myPassword = []
### Get all password
url = 'https://'+INTELX_URL+'/accounts/1?selector='+DOMAIN+'&limit=1000000'
headers = {
'X-Key': API
}
response = requests.request("GET", url, headers=headers, verify=False)
intelx_result = json.loads(response.text.encode('utf8'))
for leak in intelx_result:
if leak["passwordtype"] == "Plaintext":
if leak["password"] not in myPassword:
myPassword.append(leak["password"])
myPassword_sorted = sorted(myPassword)
### Get all password in current file
with open(PASSWD_FILE) as f:
lines = f.read().splitlines()
### Compare both lists for any changes
temp_1 = set(myPassword_sorted)
temp_2 = set(lines)
if temp_1 != temp_2:
with open(PASSWD_FILE, "w") as fp:
for password in myPassword_sorted:
fp.write("%s\n" % password)
reloadHttp()
if __name__ == '__main__':
main()
Automatisation
# crontab -e
00 00 * * * python3 /opt/intelx_ModSec.py > /dev/null 2>&1
Configuration ModSecurity
Description
Nous allons configurer ModSecurity pour aller chercher le mot de passe dans la base des mots de passe récupérés depuis IntelligenceX via le script. La règle ci-dessous fait :
- Se déclenche si l’URL appelée est « /secure/login » et la méthode est POST
- Compare la valeur de l’argument Password à notre fichier
Configuration
### 120 - Sec rule to block leaked password usage
SecRule REQUEST_URI ^\/secure\/login "chain,phase:2,t:none,t:lowercase,t:normalisePath,t:urlDecode,t:urlDecodeUni,t:utf8toUnicode,id:120,log,deny,msg:'Leaked Password Usage'"
SecRule REQUEST_METHOD "^POST" "chain,t:none"
SecRule ARGS:Password "@pmFromFile /etc/httpd/modsecurity.d/leaked_password.txt" "t:none"
Validation de fonctionnement
BURP
Logs ModSecurity
Conclusion
L’intégration des informations présente dans les fuites de données et collectées par IntelligenceX est rendu très simple grâce à l’API. Le script peut aussi être modifié pour se connecter sur différentes autres sources de leak et intégré dans un WAF selon le même principe.
De plus, les logs ModSecurity peuvent être intégrés dans votre solution de SIEM ou SOAR préférée pour déclencher des actions en cas de déclenchement de cette règle :
- Alerte SOC
- Enrichissement de la TIP
- Etc