SQL注入
SQL注入是因为后台SQL语句拼接了用户的输入,而且Web应用程序对用户输入数据的合法性没有判断和过滤,前端传入后端的参数是攻击者可控的,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。比如查询、删除,增加,修改数据等等,如果数据库的用户权限足够大,还可以对操作系统执行操作。
SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤。SQL注入是针对数据库、后台、系统层面的攻击!
mysql中注释符:# 、/**/ 、 --
一、分类
-
依据注入点类型分类
-
数字类型的注入
-
字符串类型的注入
-
搜索型注入
-
-
依据提交方式分类
-
GET注入
-
POST注入
-
COOKIE注入
-
HTTP注入(XFF注入、UA注入、REFERER注入)
XFF:X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。
UA:用户代理(User Agent,简称 UA),是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
REFERER:HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
-
-
依据获取信息的方式分类
-
基于布尔的盲注
-
基于时间的盲注
-
基于报错的注入
-
联合查询注入
-
堆查询注入(可同时执行多条语句)
-
二、判断是否存在SQL注入
-
工具扫描:网站漏扫工具、AWVS、AppScan、OWASP-ZAP、Nessus等
-
手动测试:
-
单双引号、括号;进行组合测试,看是否报错
-
对于数字型:?id=3-1 ?id=2#
如果显示的是?id=2时的正常页面,可判断注入点是数字型注入;如果返回不正常,则可判断非数字型注入
-
对于字符型:?id=2a ?id=2'#
Mysql 中,等号两边如果类型不一致,会发生强制类型转换。当数字与字符串进行比较时, 首先先将字符串转换成数字,然后再进行比较。
-
对于布尔盲注:
盲注:就是在服务器没有错误回显时完成的注入攻击。服务器没有错误回显,对于攻击者来说缺少了非常重要的信息,所以攻击者必须找到一个方法来验证注入的SQL语句是否得到了执行。
?id=1' and '1 ?id=1' and 'a
这里没有使用注释符号进行后面的单引号闭合,使用的是手工单引号闭合
或者, ?id=1' and 1=1# ?id=1' and 1=2#
两者的页面截然不同,一个正常回显,一个没有回显的话,就可判断是布尔盲注。
-
对于时间盲注:
?id=1' and sleep(3)#
在MySQL中,有一个Benchmark() 函数,它是用于测试性能的。 Benchmark(count,expr) ,这个函数执行的结果,是将表达式 expr 执行 count 次 。
因此,利用benchmark函数,可以让同一个函数执行若干次,使得结果返回的时间比平时要 长,通过时间长短的变化,可以判断注入语句是否执行成功。这是一种边信道攻击,这个技巧在 盲注中被称为Timing Attack,也就是时间盲注。
-
-
常见SQL注入功能点
只要是存在数据库交互的地方都有可能出现 SQL 注入。
常出现在 登录页面、订单页面、文章或新闻展示页面、修改密码页面(二次注入)、涉及获 取 HTTP 头(XFF等)的功能点等。
三、MySQL注入
-
必备
-
元数据库 information_schema
元数据库 information_schema 中:
存放数据库信息的表:schemata
schemata 表中
字段 schema_name 存放所有数据库名;
存放表信息的表:tables
tables 表中
字段 table_name 存放所有表名
字段 table_schema 存放所有表所在的数据库名;
存放所有字段信息的表:columns
columns 表中
字段 column_name 存放所有字段名,
字段 table_name 存放所有字段所在的表名,
字段 table_schema 存放所有字段所在的数据库名; -
语句分类
1.DQL(数据查询语言):查询语句,所有的 select 语句
2.DML(数据操作语言):insert , delete , update , 对表中的 数据 进行 增删改
3.DDL(数据定义语言):create , drop , alter 对表 结构 的 增删改
4.TCL(事务控制语言):commit 提交数据,rollback 回滚数据 Transaction
5.DCL(数据控制语言):grant 授权,revoke 撤销权限等 -
基本语句
# 查库:
show databases;
select schema_name from information_schema.schemata;
# 建库:
create database + 库名;
# 删库:
drop database + 库名;
# 进入数据库:
use + 库名;
# 查表:
show tables;
select table_name from information_schema.tables where table_schema='security'
select table_name from information_schema.tables where table_schema=database
# 查列:
select * from users;
select column_name from information_schema.columns where table_name='users'
# 查字段:
select username,password from security.users; -
基本函数
#数据库安装、路径,用户 信息
version(); Mysql 数据库版本
database(); 当前 数据库名
user(); 数据库的用户名
current_user(); 当前用户名
session_user(); 连接到数据库的用户名
system_user(); 系统用户名
@@datadir(); 数据库文件的存放路径
@@version_compile_os; 操作系统版本
@@basedir; 数据库的安装目录
#字符串长度、截取
length(); 返回字符串的长度
substring(a,b,c); 截取字符串
substr(a,b,c);
mid(a,b,c);
三个参数:a.截取的字符串 b.截取的起始位置 c.长度
left(a,b); 从左侧截取a的前b位,正确返回1,错误返回0
#字符串配对连接
concat(a,0x5e,b); 字符串配对连接
concat_ws('~',A,B); 含有分隔符的连接字符串
group_concat(); 将字符串连接为一个组,可将不同列分到同一行中
#字符串特殊处理
ord(); 返回ASCII码
ascii('a'); 将字母 a 转换为ascii值
rand(); 返回0~1之间的随机浮点数
round(); 返回最近的整数值
md5(); 返回MD5值
hex(); 将字符串转换为十六进制
unhex(); hex()的反向操作
floor(x); 返回不大于x的最大整数
load_file(); 读取文件,返回文件内容作为一个字符串
sleep(a); 沉睡a秒
if(true,t,f); 判断语句为true ,执行第一个,否则第二个
find_in_set(); 返回字符串在字符串列表中的位置
benchmark(); 指定语句执行的次数
name_const(); 返回表作为结果 -
导入数据
当希望导入一个 较大 的文件或者是想要批量的执行sql语句时,可以使用 mysql 中的 source 使用方法:source + 文件路径(直接拖拽)
-
-
语句
# insert
insert into 表名(字段名1,字段名2,字段名3......) values(值1,值2,值3......);
# delete
delete from 表名 where 条件;//可回滚
对于大表:
truncate table 表名;//不可回滚,将会永久丢失
# update
update 表名 set 字段名1=值1,字段名2=值2,......where 条件;# select
select 字段1,字段2,...... from + 表名 where + 条件;# between and
select * from users where id between 2 and 8;
select * from users where id >=2 and id <=8;# in not in
select password from users where id not in(5,8);
指查找出 id不等于5 和 id不等于8 的用户的密码
注:不是 5~8,in之后不是一个区间# like
1.% 代表任意多个字符
2._ 代表任意一个字符
select username from users where username like '%b%';
指查找出用户名中带有字母b的用户名
select username from users where username like '_a%';
指查找出用户名中带第二个字母为a的用户名
select username from users where username like '%b';
指查找出用户名中带最后一个字母为b的用户名
select username from users where username like '%\_%';
指查找出用户名中带有下划线_的用户名
注:特殊字符需要转义# order by
select username from users order by 字段名;
注:默认为升序排列
指定升序:asc
select username from users order by 字段名 asc;
指定降序:desc
select username from users order by 字段名 desc;
双重需求:
select username from users order by 字段名1 desc,字段名2 asc;# 分组函数
select sum(grade) from users;
select avg(grade) from users;
select max(grade) from users;
select min(grade) from users;# 空处理函数
select sum(ifnull(salary,0)*12), from crew;
求一年的薪水之和,当薪水为NULL时,被当作0来处理# group by 与 having
group by:按照某个字段或某些字段进行分组
having:对分组之后的数据进行再次过滤,即having 必须跟在 group by 后面使用
select max(grade) from students group by classes;
先根据班级分组,再查出各个班级的成绩最高学生的成绩
1.分组函数一般与 group by 联合使用,并且任何一个分组函数(count,sum,avg,max,min)都是堆一组数据进行操作的
2.当一条sql语句没有 group by 时,整张表会自成一组
3.当sql语句中使用group by时,select之后只能跟参与分组的字段或者分组函数# distinct 去重
distinct 关键字 去除重复记录
select distinct job from company;
查询该公司中的工作岗位# 语句执行顺序
select 5号:挑选出满足条件的数据
from 1号:定表
where 2号:过滤原始数据
group by 3号:进行分组
having 4号:对数据进行再次过滤
order by 6号:进行排序1.字符串数据 sum,avg 为 0,max,min 按字母大小取
2.分组函数会自动忽略 NULL
3.数学运算 中如果有NULL参与,结果为定为NULL
4.分组函数不能直接出现在 where 后面,原因是 group by 是在where语句执行结束之后执行的
5.分组函数可组合使用# inner join
select a.ename,b.dname from emp a join dept b on a.deptno=b.deptno;
# left/right join
select dname,ename from dept a left join emp b on a.deptno=b.deptno;or 语句:当前面语句不符合情况或者出现错误时执行or后面的内容