还是关于我对SQL注入的理解,首先,通过对注入点有无回显,以及回显信息的认识,SQL注入可以分为union注入(有回显信息,且回显信息较多,例如用户名密码之类的信息),报错注入(页面没有回显,只能通过报错信息来进行推导),布尔盲注(页面没有回显,会通过反馈真值与假值来进行判断)。
然后就是我对SQL注入现在的理解,与思路。
一.判断类型(是否存在sql注入,存在那种sql注入)
1.查找注入点:可以通过对其传入的可控参数(常见的有id,password等等)进行简单的构造,通过服务端返回的内容来判断有无注入 ,注入位置有GET数据(大多存在地址栏)、POST数据(大多存在输入框中)、HTTP头部、cookie数据。
2.判断是字符型注入还是数字型注入:首先我们假设注入类型为数字型,分别输入如下的语句。如果被测试对象是数字型,那么第一行测试语句会返回user_id为1的查询结果,而第二行语句由于条件and 1=2不成立,所以查询结果为空。如果被测试对象为字符型的话,将下面语句拼接到sql中,由于user_id的值都不匹配,所以应该是都不返回任何结果,(但是注意如果user_id本身是int类型,实际查询过程中是会返回结果的,这可能是因为对输入的字符进行了截断并转换了类型,造成1 and 1=2在字符类型中会返回user_id为1的查询结果。当然如果第二个语句返回了结果,我们也可以以此判断出该注入类型是字符型。)
1 and 1=1
1 and 1=2
3.闭合方式的判断:字符型需要闭合符' ') " ")等,数字型不需要闭合。(作用:手工提交闭合符号,结束前一段查询语句,后面即可加入其他语句。)
4.注释符号“--+’或‘#’或'%23'(可以使它们后面的语句不被执行,同时也使前面的语句被执行)。 (注意:get请求传参时字符串中不允许出现空格和特殊字符,故注释符号可以为‘--+’‘--%20’‘%23’等,可用urlencode编码解决这个问题。)
二.猜解sql查询语句中的字段数
去猜测出查询语句中的字段个数,如下注入语句所示,假设为字符型注入,先利用1'
实现引号闭环,再利用or 1=1
这样可以暴露出表中所有的数据,最后利用order by 数字#
去看是否报错来明确查询语句中的字段数。
1' or 1=1 order by 1 #
1' or 1=1 order by 2 #
或者
1' or 1=1 union select 1, 2, 3 #
三.判断回显
由于开头的 1 会干扰回显,所以可以选择去掉1(或者换成负数也行,换成负数会导致前面的值不成立,然后才会继续执行后面的语句)
?可控参数=-1' union select 1,2,3#
四. 通过命令来获得相关库,表,列,字段的信息:
SQL一些最重要的命令(常用)
SELECT - 从数据库中提取数据
UPDATE - 更新数据库中的数据
DELETE - 从数据库中删除数据
INSERT INTO - 向数据库中插入新数据
CREATE DATABASE - 创建新数据库
ALTER DATABASE - 修改数据库
CREATE TABLE - 创建新表
ALTER TABLE - 变更(改变)数据库表
DROP TABLE - 删除表
CREATE INDEX - 创建索引(搜索键)
DROP INDEX - 删除索引
除了这些常用的命令以外,还应该学会怎么构造payload,以及各种函数的理解,与调用。然后实践才是检验真理的唯一标准,上题。
题目
[SWPUCTF 2021 新生赛]sql
通过网页头信息的提示我们可以知道,在这一题里面,可控变量为wllm,通过上文提到的步骤,可以判断注入类型为union注入。
输入单引号,发现报错,同时,根据报错提示也找到了它的闭合方式
判断字段,发现被警告,说明,存在过滤(可能是过滤了空格,也可能是 order by
关键字,还可能是注释符)
通过测试可知,空格,#号(--+)被过滤了,通过尝试可知可以使用%09,或者/**/等等来代替空格,%23来代替#。
经过测试,共有 3 列。
经过测试,回显位为后两位。(因为%09来代替空格真的眼睛花,所以改用/**/来代替空格)
查询数据库,发现名称为:test_db,那么再继续向下查看。
发现又被警告了,说明除了上文发现的过滤,还存在有其他的字符被过滤。可能是information_schema
被过滤了,经过测试,是等号被过滤了。用 like 关键字可以替换等号。
通过替换以后,成功查询到了关键信息
这里使用了group_concat()函数(group_concat()的作用:确保所有查询信息能放到一行显示出来(以逗号分隔开))
然后就是朴实无华的查询出来了列名,然后就是查询flag列的内容
结果懵逼了,flag好像出来了,又好像没出来。通过查找资料与学习,我发现flag的字段被限制了。然后根据大佬的 wp ,发现substr,substring 都被过滤了,说用 mid 函数分段读取。
这里是mid()函数的用法
先查询前二十位,然后再二十位,二十位查
最后,通过一段一段复制,得到了完整的flag。
小结,这题,真牛逼,让我开眼界涨见识了,主要是因为他的过滤,导致“复制粘贴”注入无法实现,只能手搓,但是这个手搓也让我更加理解和记住了sql语句的构成,也明白了很多sql语句中可替换的部分,以及一个新的函数,也就是mid() 函数的使用。让小白开眼界了。
纯小白,如有不足和错误,欢迎指正!