Blocking leaked passwords with IntelligenceX and ModSecurity
Introduction
Background and objectives
Data leaks are becoming more and more numerous and the data contained more and more critical (PHI, PII, Password, ….). Although necessary, the use of a password manager alone is no longer sufficient. Breaches can come from many sources, and even from the password manager itself.
It is therefore essential to monitor the various data leaks concerning you, and to take automatic remediation or mitigation measures – trust does not exclude control. For this, two tools are available: ModSecurity and IntelligenceX.
IT tools presentation
ModSecurity is an application firewall (WAF), whose role is to filter incoming requests to an HTTP server. It comes in the form of an Apache, Nginx or IIS module that analyzes incoming requests by using a database of rules for requests considered undesirable.
Intelligence X is an independent European technology company, its mission is to develop and maintain the search engine and data archive. It searches in places such as the darknet, document sharing platforms, whois data, public data leaks and more.
Functional diagram
Automatic recovery of leaked passwords
Description
The objectives of the python script are to recover all the leaked and known passwords of the IntelligenceX platform.
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
ModSecurity setup
Description
We will configure ModSecurity to fetch the password from the database of passwords retrieved from IntelligenceX via the script. The rule below does :
- Fires if the URL called is “/secure/login” and the method is POST
- Compares the value of the Password argument to our file
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"
Functional validation
BURP
ModSecurity logs
Conclusion
The integration of the information present in the data leaks and collected by IntelligenceX is made very simple thanks to the API. The script can also be modified to connect to various other leak sources and integrated into a WAF using the same principle.
In addition, ModSecurity logs can be integrated into your preferred SIEM or SOAR solution to trigger actions when this rule is triggered:
-
- SOC alert
- TIP Enrichment
- Etc