今天,我服务器上的mysql被攻击了,其他数据库全没了,多了一个数据库recover_data数据库,我点开数据库看了一下,里面存了一句勒索的话,如果要恢复数据,访问某网址支付比特币,大概是要勒索我18000块左右的人民币。瞬间人麻了,顿时给我敲响了一个警钟,数据安全不是等开发好项目上线后才考虑,而是在项目落地的那一刻起就要重视起来,打战粮草先行,开发安全先做。话不多说,解决问题!
第一步:恢复数据
- 执行我们原来备份好的数据库脚本
如果MySQL数据没有备份,以下有几种比较有效的方法:
-
使用MySQL的二进制日志:
如果你启用了MySQL的二进制日志(binlog),你可以使用这些日志文件来恢复数据。二进制日志记录了所有对数据库的更改,你可以将这些日志应用到当前数据库中来恢复数据。具体步骤包括:- 找到合适的二进制日志文件。
- 使用
mysqlbinlog工具将日志应用到数据库中。 - 根据需要进行数据恢复。
-
使用InnoDB的undo日志:
对于使用InnoDB存储引擎的表,InnoDB会在内部维护undo日志。虽然这些日志主要用于事务回滚,但在一些情况下,也可能用于恢复数据。这种方法非常复杂且不总是有效,通常需要借助专业工具或技术支持。 -
恢复数据的第三方工具:
有一些第三方数据恢复工具可以尝试从损坏的数据库文件中恢复数据。比如:
MySQL Recovery Tools:这些工具可以分析损坏的数据库文件,尝试恢复表数据。
Percona Data Recovery Tools:Percona 提供了一些用于数据恢复的工具和方法。 -
检查操作系统的文件系统快照:
如果你使用的是文件系统支持快照功能(如ZFS、Btrfs等),可以检查是否有快照可用于恢复数据。 -
寻求专业团队帮助:
如果数据非常重要且上述方法无法解决问题,考虑寻求专业的数据恢复服务,他们可能会有更多的工具和技术来尝试恢复数据。
为了避免数据丢失问题,建议定期备份数据库,并将备份保存在安全的地方。设置自动备份机制可以显著降低数据丢失的风险。
以下演示没有备份的情况下,通过binlog日志恢复数据,其他方式自行了解,这里不做过多的赘述
- 通过binlog日志恢复数据的前提是你的mysql必须开启binlog功能,如何开启?在mysql的配置文件中配置即可,即在my.cnf中配置
- 在【mysqld】下添加配置
log-bin=/usr/local/log/mysql-bin
binlog_format=mixed
server-id= 1
- 在【mysqld】下添加配置
- 参数解释:
log-bin=binlog日志的存放路径
binlog_format有三种方式分别为:
STATEMENT: 记录 SQL 语句,文件较小,但可能恢复不一致。
ROW: 记录每行数据,保证一致性,但日志文件较大。
MIXED: 自动选择模式,兼顾性能和一致性。
server-id= 1:server-id是 MySQL 配置中的一个参数,用于唯一标识每个 MySQL 服务器实例。设置server-id = 1的意思是将当前 MySQL 服务器的 ID 设置为 1。
1. 唯一标识: 确保每个 MySQL 服务器在主从复制或集群中有唯一 ID。
2. 复制配置: 在设置主从复制时,每个服务器都必须有不同的server-id。
3. 格式: 必须是一个正整数,且在同一复制环境中必须唯一。 - 更多关于binlog_format的方式请自行了解这里简单介绍,不做过多的解释
开始恢复数据:
- 找到binlog文件,一般为mysql-bin.0000xx,
- 提取最新的binlog日志,看看做了哪些操作,我们需要恢复到那个时间节点?
- 提取指令:
mysqlbinlog --stop-datetime=“2024-08-12 19:17:59” /www/server/data/mysql-bin.000034 > /tmp/recovery.sql
然后打开recovery.sql查看我们需要恢复到哪个时间节点

显然我们可以看到删除数据库的时间是20240812 19:16:11开始,那么我们只需要提取20240812 19:16:11这个节点之前的数据即可。
- 执行语句:mysqlbinlog --stop-datetime=“2024-08-12 19:16:10” /www/server/data/mysql-bin.000034 > /tmp/recovery.sql
- 接着在/temp/目录下我们会得到一个提取后的recovery.sql脚本,最好是打开来看看是否有包含了删除删除数据库的语句,有的话自行删掉即可。如下图所示:

- 恢复数据前:

接着我们恢复数据:mysql -u root -p < /tmp/recovery.sql 回车输入mysql的密码即可恢复成功!!! - 数据恢复后:

执行mysqlbinlog --stop-datetime=“2024-08-12 19:16:10” /www/server/data/mysql-bin.000034 > /tmp/recovery.sql如果报错mysqlbinlog: command not found 有两个原因导致:
- 没有安装mysql-client
查看mysql的bin目录下是否存在mysqlbinlog,如果存在就是没有配置环境变量导致的,如果不存在则是因为没有安装msyql-client - 没有配置环境变量,配置如下:
一般情况下linux的profile文件存在于/etc目录下,打开vim /etc/profile 然后添加配置项export PATH=$PATH:/mysqlbinlog的存放路径例如export PATH=$PATH:/usr/local/mysql/bin/mysqlbinlog然后esc :wq保存并退出
接着执行source 你的profile路径例如:source /etc/profile 即可使配置生效,验证:输入mysqlbinlog出现如下图所示即为配置成功!

第二步:数据安全
- 备份刚刚恢复的数据,然后卸载mysql,重新安装,因为我们不清楚黑客入侵后是否植入了病毒或其他脚本,为他再次攻击提供便利,所以 为了安全起见和避免一些不必要的麻烦,我们卸载msyql,以免夜长梦多。
- 修改mysql数据的用户名和密码,密码建议英文大小写加数字加特殊符号,不要用纯数字。这样容易被黑客通过端口扫描工具获取端口并暴力破解。
- 将远程连接授权关闭。即将msyql配置文件中的bind-address=0.0.0.0改为127.0.0.1或者其他地址,然后将user表中的host 的%改为localhost,这样我们就关闭了远程连接。这样我们的端口不至于暴露在公网上被端口扫描工具扫到。
- 开启防火墙:
sudo systemctl start firewalld启动 firewalld 服务。sudo systemctl enable firewalld设置开机自启动。
然后通过放行端口的方式将需要开放的端口开放,开放指令:例如开放80端口sudo firewall-cmd --permanent --add-port=80/tcp
重新加载配置sudo firewall-cmd --reload,查看确认规则已添加sudo firewall-cmd --list-all如下图所示即为你开放的端口
- 将服务器中不需要用到的端口号关闭,只开需要用到的端口号,这样通过防火墙和服务器的安全组双重防护,我们的数据安全又多了一份保障
第三步:解决远程连接
- 我们虽然关闭了远程连接,但是我们可以通过本地跟远程服务器建立起一个隧道,通过隧道进行远程连接
配置隧道
- 下载隧道配置工具putty,下载地址putty


- 下载好了之后我们打开putty配置


注意!这里是填localhost:远端端口 ,例如我的远端mysql是13309,这里配置就是localhost:13309,而不是服务器ip:13309,
source port 填本地端口,随便填,这里我填3307.解释一下为啥这里是loaclhost,这里的localhost并不是我们以为的localhost(127.0.0.1)而是远端的ip地址,putty隧道会默认将destination中的localhost解析为远端服务器ip地址。另外强调一点,source port 不要用3306因为可能你本地有数据库并且端口为3306那么就会连接到你本地的mysql。所以建议配置除了3306以外的其他端口,避免和本地mysql冲突。隧道打通之后我们就可以用任何数据库用户连接数据库了。 - 做好以上配置后需要回到session中保存配置,给这个配置取个名,即填写Saved Sessions这里我叫msql,保存后我们就不用每次要连接都要配置一下,直接双击我们配置好的名称即可连接远端如下图所示:


-双击或者点击Open进行连接,第一次连接会有这个弹框点击accept就可以了以后不会再弹框。如下图所示

- 登录服务器 填写服务器的用户名和密码,用户名一般为root,如下图所示


- 登录好之之后接着用navicat测试连接如下图所示


