首页 > 数据库 > 利用SQLite数据库文件实现任意代码执行
2016
11-23

利用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(‘
  
    ’);--

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数据库文件了。

 

 

来自:http://www.freebuf.com/vuls/120213.html

 

编程技巧