Skip to content

A heap-based buffer overflow in function read_io_status in src/modbus.c #683

@GoldBinocle

Description

@GoldBinocle

libmodbus version

latest commit b25629bfb508bdce7d519884c0fa9810b7d98d44

OS and/or distribution

Debian GNU/Linux 11 (bullseye)

Environment

x86_64

Description

There is a heap-based buffer overflow in the function read_io_status in src/modbus.c.

Actual behavior if applicable

Heap-buffer-overflow

Expected behavior or suggestion

no crash

Steps to reproduce the behavior (commands or source code)

Build with ASan

CC=clang CXX=clang++ CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" ./autogen.sh
CC=clang CXX=clang++ CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" ./configure && make

Asan traceback

I found a heap-buffer-overflow bug via the utility tests/unit-test-client, here is the stderr output:

ERROR Connection timed out: select
ERROR Illegal data address
=================================================================
==2758680==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x604000000035 at pc 0x7f80c1952a2a bp 0x7ffd59cbdb30 sp 0x7ffd59cbdb28
WRITE of size 1 at 0x604000000035 thread T0
    #0 0x7f80c1952a29 in read_io_status /root/libmodbus/src/modbus.c:1207:29
    #1 0x7f80c195254d in modbus_read_bits /root/libmodbus/src/modbus.c:1238:10
    #2 0x560ca1aa26b4 in main /root/libmodbus/tests/unit-test-client.c:363:10
    #3 0x7f80c15d4d09 in __libc_start_main csu/../csu/libc-start.c:308:16
    #4 0x560ca19e15c9 in _start (/root/libmodbus/tests/.libs/unit-test-client+0x255c9) (BuildId: 06a076f26a7dd417c82e6c39b9bbb21e4b70fc3e)

0x604000000035 is located 0 bytes to the right of 37-byte region [0x604000000010,0x604000000035)
allocated by thread T0 here:
    #0 0x560ca1a6616b in __interceptor_malloc (/root/libmodbus/tests/.libs/unit-test-client+0xaa16b) (BuildId: 06a076f26a7dd417c82e6c39b9bbb21e4b70fc3e)

SUMMARY: AddressSanitizer: heap-buffer-overflow /root/libmodbus/src/modbus.c:1207:29 in read_io_status
Shadow bytes around the buggy address:
  0x0c087fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c087fff8000: fa fa 00 00 00 00[05]fa fa fa fa fa fa fa fa fa
  0x0c087fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==2758680==ABORTING

PoC

This bug is triggered when the client executing modbus_read_bits:

rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, UT_BITS_NB + 1, tab_rp_bits);

For this operation, the corresponding normal response to tests/unit-test-client (collected by launching tests/unit-test-server) is 001100000006ff0101300026, with structure:

###[ ModbusADU ]### 
  transId   = 0x11
  protoId   = 0x0
  len       = 6
  unitId    = 0xff
###[ Read Coils Response ]### 
     funcCode  = 0x1
     byteCount = 1
     coilStatus= [48]

However, if mutating this packet by manipulating the field unitId:

###[ ModbusADU ]### 
  transId   = 0x11
  protoId   = 0x0
  len       = 6
  unitId    = 0x7c
###[ Read Coils Response ]### 
     funcCode  = 0x1
     byteCount = 1
     coilStatus= [48]

with hex stream 0011000000067c0101300023, the tests/unit-test-client crashed due to heap buffer overflow.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions