Skip to content

Instantly share code, notes, and snippets.

@Shukhrat-03
Created June 24, 2026 22:08
Show Gist options
  • Select an option

  • Save Shukhrat-03/5cf1825b72e485ef98a32958dfbc611a to your computer and use it in GitHub Desktop.

Select an option

Save Shukhrat-03/5cf1825b72e485ef98a32958dfbc611a to your computer and use it in GitHub Desktop.
Security Vulnerability Report: Heap Buffer Overflow in getData() — openplcproject/OpenPLC_v3 (CWE-122, CVSS 8.8 HIGH)

Security Vulnerability Report

openplcproject/OpenPLC_v3 — Heap Buffer Overflow in getData() — CWE-122

Field Details
Product openplcproject/OpenPLC_v3 (github.com/thiagoralves/OpenPLC_v3)
Affected Version All versions up to latest master (commit b4702061dc14d1024856f71b4543298d77007b88)
Vulnerability Heap-Based Buffer Overflow
CWE CWE-122 (Heap-based Buffer Overflow)
CVSS 3.1 Score 8.8 HIGH (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
File webserver/core/modbus_master.cpp — line 92, 195
Function getData() called from parseConfig()
Component Modbus Master — slave device config parser

Note: This repository was archived on 2026-04-04. The vendor has confirmed this issue does not affect OpenPLC Runtime v4.


1. Summary

A heap-based buffer overflow (CWE-122) exists in the getData() function in webserver/core/modbus_master.cpp (line 92), called from parseConfig() at line 195. An authenticated attacker can send a crafted HTTP POST request to the /modbus endpoint with an oversized device_name field, causing a 100-byte overflow into adjacent struct fields on the heap.


2. Root Cause

getData() reads characters between two delimiter characters and writes them into a caller-supplied buffer without any size parameter or bounds check. At parseConfig() line 195, it is called with mb_devices[n].dev_name — a 100-byte heap-allocated field. Any device name longer than 99 characters causes an overflow into adjacent struct fields.

Vulnerable file: webserver/core/modbus_master.cpp, lines 92-110


3. Attack Chain

HTTP POST /modbus -> mbconfig.cfg -> parseConfig() -> getData()

An attacker with access to the web interface sends a crafted POST request to /modbus with device_name = "A" x 200.


4. Overflow Calculation

Parameter Value Notes
dev_name buffer size 100 bytes MB_device.dev_name[100] — heap allocated
Attacker payload 200 bytes HTTP POST device_name = "A" x 200
protocol field offset 108 First field overwritten
dev_address offset 109 char dev_address[100] — fully overwritten
ip_port offset 210 uint16_t ip_port — overwritten
Bytes past allocation 100 bytes 200 payload - 100 buffer = 100 bytes overflow

5. PoC Output (canary-based verification)

[BEFORE overflow] mb_devices[0].protocol = 0xDE (canary) mb_devices[0].dev_address = "SAFE_ADDR" (canary)

[AFTER overflow] mb_devices[0].protocol = 0x41 [OVERWRITTEN: was 0xDE, got 0x41 = 'A'] mb_devices[0].dev_address = "AAAAAAAAAAAAA..." [OVERWRITTEN: was 'SAFE_ADDR']

[VULNERABLE] getData() wrote 200 bytes into dev_name[100] CWE-122: Heap-based Buffer Overflow CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 8.8


6. Impact

  1. Denial of Service — Heap corruption causes PLC runtime crash. In ICS/SCADA environments this directly disrupts physical process control.
  2. Heap Corruption — Adjacent struct fields (protocol, dev_address, ip_port) are overwritten with attacker-controlled data.

7. Proposed Fix

Add bounds checking in getData():

if (j >= buf_size - 1) break;

Also add server-side length validation in sanitize_input() or the add_modbus_device route — truncate device_name to max 99 characters.


8. References

Reported by: Shuhratbek Uraimov (shuhraturaimov@gmail.com)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment