PAYATHON 2026

Wordpress 被黑:登录或支付成功后跳转到外部网站

支付小周

明确结论

这不是 WordPress 的正常行为。登录或支付成功后跳转到陌生域名,通常说明网站被植入了恶意重定向代码,或者服务器、DNS、支付平台中的返回地址遭到篡改。

即使禁用了普通插件、切换了主题,也搜索不到完整域名,仍然不能排除网站已被入侵。恶意代码可能藏在 mu-plugins、WordPress 核心文件、服务器配置、数据库序列化数据、计划任务或站外加载的 JavaScript 中。目标域名也可能经过 Base64、字符串拼接或十六进制编码,甚至由远程服务器动态返回。

不要只删除发现的跳转代码。应先暂停交易并保留现场,再从可信来源重建网站,同时更换所有凭据。

先判断重定向发生在哪里

先确认跳转是由服务器通过 HTTP 重定向返回,还是页面加载后由浏览器执行 JavaScript 触发。

可以在终端检查登录页和支付完成页的响应头:

curl -I https://topvegans.com/wp-login.php
curl -IL https://topvegans.com/wp-login.php

如果支付完成页要求登录或依赖特定订单状态,应在浏览器开发者工具的 Network 面板中检查:

  • 响应状态为 301、302、303、307 或 308 时,查看响应中的 Location。
  • 如果原页面先正常加载,过一会儿才跳转,应重点检查 JavaScript、Service Worker 和第三方脚本。
  • 如果只有部分设备、访客或特定来源会触发跳转,恶意代码可能会根据 Cookie、IP、User-Agent、Referer 或订单状态判断是否执行。

还应使用无痕窗口、另一台设备和另一个网络复测,排除浏览器扩展、缓存或本地 DNS 污染。

立即采取的措施

问题发生在支付成功后,应暂时关闭结账功能,或将网站切换到维护状态,避免客户继续被导向恶意页面。

接着处理以下事项:

  1. 为当前文件、数据库、Web 服务器日志和访问日志制作只读备份,以便后续调查。
  2. 在可信设备上修改主机面板、SSH、SFTP、数据库、WordPress 管理员、支付平台和 DNS 账户的密码。
  3. 启用多因素认证。
  4. 撤销未知的 API Key、应用密码、部署密钥和活跃会话。
  5. 联系支付服务商,确认账户中的成功页、回调地址和 Webhook 地址有没有被修改。
  6. 检查是否出现了未知管理员,以及订单、客户资料或支付数据是否可能泄露。

如果网站处理真实交易,还应根据支付服务商、主机商和适用法规的要求,评估是否需要报告安全事件。

检查 WordPress 地址配置

先在数据库中确认 home 和 siteurl 的值:

SELECT option_name, option_value
FROM wp_options
WHERE option_name IN ('home', 'siteurl');

数据表前缀不一定是 wp_,应以 wp-config.php 中的 $table_prefix 为准。

正常情况下,两项都应指向网站自己的域名,例如:

https://topvegans.com

同时检查 wp-config.php 是否覆盖了数据库设置:

define('WP_HOME', 'https://topvegans.com');
define('WP_SITEURL', 'https://topvegans.com');

只有确认站点确实使用这个地址后,才能添加或修改这两项。它们可以纠正错误的 WordPress 基础地址,但不能清除恶意程序。

还要检查 PHP 或服务器环境中是否存在异常的 HTTP_HOST、代理头或强制跳转规则。如果站点位于 CDN、反向代理或负载均衡器之后,错误的代理配置也可能生成异常 URL。不过,固定跳转到无关域名更像是网站遭到了入侵。

不要只搜索完整域名

攻击代码未必会直接保存完整的 cartoonmines.com/scount。搜索时应扩大范围,包括:

