目录
SQL注入概述
-
关于SQL注入,我们首先得知道什么是SQL
- SQL(Structured Query Language) – 结构化查询语句
- 用途:用于存取数据及查询,更新与管理关系数据库系统
-
SQL注入的本质与原理
- 原理:SQL注入是服务器端未严格校验客户端发送的数据,而导致服务器端SQL语句被恶意修改并成功执行的行为
- 本质:把用户输入的数据当作代码执行
-
SQL注入产生的原因
- 代码对带入SQL语句的参数过滤不严格
- 未启用框架的安全配置。例如:PHP的magic_quotes_gpc
- 未使用框架安全的查询方法
- 测试接口未删除
- 未启用防火墙
- 未使用其他的安全防护设备
-
SQL注入的条件
- 用户可以控制传参
- 用户输入的语句被带入数据库进行查询
-
SQL注入的危害
- 数据库信息泄露:脱库
- 网页篡改:通过操作数据库对特定网页进行篡改
- 网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击
- 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员账号被篡改
- 服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统
-
SQL注入的类别
- 按照数据类型分类
- 数字型:没有闭合
- 字符型:有闭合
- 按照HTTP请求方式分类
- GET型
- POST型
- 按照注入方式分类
- 联合注入
- 报错注入
- 盲注
- 堆叠注入
- cookie注入
- UA注入
- 二次注入
- 万能密钥
- 等等
- 按照数据类型分类
-
关于注入基础
-
Mysql数据库的基本认知
-
MYSQL5.0以上版本,将自带information_schema数据库
information_schema 用于存储数据库元数据(关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等 。
该数据库中有两张表tables和columnsTABLES:提供了关于数据库中的表的信息,详细表述了某个表属于哪个schema,
表类型,表引擎,创建时间等信息。tables表中 table_name字段表示 表的名字,
table_schema 字段表示数据库名(数据表所属的数据库名)COLUMNS:提供了表中的列信息,详细表述了某张表的所有列以及每个列的信息,某个列属于哪个表。
columns表中table_schema字段为数据库名,table_name字段为表的名字,column_name字段为列的名字 - information_schema.tables 存放表名和库名的对应
- information_schema.columns 存放字段名和表名的对应
- information_schema.mata存放了当前数据库管理系统下所有的数据库
-
-
Mysql数据库的常用函数
- SQL函数是在SQL注入中用的比较多的,经常利用SQL函数来判断数据库的版本,当前用户,当前用户权限以及数据库的安装路径等等,以下是常用的MYSQL函数
- select
- delete
- update
- insert
- system_user()系统用户名
-
user()用户名
-
current_user() 当前用户名
-
session_user() 连接数据库用的用户名
-
database() 数据库名
-
version() mysql数据库版本
-
load_file() mysql读取本地文件的函数
-
@@datadir 数据库路径
-
@@basedir mysql. 安装路径
-
@@version_compile_os 操作系统
-
这里我们用sqli靶场来进行简单的演示及实现,以便更好的理解
SQL注入-联合注入(数字型)
- 首先进入靶场
- 将id=1,改成id=2
- 可以轻松的得知该页面是通过id进行传参的,通过改变id值页面会返回不同的结果
- 分别使用and1=1和1=2进行传参
- 这里分别使用and 1=1 ,and 1=2 后,发现页面显示不一样的结果,代表注入成功,为什么呢?因为1=1这是所有人都知道的,当我们在正常的语句后面加1=1,都是成立的,然后1=2明显是错误的,因为1不可能等于2对吧,所以当我们在后面加上and 1=2时,一定是错误的,所以显示的结果是不正常的,这里我们使用1=1,1=2是为了判断我们输入的语句是否被后端当作正常的代码进行执行,判断是否注入成功的。显而易见这里我们的语句已经被当作正常的代码进行执行了。
- 当我们输入的数据能被当作代码执行的时候,这时候我们可以运用到order by函数了,首先我们输入order by 5
- 页面显示的结果是当前并没有5列,这里order by的作用是为了判断该表有几列,想要知道为什么使用order by,首先得知道order by在SQL语句中的作用是用于对结果集进行升序排序。在SQL注入中我们通常用order by函数来判断有几个字段,发现回显位的
- 这里我们尝试输入order by 4进行测试
- 同样提示没有4列,继续尝试order by 3 进行测试
- 这里有数据了,得知字段数为3
- 将id改为0,使用联合查询union进行测试,输入 union select 1,2,3
- 这里可能很多初学者就开始觉得不太理解了,首先id=0是为了查找到不存在的数据,实际上id可以=-1,也可以等于9999999999999999这样的数字,都是为了查找到不存在的数据,这样我们在输入union select 1,2,3时,我们的占位符就会显示出来,由此我们可以判断回显位,所以从页面返回的结果我们可以得知,回显为在2,3。如果这一步看不懂的话,可以去数据库里敲一敲,实践一下就懂了,想要学好就需要自己多多动手了。
- 这里因为回显位为2,3。所以我们将2改为database(),将3改为version()来查看当前数据库名,及版本号
- 由此查看当前回显位显示的数据库名为security,版本号为5.5.53,前面我们也提到了,Mysql5以上的版本才有自带information_schema数据库,里面的表有相关的关系型数据库的信息内容,是我们后面要用到的,得知MySQL版本号为5.0以上版本,所以可以使用MySQL自带数据库information_schema中的table和column表爆出数据
- 使用group_concat()函数来爆出当前数据库的所有表名
http://127.0.0.1/sqli/Less-2/index.php?id=0%20union%20select%201,2,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()
- 这里我把我们语句写出来了,如果看不懂的话,说明数据库知识内容不扎实,%20是url编码中将空格编译为%20。这里我们通过group_concat语句查出表名为emails,referers,uagents,users。当然正常的回显位不会显示这么多的数据,所有必要时会用到limit函数,此处只是为了演示基本的原理教学
- 有了表名,我们可以看到有个users表,users表示用户嘛,所以一般会存放用户名和密码的,所以我们只要爆出这个users表,就可以拿到用户的信息了,这里我们还需要拿到users表的列名这里还是用的group_concat函数,当然我们这里需要将tables改为columns了,因为我们要拿到列名,这里我们为了精准的查找,还要加上and table_name='users',这里切记users要加上单引号
http://127.0.0.1/sqli/Less-2/index.php?id=0%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema=database()%20and%20table_name=%27users%27
- 这里显示了列为id,username,password,有了表名,有了列名,我们就可以爆数据了
http://127.0.0.1/sqli/Less-2/index.php?id=0%20union%20select%201,group_concat(username),group_concat(password)%20from%20users
- 这里为了方便查看,我们可以将用户名放在第二个回显位上,将密码放在第三个回显位上,以便观察,当然这里只是演示了其中一种方法,语法千千万,有自己的思路才是最重要的