Skip to content

Denial of Service (DoS) via Single-Connection Slowloris Attack in TCP Network Handler #562

@MrAlaskan

Description

@MrAlaskan

Vulnerability Description

I find that OpENer is vulnerable to a Slowloris-style DoS attack. Because OpENer processes all network traffic in a single-threaded event loop without setting client sockets to non-blocking mode, an attacker can establish a single TCP connection, send an incomplete Ethernet/IP (ENIP) packet, and simply wait. This completely blocks the server's main network processing loop, preventing it from handling any other legitimate requests.

Root Cause

The root cause lies in the synchronous, blocking nature of the socket reads within the single-threaded network handler:

  1. Single-threaded event loop: NetworkHandlerProcessCyclic() uses select() in a single thread to multiplex all incoming socket events.
  2. Missing non-blocking configuration: When a new TCP connection is accepted in CheckAndHandleTcpListenerSocket(), the newly created new_socket is added to the select read set but is not set to non-blocking mode.
  3. Blocking reads: In HandleDataOnTcpSocket(), the code expects a complete ENIP packet and issues direct, blocking reads: recv(socket, ..., 4, 0) followed by a loop reading data_size. If an attacker sends exactly 4 bytes (the ENIP command and length) and intentionally delays sending the rest of the payload, the second recv() call will block indefinitely until data arrives or a TCP timeout occurs. During this time, the entire NetworkHandlerProcessCyclic loop is stalled.

Trigger Conditions

  1. The target device is running OpENer and listening on the default ENIP TCP port (44818).
  2. The attacker establishes a standard TCP connection to the ENIP port.
  3. The attacker sends a partial payload (e.g., a 4-byte header specifying a large data_size) and then holds the connection open without sending the remaining data.

Reproduction (Validated)

PoC.zip

1) Build:
Compile the OpENer project on a POSIX environment (e.g., Ubuntu):

  • Change to the bin/posix directory
  • For a configuration invoke setup_posix.sh (make sure -DOpENer_TRACES:BOOL=ON and -DOpENer_TRACE_LEVEL_ERROR:BOOL=ON are enabled to observe the error logs)
  • Invoke the make command

2) Run target:
Start the OpENer service, listening on the loopback interface:

./src/ports/POSIX/OpENer lo

3) Launch Attack:
In a new terminal, execute the slowloris attacker script to establish a connection and send an incomplete payload:

python3 slowloris_attacker.py

4) Run Legitimate Client Probe:
While the attacker script is holding the connection, run the normal client probe in another terminal to test the server's responsiveness:

python3 normal_client_probe.py

5) Observe Phenomena:

  • The normal_client_probe.py will report consecutive timeouts for its RegisterSession requests until the attacker finally closes the socket.
  • Server logs may show delayed processing or print errors like Error Code: 107 - Transport endpoint is not connected after the attacker closes the socket, proving the network loop was stalled.

Impact Assessment

This is a High severity availability issue. Industrial Control Systems (ICS) rely on deterministic and continuous communication. An unauthenticated attacker with minimal resources (a single TCP connection and negligible bandwidth) can remotely paralyze the OpENer protocol stack, causing legitimate Engineering Workstations or PLCs to lose communication with the device. This leads to a total loss of Ethernet/IP service availability.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions