0x01 前言
最近在 Docker Desktop 上搭建 Pikachu 靶场进行渗透练习,在配置数据库连接时遇到了一系列非常经典的问题。
从“Web 端连接不上”到“Navicat 连不上”,再到“SQL 授权报错”,每一步都是坑。本文将详细记录解决过程和背后的原理,希望能帮到同样遇到这些问题的同学。
环境信息:
- 宿主机: Windows (Docker Desktop)
- 镜像:
area39/pikachu - 启动命令:
docker run -d -p 8899:80 -p 3307:3306 --name pikachu area39/pikachu - 端口映射:
- Web: 本地 8899 -> 容器 80
- MySQL: 本地 3307 -> 容器 3306
0x02 踩坑一:Navicat 远程连接报错 1045
1. 现象
Web 端配置好后,我想用本地的 Navicat 管理靶场数据库。
连接配置:主机 127.0.0.1,端口 3307,用户 root,密码空。
点击测试连接,报错:
1045 – Access denied for user ‘root’@’172.17.0.1’ (using password: NO)
2. 原理分析 (MySQL 的用户隔离)
这里最容易产生误解:“我在容器里明明是 root,为什么在外面就不认了?”
MySQL 的用户鉴权是基于 用户名 + 来源主机 的。
- root@localhost: 这是给容器内部 PHP 用的,它只允许本地连接。
- root@% (或 root@172.xx): 当你用 Navicat 连接宿主机的 3307 端口时,Docker 会把流量转发进容器。对于容器内的 MySQL 来说,这个请求来自于 Docker 网关 IP (如 172.17.0.1),而不是 localhost。
MySQL 默认的安全策略通常 禁止 root 用户从远程(非本地)登录。报错提示 Access denied 就是因为数据库里没有允许远程 IP 登录的 root 账号。
0x03 踩坑二:SQL 授权报错 1133
1. 尝试修复 (失败)
为了解决 Navicat 连接问题,我进入容器尝试给 root 用户授权远程访问:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '' WITH GRANT OPTION;
结果报错:
ERROR 1133 (42000): Can’t find any matching row in the user table
2. 原理分析 (SQL Mode 限制)
这个报错的意思是:在用户表中找不到匹配的行 。
在 MySQL 5.7 及更新版本中,默认开启了 NO_AUTO_CREATE_USER 模式。这意味着 GRANT 命令 不再支持隐式创建用户 。
也就是说:你想给 root@% 授权,但 root@% 这个人根本不存在,你得先把他“造”出来,才能给他“发证件”。
0x04 终极解决方案 (正确步骤)
综合以上分析,要在 Docker 环境下完美配置 Pikachu 数据库,需要执行以下标准操作:
第一步:进入容器终端
docker exec -it pikachu /bin/bash
第二步:登录 MySQL
mysql -u root -p
# 密码默认为空,直接回车
第三步:创建远程用户并授权 (关键)
在 mysql> 提示符下依次执行:
1. 显式创建远程用户 (解决报错 1133)
-- 创建一个名为 root 的用户,允许从任意 IP ('%') 登录,密码为空
CREATE USER 'root'@'%' IDENTIFIED BY '';
2. 赋予所有权限 (解决报错 1045)
-- 给这个新用户赋予超级管理员权限
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
3. 刷新权限
FLUSH PRIVILEGES;
4. 退出
exit
0x05 总结
这次排查过程本质上是对 Docker 网络模型 和 MySQL 权限体系 的一次复习:
- 身份隔离: MySQL 中
root@localhost和root@%是两个完全不同的账号,默认通常只有前者。 - 语法严谨: 在新版 MySQL 中,必须先
CREATE USER再GRANT,不能偷懒一步到位。
配置完成后,Navicat 成功连接,靶场 Web 端也能正常初始化,环境搭建完毕!🚀
