利用SQLite数据库文件实现任意代码执行

前言

近期,我们对贝尔金WeMo智能家居设备的安全性进行了分析。在研究过程中,我们开发出了一种新型的SQL注入技术,这项技术针对的是SQLite数据库。实验表明,我们可以利用这项SQLite注入技术在SQLite数据库中实现任意代码执行。

这篇文章将会告诉大家如何去创建一个SQLite数据库,并且利用纯粹的SQL查询语句来执行一个ashShell脚本。

我们认为,对于渗透测试人员和漏洞研究社区而言,这项技术的适用性是非常广泛的。我们希望这篇文章能够给各位带来有价值的信息,并且各位能够通过这篇文章中的内容自己动手复现这个漏洞。

背景知识

利用SQLite注入漏洞来执行任意代码的一个最简单的方法就是利用load_extension()函数来执行共享库中的某个函数。但是libsqlite3.so这个库默认是禁止这个功能的,因为这很明显就是一个安全漏洞。

实际上,在某些SQLite injection cheat sheets(SQLite注入安全备忘单)中,也有人会使用一个ATTACH DATABASE语句来在目标Web服务器的根目录下创建SQLite文件。

此时,攻击者就可以使用恶意PHP代码来对该文件进行处理,当攻击者向服务器请求该文件时,PHP解释器就会执行其中的恶意代码。相关代码如下所示:

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语句首先会检查指定位置是否存在相应的文件。如果存在,那么它便会尝试将该文件视作一个SQLite数据库来打开。

如果不存在,它将会在目标地址创建这个文件,并为这个SQLite数据库文件赋予读取和写入权限。

在上面这个例子中,语句在/var/www/目录下创建了一个名为lol.php的文件,我们可以使用“lol”作为数据库名称来访问这个文件接下来,我们在“lol”数据库中创建了一个名为“pwn”的表,并向该表插入了一个字符串。

当Web服务器请求该文件时,该数据库的后缀名“.php”将会触发Web服务器的PHP解释器。解释器会寻找文件中的“<?”,并尝试执行该符号之后的所有语句,直到解释器扫描到“?>”为止。

在这种情况下,无论 “cmd”这个GET请求变量中包含的是怎样的代码,这些代码最终都会以系统命令的形式得到执行。这样一来,我们就可以使用这个方法来利用SQL注入漏洞实现任意命令执行了。

但是大多数使用SQLite数据库的服务器中并不会安装PHP解释器,例如很多嵌入式系统就是这样。这样一来,我们的技术就不管用了。

将SQLite当作一个ash脚本

很多基于Linux的嵌入式系统都会使用BusyBox工具套件来实现绝大部分基础的Linux命令。默认情况下,BusyBox会使用ash shell来实现/bin/sh。

所以我们打算看看是否可以创建一个SQLite数据库文件,并将其当作一个ash shell脚本来执行,而且我们希望只使用SQL语句就能够执行它。

因为ash的命令解析器比PHP的代码解释器要复杂的多,所以我们就要想一些其他的办法了。不过幸运的是,ash比bash要简单得多,看来我们选择ash是正确的。

首先我们要了解的是,ash的解析器对于换行符(“\n”)和圆括号(“(”和“)”)是非常敏感的。这是因为当用户在命令行中按下回车之后,便会插入一个新行,而括号中包含的指令是subshell所需要执行的指令。

所以,如果我们能够找到某种方法可以在SQLite数据库文件中插入这些字符的话,我们就可以用它们来控制ash在处理这个文件时所采用的方式了。

图片1:向一个SQLite数据库文件插入并保存换行符

我们使用“插入换行符”这个技巧的主要依据为:SQLite数据库会将用于构造数据库模式的SQL语句保存下来,正如图片1顶部的CREATE语句所表示的那样,SQLite数据库会将我们的换行符保存在数据库模式的定义之中。

图片1下半部分的代码显示的是我们将数据库文件以ash shell脚本来运行时的情况。