cartoonmines
scount
base64_decode
gzinflate
str_rot13
eval(
assert(
shell_exec
passthru
proc_open
preg_replace
Location:
window.location
location.href
document.location
atob(
String.fromCharCode

发现这些字符串不等于发现了恶意代码。例如,正常软件也可能使用 base64_decode(),需要结合文件位置、代码上下文和修改时间判断。

还要注意通过字符串拼接生成的地址:

$host = 'cartoon' . 'mines' . '.com';
header('Location: https://' . $host . '/scount');
exit;

以及经过编码的跳转:

window.location.href = atob('aHR0cHM6Ly9leGFtcGxlLmNvbS8=');

不要运行来源不明的解码结果。只能在隔离环境中把它当作文本分析。

检查禁用插件时仍会执行的位置

在 WordPress 后台选择“禁用所有插件”,并不能关闭所有可执行入口。需要重点检查:

  • wp-content/mu-plugins/
  • wp-content/advanced-cache.php
  • wp-content/object-cache.php
  • wp-content/db.php
  • wp-content/sunrise.php
  • wp-config.php
  • 网站根目录的 index.php
  • .htaccess
  • .user.ini
  • php.ini
  • Web 服务器的 Nginx 或 Apache 配置
  • 主机面板设置的自动追加文件
  • WordPress 核心目录中的异常 PHP 文件
  • 上传目录中的 .php、.phtml、.phar 等可执行文件

尤其要检查 .user.ini 或 PHP 配置中是否包含:

auto_prepend_file=/path/to/unknown-file.php
auto_append_file=/path/to/unknown-file.php

这类配置会让恶意文件在每个 PHP 请求之前或之后执行,所以切换主题、停用插件都不会使其失效。

在 Apache 配置中,还要检查类似规则:

RewriteRule ^wp-login\.php https://example.com/scount [R=302,L]

也要留意根据 Cookie、Referer 或查询参数匹配的条件规则。

校验并替换 WordPress 核心文件

如果可以使用 WP-CLI,可通过以下命令校验核心文件:

wp core verify-checksums

对于来自 WordPress.org 的插件,也可以尝试:

wp plugin verify-checksums --all

校验失败不一定说明文件是恶意的,因为部分商业插件、定制包或语言文件没有可用的校验值。但如果核心文件校验失败,必须认真处理。

更可靠的处理方法是:

  1. 保留 wp-config.php 和检查过的用户上传内容。
  2. 从 WordPress 官方来源下载对应的可信版本。
  3. 完整替换 wp-admin、wp-includes 和根目录中的核心文件。
  4. 从开发商或官方市场重新安装插件和主题,不要复用现场中的 PHP 文件。
  5. 删除不再使用的插件和主题,不要只停用。
  6. 检查 wp-content/uploads。正常情况下,上传目录不应包含可执行 PHP 文件。

不要直接用一份可能已被感染的旧备份覆盖网站。恢复前要确认备份早于入侵时间,并在恢复后立即修补最初的入侵入口。

检查数据库中的隐藏配置

完整域名可能藏在序列化数据、JSON、Base64 内容或拆分后的字段中。除了 wp_options,还要检查:

  • 未知管理员账户
  • 用户元数据中的权限提升
  • 自动加载的异常选项
  • 页面、区块、小工具和自定义 HTML
  • 订单完成页配置
  • 支付插件的返回 URL
  • 注入了脚本的文章或模板数据

检查管理员:

SELECT ID, user_login, user_email, user_registered
FROM wp_users;

检查具有管理员权限的用户时,要注意数据表前缀:

SELECT user_id, meta_key, meta_value
FROM wp_usermeta
WHERE meta_key LIKE '%capabilities%';

查找可疑的自动加载配置:

SELECT option_id, option_name, LENGTH(option_value) AS value_length
FROM wp_options
WHERE autoload = 'yes'
ORDER BY value_length DESC
LIMIT 50;

不要使用普通 SQL 全文替换直接修改序列化数据,否则可能破坏其中的长度信息。处理序列化字段时,应使用能够识别 WordPress 序列化格式的工具,并提前备份数据库。

检查计划任务和持久化机制

攻击者可能利用计划任务反复写回恶意代码。先查看 WordPress Cron:

wp cron event list

然后检查系统级计划任务、主机面板定时任务和部署脚本。重点关注:

  • 执行陌生 PHP 文件的任务
  • 定期下载远程脚本的任务
  • 定期修改 .htaccess、wp-config.php 或插件文件的任务
  • 名称模仿 WordPress 更新任务,但回调函数不存在或来源不明的事件

如果删除的文件很快又出现,通常说明网站中仍有后门或计划任务,也可能是控制面板凭据已经泄露。

检查登录后的重定向逻辑

正常插件可能通过以下钩子修改登录后的地址:

add_filter('login_redirect', function ($redirect_to, $requested, $user) {
    return home_url('/');
}, 10, 3);

这段代码只能用于临时诊断,或在确认业务需求后使用。它无法阻止发生得更早的服务器重定向,也不能修复后门。

还要检查代码中是否调用了:

wp_redirect($url);
wp_safe_redirect($url);
header('Location: ' . $url);

wp_safe_redirect() 默认会限制外部主机,但攻击者可以修改允许的主机列表,也可以直接使用 wp_redirect()、header() 或 JavaScript 绕过限制。检查是否存在异常的:

add_filter('allowed_redirect_hosts', ...);
add_filter('login_redirect', ...);
add_action('wp_login', ...);
add_action('template_redirect', ...);

如果只有管理员登录后才发生跳转,还应检查管理后台页脚脚本、管理员专用钩子和用户资料中的异常字段。

检查支付成功后的返回链路

支付流程通常涉及多个地址,需要逐一确认:

  • 用户支付完成后的浏览器返回地址
  • 支付取消地址
  • 服务器端 Webhook 或 IPN 地址
  • 商店中的“订单已收到”页面
  • 支付平台后台配置的默认成功页
  • 支付插件保存的网关配置
  • 自定义结账代码或支付服务商托管页面

Webhook 是服务器之间使用的通知地址,通常不应成为用户浏览器最终访问的页面。不要为了消除跳转而随意修改 Webhook,否则订单状态可能无法更新。

使用浏览器 Network 面板记录完整的跳转链,可以判断外部地址是由哪一环返回的:

支付平台 → 商店回调地址 → 订单完成页 → 外部域名

如果外部地址由支付平台直接返回,应检查支付平台账户,以及交易请求中提交的 return_url、success_url 或同类参数。不同网关使用的参数名称不同,在不知道支付服务商的情况下不能统一判断。

检查站外脚本、DNS 和浏览器持久化

如果服务器响应中没有 Location,应检查页面加载的所有第三方资源,尤其是:

  • 不认识的 JavaScript 域名
  • 被篡改的统计代码
  • Google Tag Manager 或类似标签管理器
  • 聊天、广告和转化追踪脚本
  • 远程字体或脚本加载器
  • 仅在支付完成页加载的脚本

如果标签管理平台账户被盗,恶意代码可能完全不会出现在 WordPress 文件或数据库中。

同时核对:

  • DNS 的 A、AAAA、CNAME 和 NS 记录
  • CDN 的重定向规则、Workers 或边缘函数
  • 主机面板的域名转发
  • 反向代理规则
  • Service Worker

在浏览器开发者工具的 Application 面板中注销可疑的 Service Worker,清除该站点的存储后再测试。如果只有某台设备出现问题,还应禁用浏览器扩展,并检查系统代理和 DNS 设置。

修复后的收尾工作

确认跳转已经消失后,还要完成以下工作:

  1. 更新 WordPress、插件、主题和服务器软件。
  2. 删除未知管理员、废弃账户和不必要的应用密码。
  3. 重新生成 WordPress salts,并强制所有用户退出。
  4. 检查文件所有者和权限,避免 Web 进程随意修改不需要写入的目录。
  5. 禁止上传目录执行 PHP。
  6. 检查支付订单、管理员操作和登录日志。
  7. 持续监控一段时间,关注文件变化、计划任务、外连请求和异常登录。
  8. 对可能涉及的客户数据和密钥进行风险评估。

新的 salts 可以通过 WordPress 官方密钥服务生成,然后替换 wp-config.php 中对应的常量。替换后,现有登录会话会失效,这是正常现象。

最稳妥的恢复方法,是在干净环境中重新部署 WordPress,安装来自可信来源的扩展,只迁移检查过的数据和媒体文件,而不是继续在原站点中逐段寻找并删除可疑代码。只要还有一个后门没有被发现,外部跳转就可能再次出现。

备注:内容仅供参考。