利用SQLite数据库文件实现任意代码执行
<p style="text-align:center"><img src="https://simg.open-open.com/show/fdc5d7f346e343a09e20a72bde12dc30.jpg"></p> <h2><strong>前言</strong></h2> <p>近期,我们对贝尔金WeMo智能家居设备的安全性进行了分析。在研究过程中,我们开发出了一种新型的SQL注入技术,这项技术针对的是SQLite数据库。实验表明,我们可以利用这项SQLite注入技术在SQLite数据库中实现任意代码执行。这篇文章将会告诉大家如何去创建一个SQLite数据库,并且利用纯粹的SQL查询语句来执行一个ashShell脚本。</p> <p>我们认为,对于渗透测试人员和漏洞研究社区而言,这项技术的适用性是非常广泛的。我们希望这篇文章能够给各位带来有价值的信息,并且各位能够通过这篇文章中的内容自己动手复现这个漏洞。</p> <h2><strong>背景知识</strong></h2> <p>利用SQLite注入漏洞来执行任意代码的一个最简单的方法就是利用load_extension()函数来执行共享库中的某个函数。但是libsqlite3.so这个库默认是禁止这个功能的,因为这很明显就是一个安全漏洞。实际上,在某些 <a href="/misc/goto?guid=4959726104111776174" rel="nofollow,noindex">SQLite injection cheat sheets</a> (SQLite注入安全备忘单)中,也有人会使用一个ATTACH DATABASE语句来在目标Web服务器的根目录下创建SQLite文件。此时,攻击者就可以使用恶意PHP代码来对该文件进行处理,当攻击者向服务器请求该文件时,PHP解释器就会执行其中的恶意代码。相关代码如下所示:</p> <pre> <code class="language-sql">ATTACH DATABASE ‘/var/www/lol.php’ AS lol; CREATE TABLE lol.pwn (dataz text); INSERT INTO lol.pwn (dataz) VALUES(‘ <!--?system($_GET[‘cmd’]); ?-->’);--</code></pre> <p>ATTACH DATABASE语句首先会检查指定位置是否存在相应的文件。如果存在,那么它便会尝试将该文件视作一个SQLite数据库来打开。如果不存在,它将会在目标地址创建这个文件,并为这个SQLite数据库文件赋予读取和写入权限。在上面这个例子中,语句在/var/www/目录下创建了一个名为lol.php的文件,我们可以使用“lol”作为数据库名称来访问这个文件接下来,我们在“lol”数据库中创建了一个名为“pwn”的表,并向该表插入了一个字符串。当Web服务器请求该文件时,该数据库的后缀名“.php”将会触发Web服务器的PHP解释器。解释器会寻找文件中的“<?”,并尝试执行该符号之后的所有语句,直到解释器扫描到“?>”为止。在这种情况下,无论 “cmd”这个GET请求变量中包含的是怎样的代码,这些代码最终都会以系统命令的形式得到执行。这样一来,我们就可以使用这个方法来利用SQL注入漏洞实现任意命令执行了。但是大多数使用SQLite数据库的服务器中并不会安装PHP解释器,例如很多嵌入式系统就是这样。这样一来,我们的技术就不管用了。</p> <h3><strong>将SQLite当作一个ash脚本</strong></h3> <p>很多基于Linux的嵌入式系统都会使用BusyBox工具套件来实现绝大部分基础的Linux命令。默认情况下,BusyBox会使用ash shell来实现/bin/sh。所以我们打算看看是否可以创建一个SQLite数据库文件,并将其当作一个ash shell脚本来执行,而且我们希望只使用SQL语句就能够执行它。因为ash的命令解析器比PHP的代码解释器要复杂的多,所以我们就要想一些其他的办法了。不过幸运的是,ash比bash要简单得多,看来我们选择ash是正确的。</p> <p>首先我们要了解的是,ash的解析器对于换行符(“\n”)和圆括号(“(”和“)”)是非常敏感的。这是因为当用户在命令行中按下回车之后,便会插入一个新行,而括号中包含的指令是subshell所需要执行的指令。所以,如果我们能够找到某种方法可以在SQLite数据库文件中插入这些字符的话,我们就可以用它们来控制ash在处理这个文件时所采用的方式了。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/0a060545320c5158bab0f07936953028.jpg"></p> <p>图片1:向一个SQLite数据库文件插入并保存换行符</p> <p>我们使用“插入换行符”这个技巧的主要依据为:SQLite数据库会将用于构造数据库模式的SQL语句保存下来,正如图片1顶部的CREATE语句所表示的那样,SQLite数据库会将我们的换行符保存在数据库模式的定义之中。</p> <p>图片1下半部分的代码显示的是我们将数据库文件以ash shell脚本来运行时的情况。ash报告的第一个错误是它无法找到“SQLite”命令,因为它在解析代码时,将文件中的第一个词当作了命令,然后将CREATE语句中的内容(换行符之前的代码)当作了命令的执行参数。这样一来,我们只需要插入新的一行,就可以让ash忽略整个文件的内容了。现在我们要解决的就是如何修复ash的第二个报错,即“unterminated quoted string”(未结束引用字符串)。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/d1ee02b853785bcae4d1fee8b1ffda60.jpg"></p> <p>图片2:执行“echo”命令</p> <p>很简单,解决第二个报错的方法就是另外插入新的一行。大家可以从图片2中看到,我们在新的一行中向CREATE语句中添加了“withoutrowid”。我们在定义完数据表中的列之后,又插入了一个换行符。这样一来,我们就用换行符包裹住了列定义语句了。当文件被当作脚本来解析时,列定义语句就会被视作一个单独的文本行。图片2底部的代码表面,当文件作为脚本来执行时,“echonone primary key”这条语句将会被解析为一个echo命令,“noneprimary key”会被输出到屏幕上。这样一来,我们就可以实现任意命令执行了,因为我们可以将列名修改为任何想要执行的命令。当然了,这还不是真正意义上的“任意命令执行”,因为我们无法在命令中设置任意参数。为了得到一个有效的列定义,列名之后的第一个词必须符合数据库的类型定义。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/605b7f457a9727f6ff93216d91cd65ec.jpg"></p> <p>图片3:使用SQLite数据库文件实现任意命令执行</p> <p>为了实现任意命令执行,我们先回顾一下之前运行PHP恶意代码所用的方法,即把需要执行的命令作为表的值来插入。大家可以在图片3中看到,我们也使用了同样的方法,只不过字符串的第一个字符和最后一个字符必须为换行符。</p> <h2><strong>总结</strong></h2> <p>阅读完这篇文章之后,大家应该已经知道了如何去创建一个可以被当作ash shell脚本的SQLite数据库文件了。</p> <p> </p> <p> </p> <p>来自:http://www.freebuf.com/vuls/120213.html</p> <p> </p>
本文由用户 GenesisCana 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!