今天,我服务器上的mysql被攻击了,其他数据库全没了,多了一个数据库recover_data数据库,我点开数据库看了一下,里面存了一句勒索的话,如果要恢复数据,访问某网址支付比特币,大概是要勒索我18000块左右的人民币。瞬间人麻了,顿时给我敲响了一个警钟,数据安全不是等开发好项目上线后才考虑,而是在项目落地的那一刻起就要重视起来,打战粮草先行,开发安全先做。话不多说,解决问题!
第一步:恢复数据
- 执行我们原来备份好的数据库脚本
如果MySQL数据没有备份,以下有几种比较有效的方法:
使用MySQL的二进制日志: 如果你启用了MySQL的二进制日志(binlog),你可以使用这些日志文件来恢复数据。二进制日志记录了所有对数据库的更改,你可以将这些日志应用到当前数据库中来恢复数据。具体步骤包括:
使用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
- 参数解释: 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的方式请自行了解这里简单介绍,不做过多的解释
开始恢复数据:

- 执行语句: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,重新安装,因为我们不清楚黑客入侵后是否植入了病毒或其他脚本,为他再次攻击提供便利,所以 为了安全起见和避免一些不必要的麻烦,我们卸载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日志功能。
最后
如果某一天你也很不幸数据库被黑客攻击了,不要慌,我们首先要做的就是把损失降到最低,先把数据恢复,然后备份数据,在清理环境,做数据安全防护措施,千万不要点击黑客的连接,对其付款进行恢复数据,这不是解决问题的办法,黑客可能还会继续勒索。继续黑你数据库。我们被黑了数据库是不幸的同时也是幸运的,因为他的攻击只会让我们变得更强,最后我想说,让暴风雨来得更猛烈些吧!!!!
- 关主我不迷路,愁哥带你上高速!
评论前必须登录!
注册