- 到此我们实现了远端连接,避免了将端口号暴露在公网上,给黑客有可乘之机。
数据备份
- 但我们解决好上述问题后,我们还需要做的是做好数据备份,定期备份,最好是有全量和增量的定期备份开启定时任务每天备份到安全的地方,这样我们可以自己多一份保障,并不是任何时候都能通过binlog恢复数据的,所以只要我们能够想到的办法都要用上,不给黑客一点攻击的可能。
- 以下是我备份的示例
- 创建一个工具类
public class MysqlBackupUtil {
public static void backupData(String host, int port, String username, String password, String database,
String backupDirectoryPath) throws IOException {
String command = String.format("mysqldump -h %s -P %d -u %s -p%s %s -r %s", host, port, username, password,
database, backupDirectoryPath);
Process process = Runtime.getRuntime().exec(command);
int exitCode;
try {
exitCode = process.waitFor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("备份过程被中断", e);
}
if (exitCode != 0) {
throw new IOException("备份 MySQL 数据失败");
}
}
public static void backupTableData(String host, int port, String username, String password, String database,
String backupDirectoryPath,String tables ) throws IOException {
String command = String.format("mysqldump -h %s -P %d -u %s -p%s %s -r %s %s", host, port, username, password,
database, backupDirectoryPath,tables);
Process process = Runtime.getRuntime().exec(command);
int exitCode;
try {
exitCode = process.waitFor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("备份过程被中断", e);
}
if (exitCode != 0) {
throw new IOException("备份 MySQL 数据失败");
}
}
}
数据库备份的定时任务实现方法
public void MysqlBackupTask(String host,Integer port,String username, String password,String database,String backupDirectoryPath)
{
try {
MysqlBackupUtil.backupData(host, port, username, password, database, backupDirectoryPath);
try {
uploadFile(backupDirectoryPath);
deleteTableFile(backupDirectoryPath,-2);
} catch (Exception e) {
throw new RuntimeException(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void MysqlBackupTableTask(String host,Integer port,String username,String password,String database, String backupDirectoryPath,String tables)
{
try {
MysqlBackupUtil.backupTableData(host, port, username, password, database, backupDirectoryPath,tables);
try {
uploadFile(backupDirectoryPath);
deleteTableFile(backupDirectoryPath,-1);
} catch (Exception e) {
throw new RuntimeException(e);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void uploadFile(String backupDirectoryPath) throws Exception {
String endpoint ="服务器endpoint"; // 例如:http://oss-cn-hangzhou.aliyuncs.com
String accessKeyId = "这里填你自己的服务器accessKeyId";
String accessKeySecret ="这里填你自己的服务器accessKeySecret";
String bucketName = "服务器bucket桶名称";
String objectName = backupDirectoryPath+"/"+ DateUtils.datePath()+"/"+backupDirectoryPath; // 上传到 OSS 后的文件名
String localFilePath = backupDirectoryPath; // 本地文件路径
// 创建 OSSClient 实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 上传文件到服务器oss
ossClient.putObject(bucketName, objectName, new File(localFilePath));
// 关闭 OSSClient
ossClient.shutdown();
}
- 获取accessKeyId和accessKeySecret 如下图所示

- 接着创建一个bucket桶



- 填写完以上信息即可完成bucket创建接着实现数据备份
备份的文件是按日期每天一个文件夹进行备份的,您可以自行修改,如图所示

- 每天都有一个sql文件的备份,即使我们的binlog恢复不了我们还能通过备份的方式,恢复我们的数据,备份恢复也更加直接方便快捷,赶紧备份起来吧!!!

总结
当我们发现数据库被黑时
- 第一步:恢复数据
- binlog 恢复
- 备份文件恢复
- 第二步:做数据安全防护
- 卸载mysql,重装
- 修改用户名密码(字母大小写数据加特殊符号)
- 关闭安全组不用的端口号
- 开启防墙
- 关闭msyql远程访问授权(修改bind-address=0.0.0.0)
- 修改mysql用户的host为%的改为localhost或者其他地址。
- 需要远程连接可以通过隧道的方式进行连接
- 第三步:数据备份
- 开启定时任务,定时备份全量和增量数据
- 开启msyql的binlog日志功能。
网络安全学习资源分享:
给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,需要点击下方链接即可前往获取
读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)
👉1.成长路线图&学习规划👈
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


👉2.网安入门到进阶视频教程👈
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。(全套教程文末领取哈)


👉3.SRC&黑客文档👈
大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录
SRC技术文籍:

黑客资料由于是敏感资源,这里不能直接展示哦!(全套教程文末领取哈)
👉4.护网行动资料👈
其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

👉5.黑客必读书单👈

👉6.网络安全岗面试题合集👈
当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。

所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~
读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)
除。

3180

被折叠的 条评论
为什么被折叠?