ash报告的第一个错误是它无法找到“SQLite”命令,因为它在解析代码时,将文件中的第一个词当作了命令,然后将CREATE语句中的内容(换行符之前的代码)当作了命令的执行参数。

这样一来,我们只需要插入新的一行,就可以让ash忽略整个文件的内容了。现在我们要解决的就是如何修复ash的第二个报错,即“unterminated quoted string”(未结束引用字符串)。

图片2:执行“echo”命令

很简单,解决第二个报错的方法就是另外插入新的一行。大家可以从图片2中看到,我们在新的一行中向CREATE语句中添加了“withoutrowid”。我们在定义完数据表中的列之后,又插入了一个换行符。

这样一来,我们就用换行符包裹住了列定义语句了。当文件被当作脚本来解析时,列定义语句就会被视作一个单独的文本行。

图片2底部的代码表面,当文件作为脚本来执行时,“echonone primary key”这条语句将会被解析为一个echo命令,“noneprimary key”会被输出到屏幕上。

这样一来,我们就可以实现任意命令执行了,因为我们可以将列名修改为任何想要执行的命令。

当然了,这还不是真正意义上的“任意命令执行”,因为我们无法在命令中设置任意参数。为了得到一个有效的列定义,列名之后的第一个词必须符合数据库的类型定义。

图片3:使用SQLite数据库文件实现任意命令执行

为了实现任意命令执行,我们先回顾一下之前运行PHP恶意代码所用的方法,即把需要执行的命令作为表的值来插入。大家可以在图片3中看到,我们也使用了同样的方法,只不过字符串的第一个字符和最后一个字符必须为换行符。

总结

阅读完这篇文章之后,大家应该已经知道了如何去创建一个可以被当作ash shell脚本的SQLite数据库文件了。最后,祝大家hacking愉快!

* 参考来源:invincealabs,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM。

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2016-11-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏智能大石头

充血模型的ORM能做什么?——ORM组件XCode(十八般武艺)

ORM组件XCode(十八般武艺) 之前,XCode总是若隐若现,耐性好的同学想知道它还有啥特点,沉不住气的则认为不过是CURD耳! XCode开发模式是灵魂,...

21090
来自专栏黑泽君的专栏

day30_Hibernate复习_02(补刀)

对象的三种状态:     瞬时态:对象刚刚创建,没有与session关联,没有ID     持久态:已经和Session关联,有ID     游离...

7720
来自专栏天天

Ajax(20171102)

9930
来自专栏前端儿

Web 后端--PHP 与数据库的交互

         用 PHP  操作 MySQL ,实现数据的交换,还要多练练....

14910
来自专栏IT可乐

mybatis 详解(八)------ 懒加载

  本章我们讲如何通过懒加载来提高mybatis的查询效率。   本章所有代码:http://pan.baidu.com/s/1o8p2Drs 密码:trd6 ...

43490
来自专栏青玉伏案

Swift3.0服务端开发(五) 记事本的开发(iOS端+服务端)

前边以及陆陆续续的介绍了使用Swift3.0开发的服务端应用程序的Perfect框架。本篇博客就做一个阶段性的总结,做一个完整的实例,其实这个实例在《Swift...

24870
来自专栏JavaQ

细说MySQL区分字母大小写

在Linux系统上使用MySQL,MySQL是区分字母大小写的,例如建A表时表名是大写的A,修改A表时脚本里写的a,就会报错表a不存在。在MySQL中,数据库对...

40750
来自专栏积累沉淀

Python快速学习第九天--安装并操作Mysql数据库

python操作mysql数据库 Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。...

29780
来自专栏nnngu

Hibernate的关联映射

首先我们了解一个名词ORM,全称是(Object Relational Mapping),即对象关系映射。ORM的实现思想就是将关系型数据库中表的数据映射成对象...

30550
来自专栏JackeyGao的博客

Django + MySQL 查询不区分大小写问题

由于测试环境的 sqlite 没有问题, 所以怀疑在 mysql 的配置上面。 原来是字符集校对规则的问题, utf8_general_ci 不区分大小写, 可...

20920

扫码关注云+社区

领取腾讯云代金券