从盘古石杯CTF赛题出发:手把手教你用Navicat+SSH隧道连接Docker内网数据库(附实战避坑点)
内网数据库渗透实战:从CTF赛题到Navicat+SSH隧道的高级应用
当你在CTF比赛中拿到一个服务器镜像,发现它运行着Docker并开放了非常规端口时,如何快速定位并连接内网数据库?这不仅是比赛中的常见场景,也是真实安全运维中的必备技能。本文将带你从零开始,通过SSH隧道技术穿透Docker网络,用Navicat实现图形化操作,同时分享多个实战中积累的避坑经验。
1. 环境侦察与Docker网络拓扑分析
在开始连接之前,我们需要先理解目标环境的网络结构。通过几个关键命令,可以快速绘制出Docker的内网地图:
# 查看主机网络接口 ip a # 列出所有运行中的容器 docker ps -a # 检查特定容器的详细配置(替换64为你的容器ID) docker inspect 64 | grep -i 'db' -C 10典型Docker网络模式对比
| 网络模式 | IP分配特点 | 外部访问方式 | 适用场景 |
|---|---|---|---|
| Bridge | 172.17.0.0/16 | 端口映射或直接访问 | 默认模式,容器间隔离 |
| Host | 共享主机网络栈 | 直接使用主机IP | 高性能需求场景 |
| None | 无网络接口 | 无法直接通信 | 特殊安全需求 |
提示:当发现8065等非常规端口时,先用curl测试HTTP服务,再考虑数据库可能性。例如:
curl -v http://192.168.48.133:8065
在最近一次实战中,我们发现目标容器使用了Mattermost(一个开源通讯平台),其数据库凭证就存储在环境变量中。通过docker inspect输出的JSON结果里,搜索以下关键字段往往会有收获:
Env(环境变量)Config.Cmd(启动命令)Mounts(挂载点)
2. SSH隧道配置的进阶技巧
建立SSH隧道是连接内网数据库的核心技术,但实际操作中会遇到各种意外情况。以下是经过多个CTF比赛验证的可靠配置流程:
本地SSH配置优化
编辑~/.ssh/config文件,添加以下参数防止连接中断:Host jump_server HostName 192.168.48.133 User root ServerAliveInterval 60 TCPKeepAlive yes Compression yes动态端口转发实战
对于需要探索多个内网服务的情况,推荐使用动态转发:ssh -D 1080 jump_server然后在Navicat的SOCKS代理设置中填入
localhost:1080常见连接失败排查清单:
- 检查SSH服务是否允许TCP转发(/etc/ssh/sshd_config中
AllowTcpForwarding应为yes) - 确认Docker容器的网络策略未限制出站连接
- 验证数据库用户是否具有远程登录权限(MySQL的%通配符问题)
- 检查SSH服务是否允许TCP转发(/etc/ssh/sshd_config中
隧道类型选择指南
| 隧道类型 | 命令示例 | 适用场景 | Navicat配置要点 |
|---|---|---|---|
| 本地端口转发 | ssh -L 3306:172.17.0.2:3306 user@host | 单一服务访问 | 直接连接localhost:3306 |
| 远程端口转发 | ssh -R 3306:localhost:3306 user@host | 从外网访问内网 | 需配合服务端防火墙规则 |
| 动态转发 | ssh -D 1080 user@host | 多服务探索 | 需配置SOCKS代理 |
3. Navicat高级连接配置详解
有了SSH隧道后,Navicat的连接配置也有讲究。以下是经过大量实战验证的参数组合:
SSH选项卡:
- 主机名:跳板机的公网IP(如192.168.48.133)
- 身份验证:优先选择密钥认证(更安全)
- 端口:通常为22,但注意有些CTF环境会修改默认端口
数据库连接选项卡:
- 连接名:建议包含环境标识(如"CTF_MySQL_Prod") - 主机:**容器内网IP**(如172.17.0.2) - 端口:数据库真实端口(非映射端口) - 用户名/密码:从docker inspect或环境变量获取
注意:遇到"Client does not support authentication protocol"错误时,尝试在MySQL容器内执行:
ALTER USER 'username'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
Navicat性能优化参数
| 参数项 | 推荐值 | 作用说明 |
|---|---|---|
| 连接超时 | 30秒 | 避免网络波动导致UI假死 |
| 保持连接间隔 | 240秒 | 防止SSH超时断开 |
| 查询超时 | 0(无限制) | 大数据量导出时不中断 |
| 使用压缩 | 启用 | 节省带宽,提升响应速度 |
4. 实战中的高阶技巧与应急方案
即使按照标准流程操作,真实环境中仍会遇到各种意外。以下是几个典型场景的解决方案:
场景一:Docker使用自定义网络
# 发现容器使用了自定义网络 docker network ls # 查看该网络详情 docker network inspect network_name # 获取容器在该网络中的IP docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name场景二:数据库端口未对外暴露当docker ps显示没有端口映射时,可以尝试以下方法:
- 在容器内安装
netcat临时暴露端口:docker exec -it container_id bash apt update && apt install -y netcat nc -lkp 3306 -e /usr/bin/mysql - 通过
docker commit创建新镜像并重新运行
场景三:Navicat连接成功但无法显示表这通常是权限问题,尝试以下SQL:
GRANT SELECT ON *.* TO 'user'@'%'; FLUSH PRIVILEGES;数据库取证快速检查清单:
- 检查
information_schema中的PROCESSLIST表查看当前连接 - 查询
mysql.user表获取所有用户权限 - 查看
general_log是否开启(如有则包含完整操作记录) - 搜索包含"password"的环境变量:
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' container_id | grep -i pass
在最近参与的盘古石杯比赛中,我们就是通过分析数据库中的时间戳字段,成功定位到了攻击者的操作时间线。Mattermost数据库的Posts表中存储的编辑历史,成为了取证的关键证据。
