phpMyAdmin无内置登录日志,需通过Nginx access日志抓取/phpmyadmin/index.php等POST请求(含200/302状态),结合MySQL错误日志中“Access denied”记录交叉分析,并用ELK建会话链路模型检测爆破行为。

直接看 Nginx access 日志里的 /phpmyadmin/login 路径
ELK 本身不解析 PHP 应用逻辑,但 phpMyAdmin 的登录行为一定会打到 Web 服务器日志里。关键不是找“phpMyAdmin 登录成功”,而是抓所有对 /phpmyadmin/index.php、/phpmyadmin/login.php 或重写后 /phpmyadmin/ 的 POST 请求——尤其是状态码为 200 或 302 的那些。
真实攻击中,爆破成功后常跳转到 /phpmyadmin/main.php,所以也要监控首次跳转成功的 IP + User-Agent 组合是否异常(比如来自 Tor 出口节点、UA 是 curl/wget、无 Referer)。
- 在 Logstash 或 Filebeat 中,用
if [uri] == "/phpmyadmin/index.php" and [method] == "POST"提取登录尝试事件 - 加字段
phpmyadmin_login_attempt: true,便于 Kibana 过滤和告警 - 避免只依赖
status == 200:有些弱口令爆破工具会故意触发 302 跳转,而服务端返回 302 并不代表登录失败
用 Kibana Discover 筛选高频失败 + 单 IP 突增 200/302
攻击者爆破时,前几十次大概率是 401 或 200(页面返回登录表单),最后几次才是 302(跳转后台)。所以不能只盯失败,得把“失败密集 + 成功突现”串起来看。
在 Kibana Discover 中快速定位可疑行为:
立即学习“PHP免费学习笔记(深入)”;
- 时间范围设为最近 15 分钟,筛选
phpmyadmin_login_attempt: true - 按
clientip分组,看哪些 IP 的status为401的次数 > 30 次,且紧跟着出现302或200(非登录页) - 再叠加
http_user_agent: "sqlmap*"或http_user_agent: "python-requests"排除运维脚本 - 导出该 IP 所有请求 URI,确认是否后续访问了
/phpmyadmin/import.php或/phpmyadmin/export.php
关联 MySQL 错误日志中的 “Access denied” 记录
phpMyAdmin 登录失败 ≠ MySQL 认证失败,但登录成功一定经过 MySQL 验证。所以 ELK 里必须同时摄入 MySQL 错误日志(log_error 文件),并提取其中的 "Access denied" 行。
注意两点:
- MySQL 错误日志默认不记录完整 IP,只记
'user'@'host'中的host;若 Web 服务器与 MySQL 同机,host可能是localhost,无法反推攻击源——这时必须靠 Nginx 日志里的clientip去交叉比对 - 开启
general_log虽能记录连接,但性能损耗大,生产环境慎用;错误日志更轻量,且已足够捕获爆破特征 - 在 Logstash 中用 grok 匹配:
%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level}.*Access denied for user '%{DATA:user}'@'%{DATA:host}'
告警规则别只盯“单次成功”,要建会话链路模型
单纯对“某个 IP 登录成功”发告警,误报率极高——运维人员也会正常登录。真正危险的是:同一 IP 在 5 分钟内先有 20+ 次失败,然后成功,接着 2 分钟内访问 import.php + 执行 SQL 导入。
这需要在 Elastic 中用 EQL(Event Query Language)写检测逻辑,例如:
sequence by clientip [filebeat-* where phpmyadmin_login_attempt and status in (401, 200) and event.duration < 1000] with maxspan=3m [filebeat-* where phpmyadmin_login_attempt and status in (302, 200) and uri != "/phpmyadmin/index.php" and event.duration < 500] with maxspan=1m [filebeat-* where uri == "/phpmyadmin/import.php" and method == "POST"] with maxspan=2m
这种链路式检测比单点阈值更准,但也更消耗资源。上线前务必在测试索引上验证查询性能,避免拖慢整个集群。
最易被忽略的一点:phpMyAdmin 的登录表单可能被代理或 CDN 缓存,导致 Nginx 日志里的 clientip 是 CDN 节点 IP,而非真实攻击者 IP。必须确认 $realip_remote_addr 已正确配置并写入日志字段,否则所有分析都建立在错误源头上。



















