[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧

来源:http://bbs.ichunqiu.com/thread-10359-1-1.html?from=ch

作者:万年死宅

首发:i春秋社区

注明:转载请务必注明i春秋社区(bbs.ichunqiu.com)

前言

过了Today的No.7paper,我们就不在讲SQL注射的问题了,我们将慢慢过渡到前端,那么,这节课呢。有两个主题,一是WeChall的第二道MySQL题(这道题,当时我也琢磨了一会才做出来。。。),第二个呢,就是MySQL注射的高级技巧。(一万个舍不得~~)。好了废话不多说,我们进入正题。

目录

root@1~# Training: MySQL II的简单分析

root@2~# MySQL高级注射技巧load_file()来读文件

root@3~# MySQL高级注射技巧into otfile来getshell

正文

root@1~# Training: MySQL II的简单分析

OK,昨天的Training:MySQL I给大家的启发很大吧。总之,对我启发很大,因为,我就是从这道题开始才真正的算是开始了解MySQL注射的(之前就是背注射语句,然后套。。。)

好了,我们不废话,直接来看这道题:

小宅的传送门

OK,大家可以先尝试解一下,然后在回来继续看这份教程,首先,我们还是先来看高亮的代码:

小宅的传送门

我们定位到HTML的Form表单(68~83行):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第1张图片

我们注意表单的method为POST,要传送的参数是username和password,于是定位到接收参数的地方(10~13行):

我们看到接收了POST参数username和password就调用了auth2_onLogin()函数,我们跟踪到该函数的定义处(36~66行):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第2张图片

我们来看函数的流程,可以发现于昨天的No.6paper极其相似,但是,有一处不同,就是认证不同了,我们来观察一下。首先是用于我们可控的SQL语句不同了(42行):

本次的SQL语句成了这样,接着,我们来看44~47行,这是和上道题一样的判断,只是SQL语句变了,但是还是一个道理:

[PHP]纯文本查看复制代码

?

1

if(false === ($result=$db->queryFirst($query)))

可以看到,还是调用$db->queryFirst()来执行SQL语句,并将查询结果赋值给$result,然后以这个整体(也就是这次查询的返回值)与false进行比较。当为false时自然就是说查询语句失败,例如,传入“xxx”,SQL语句则是:

[SQL]纯文本查看复制代码

?

1

SELECT*FROMusersWHEREusername='xxx';

若查询失败,则证明不存在xxx这条记录,若查询成功则证明存在xxx这条记录。这次的查询语句还有不同的是select的是*,所以,我们来看下users表的表结构(2~8行):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第3张图片

可以看到这个users表里有三个字段,分别是:“userid,username,password”。因为我们select的是*所以$result里就同时存在这三个与username同行的userid和password。

接着,我们来看重头戏,新的认证检测步骤(50~56行):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第4张图片

我们来看这个新增的步骤:

[PHP]纯文本查看复制代码

?

1

if($result['password'] !==$password)

这个if语句的条件是查询结果里的与我们赋值的username同行的password是否与我们传入的password相同,如果不相同则执行if里的内容。

看起来简直天衣无缝,这样的验证从逻辑上来讲几乎没有问题了,所以,我们的突破口,绝不会在PHP代码上。

于是,我们就发现这次的SQL语句也是存在注射漏洞的,因为我们来看这个代码片段:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第5张图片

从图中可以看到,从SQL语句的生成到查询之间并未进行任何过滤,所以存在SQL注射。所以问题就出在我们可控的SQL语句上,我就提示到这里,大家先自己动动脑筋,想想怎么绕过认证。

我们得清楚,首先,我们不知道正确的username和password,而且不是以SQL的返回值来认证的,那怎么办?

这个,其实解决方案,我在No.5paper里讲过,就不知道大家有没印象了。

好了,大家想完之后呢,就来看正确的解题思路吧。

首先,既然我们不知道正确的用户名和密码,那我们就构造啊,什么意思呢?

大家记不记得UNION的神奇功效,假设我们如下SQL语句:

[SQL]纯文本查看复制代码

?

1

SELECTAFROMBWHEREC='$aaa'

假设在B表里有C等于111,但是我们不知道,那么如果我们构造如下$aaa的值会发生什么?

[SQL]纯文本查看复制代码

?

1

xxx'UNIONSELECT1#

这样一拼接就成了:

[SQL]纯文本查看复制代码

?

1

SELECTAFROMBWHEREC='xxx'UNIONSELECT1#'

所以A就成了1,对吧,嘿嘿,其实就是这么简单,只是由于我们对SQL的理解还不够深,才导致我们一时半会没想出解法。

于是我们在还去看题里的SQL语句:

[SQL]纯文本查看复制代码

?

1

SELECT*FROMusersWHEREusername='$username';

所以我们构造:

[SQL]纯文本查看复制代码

?

1

xxx' UNION SELECT 1,'test','123456'#

就拼接成了:

[SQL]纯文本查看复制代码

?

1

SELECT*FROMusersWHEREusername='xxx'UNIONSELECT1,'test','123456'#';

由于xxx这个username本就不存在,所以查询结果自然的变成了UNION的,于是userid变为1,username变为test,而password变为123456。

所以,我们username填"xxx' UNION SELECT 1,'test','123456'#",password填123456就OK了吗?我们试试就知道了,如下图:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第6张图片

我们点Login听天由命吧,哈哈:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第7张图片

密码错误!知道为什么吗?恩?嘿嘿,大家细想一个细节,在PHP程序中处理我们传入password的细节(在40行,哈哈):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第8张图片

知道问题出在哪里了吗?哈哈,对的,我们UNION的password一定要是输入的password的MD5值,当然,也可以是我们输入的password是UNION的password的MD5值。

我们来试试看(123456的MD5值是:e10adc3949ba59abbe56e057f20f883e)。把username填成:"xxx' UNION SELECT 1,'test','e10adc3949ba59abbe56e057f20f883e'#",把password填成123456,我们来看:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第9张图片

结果是:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第10张图片

成功!Bypass了新的认证方式!但是,这道题并没解出来,我们来看原题的题意:

要以admin的身份登录,而不是test,所以,我们得稍稍的改一下payload:

[SQL]纯文本查看复制代码

?

1

xxx' UNION SELECT 1,'admin','e10adc3949ba59abbe56e057f20f883e'#

我们再来看:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第11张图片

来,和我一起欢呼!yeah!(O了,别**了,我们还有事呢。)

root@2~# MySQL高级注射技巧load_file()来读文件

接下来,我们进入下一个主题,MySQL高级注射技巧,这里我只提及几个很常见的技巧。现在我们来说第一个load_file()函数。

我们来简单的学习一下这个load_file()函数,首先我们得先启动mysql和apache服务:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第12张图片

OK了,我们登录MySQL:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第13张图片

接着,我们进入早已准备好的sqliDemo数据库(这个其实无所谓,大家自己随便新建一个数据库也阔以,嘿嘿):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第14张图片

然后,我们来来学习一下使用这个load_file()函数(语句在下图中):

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第15张图片

就这么简单,然后用No.5paper里提到的公式去构造适合的Payload即可利用,但是啊,前几天就有同学问我我就这样在mysql里演示,没有将怎么注射啊。。。当时我的内心是崩溃的,因为我就是想让大家具有这种自己构造Payload的能力啊,而不是说到头来你还是只能背人家给的payload。

但是,我还是演示一下吧,以免看不懂的人说假。(我心累,而且还很无奈。)

我在本地搭建了一下,构造了这样一个注射点"http://localhost/test.php?id=1",参数是id(GET)没任何过滤。

我们用FireFox来的HackBar演示吧,我们先到如下页面:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第16张图片

接着点击HackBar上的Load URL,如图:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第17张图片

我们接着构造如下Payload,即可load那个file了:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第18张图片

接着点击Execute,如下图:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第19张图片

成功了吧,就这么简单,甚至可以不用绝对路径,大家自己尝试嘛,嘿嘿。

root@3~# MySQL高级注射技巧into otfile来getshell

接着是第二个MySQL高级注射技巧into outfile写文件,来GetWebshell,嘿嘿,以后妈妈再也不用担心我GetWebshell的方法少了,嘿嘿。

我们还是先演示MySQL Console的语句,首先,我决定写一个到Web跟目录/var/www/html的my.php文件里:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第20张图片

可以看到失败了,报错了,这是目录权限问题,执行如下命令:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第21张图片

接着,重来:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第22张图片

成功了,我们在Web上访问看看:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第23张图片

OK,接着我们演示在SQL注射点如何写,其实也很简单,如图:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第24张图片

接着,我们来访问试试写进去没:

[深入学习Web安全](7)人人都可学会的MySQL高级注射技巧_第25张图片

O了,就这样吧,这篇paper就陪大家到这里了,希望大家好梦~~

你可能感兴趣的:([深入学习Web安全](7)人人都可学会的MySQL高级注射技巧)