我已经数不清有多少次客户带着同样的故事找到我们:"我们的 WordPress 网站被黑了。我们清理了它。它又被黑了。我们放弃了。" 最近的一个是一家中等规模电商公司,他们的 WooCommerce 商店被注入了信用卡窃取程序,隐藏在看似合法的插件更新中。他们泄露了客户支付数据三周才被发现。这不是边界情况。这就是 2026 年 WordPress 生态系统的日常。

本文并不是在抨击 WordPress。它之所以能够支撑网络的很大一部分是有原因的。但是让它在 2005 年可访问的架构,正是让它在 2026 年成为自动化攻击磁石的原因。如果你已经被黑过——或者你已经厌倦了在安全插件上花钱,而这些插件本身就是攻击向量——这是你迁移到更安全系统的行动手册。

目录

WordPress 被黑了?迁移到 Next.js + Supabase 是你最好的解决方案

WordPress 安全问题的架构根源

让我明确说一点:WordPress 核心团队做了扎实的安全工作。WordPress 核心,保持更新,是相当安全的。但没有人只是运行 WordPress 核心。平均的 WordPress 网站安装了 20-30 个插件。每一个都是你没有写的依赖,由你不认识的人维护,可以访问你的数据库、文件系统和用户数据。

这是在"WordPress 安全最佳实践"文章中经常被忽略的关键点:问题不在于 WordPress 网站所有者疏忽。问题在于 WordPress 的架构要求你直接在服务器上安装来自第三方的可执行 PHP 代码来获得基本功能。这相当于给每一个在你家工作的承包商永久复制你的房钥匙。

WPScan 的漏洞数据库在 2024 年追踪了超过 7,900 个新的 WordPress 漏洞,其中大约 96% 来自插件。Sucuri 的 2024 年威胁报告发现,WordPress 占他们清理的所有 CMS 感染的大约 95%。Patchstack 报告称,2024 年 33% 的严重 WordPress 漏洞在披露时没有补丁可用。

这些不是可以通过更好的编码实践修复的错误。它们是架构本身的涌现特性。

2026 年常见的 WordPress 攻击向量

在我们谈论修复之前,让我们列举一下你实际上在防御什么。我个人已经审查过数十个被攻破的 WordPress 网站,攻击遵循可预测的模式。

通过插件的 SQL 注入

WordPress 使用具有文档良好的架构的 MySQL 数据库。每个接受用户输入并接触数据库的插件都是潜在的 SQL 注入点。$wpdb->prepare() 函数存在,但它是可选的。插件开发者忘记了它、误用了它,或者对"简单"查询完全跳过了它。

我曾经追踪过一个注入,它来自一个已被放弃 18 个月但仍安装在 200,000+ 网站上的联系表单插件。攻击者使用基于 UNION 的注入来转储 wp_users 表,获取管理员密码哈希,并在离线状态下破解弱密码。

-- 典型的 WordPress SQL 注入在日志中的样子
GET /wp-content/plugins/vulnerable-plugin/ajax.php?id=1%20UNION%20SELECT%201,user_login,user_pass,4,5%20FROM%20wp_users--

PHP 对象注入和远程代码执行

WordPress 对 serialize()unserialize() 的大量使用为 PHP 对象注入创造了机会。当插件反序列化用户控制的数据(许多都这样做)时,攻击者可以制作在反序列化过程中执行任意代码的有效负载。

在 2024 年,一个流行备份插件(安装在 500 万+ 网站上)的严重 RCE 漏洞允许未经身份验证的攻击者执行任意 PHP 代码。修复花了 11 天才发布。11 天内,每个运行该插件的网站都是待宰的羔羊。

插件供应链攻击

这是最让我害怕的。攻击者购买有大量安装基础的被放弃插件,推送包含后门的"安全更新",WordPress 自动更新机制将恶意软件分发给每个运行该插件的网站。它发生在 Display Widgets(300,000 个安装)和 Social Warfare(70,000 个安装)上,这些只是被捉住的。

对 wp-login.php 的暴力破解攻击

每个 WordPress 网站默认暴露 /wp-login.php/xmlrpc.php。自动僵尸网络不断袭击这些端点。Wordfence 报告称,2024 年他们网络中平均每月阻止了 30 亿次恶意请求。即使有速率限制和双因素认证,你也在花费服务器资源处理这些攻击。

通过主题和插件的跨站脚本 (XSS)

存储型 XSS 在 WordPress 中特别危险,因为管理员仪表板和公共网站共享相同的会话上下文。通过评论、表单提交或易受攻击的插件设置注入的 XSS 有效负载可以升级为完全的管理员访问权限。

无头架构为什么能消除整个类别的攻击

现在事情变得有趣了。无头架构不仅可以减少你的攻击面——它通过移除使攻击成为可能的条件来消除整个类别的攻击。

在传统的 WordPress 设置中,呈现 HTML 的同一服务器也:

  • 运行来自 20+ 第三方插件的 PHP 代码
  • 管理用户身份验证
  • 连接到数据库
  • 提供管理员界面
  • 处理文件上传
  • 处理表单提交

这对单个应用来说是很多责任。在使用 Next.js 和 Supabase 的无头设置中,这些责任被分散到隔离的服务中:

  • 前端(Next.js 在 Vercel/Netlify): 从 CDN 提供的静态 HTML/JS。在大多数情况下,没有向公网暴露的服务器端运行时。
  • 数据库 + 身份验证(Supabase): 带有行级安全的托管 Postgres,永远不会直接暴露给最终用户。
  • API 层: 具有明确、最小端点的无服务器函数。
  • CMS(如果需要): 在自己隔离的基础设施上运行的无头 CMS。

没有 PHP 可以注入。没有具有写入权限的插件目录。没有在管理员和公共网站之间的共享会话。没有 wp-login.php 供机器人猛击。

你不需要 WAF 来保护一个不存在的攻击面。

WordPress 被黑了?迁移到 Next.js + Supabase 是你最好的解决方案 - 架构

Next.js + Supabase:安全优先的技术栈

让我们具体说说为什么这个特定的组合从安全角度来说效果这么好。

Next.js:不运行代码的前端

当你用静态生成 (SSG) 或增量静态再生 (ISR) 构建 Next.js 网站时,部署的是 CDN 上的 HTML、CSS 和 JavaScript 文件。没有应用服务器实时处理请求。你不能 SQL 注入一个 CDN。

对于动态功能,Next.js 服务器操作和路由处理程序作为无服务器函数运行。每个函数是:

  • 在自己的执行上下文中隔离的
  • 无状态的(请求之间没有共享内存)
  • 短期的(冷启动、执行、终止)
  • 明确定义的(没有端点的自动发现)
// Next.js 路由处理程序 -- 明确、有类型、最小化
import { createClient } from '@/lib/supabase/server'
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'

const ContactSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  message: z.string().min(10).max(5000),
})

export async function POST(request: NextRequest) {
  const body = await request.json()
  const parsed = ContactSchema.safeParse(body)
  
  if (!parsed.success) {
    return NextResponse.json({ error: 'Invalid input' }, { status: 400 })
  }
  
  const supabase = await createClient()
  const { error } = await supabase
    .from('contact_submissions')
    .insert(parsed.data)
  
  if (error) {
    return NextResponse.json({ error: 'Submission failed' }, { status: 500 })
  }
  
  return NextResponse.json({ success: true })
}

将其与必须钩入 WordPress 的操作系统、包含自己的 AJAX 处理程序、管理自己的 nonce 验证和构建自己的 SQL 查询的 WordPress 联系表单插件进行比较。Next.js 版本有更少的移动部分,通过 Zod 验证输入,以及通过 Supabase 客户端的参数化查询。

Supabase:带行级安全的 Postgres

Supabase 为你提供了一个托管的 PostgreSQL 数据库,带有一个杀手级功能:行级安全 (RLS)。与其相信你的应用代码来强制执行访问控制(WordPress 模型),你定义数据库级别的安全策略。

-- 只有经过身份验证的用户可以读他们自己的数据
CREATE POLICY "Users can view own profile"
  ON profiles
  FOR SELECT
  USING (auth.uid() = user_id);

-- 公共可以插入到联系提交但不能读
CREATE POLICY "Anyone can submit contact form"
  ON contact_submissions
  FOR INSERT
  WITH CHECK (true);

CREATE POLICY "Only admins can read submissions"
  ON contact_submissions
  FOR SELECT
  USING (auth.jwt() ->> 'role' = 'admin');

即使攻击者找到了一种方式来进行任意 Supabase 查询(在没有 PHP 执行上下文的情况下已经困难得多),RLS 策略也会阻止他们访问他们不应该看到的数据。这是深度防御,WordPress 从根本上无法提供,因为它的权限系统是在 PHP 代码中实现的,而不是在数据库层。

Supabase 还通过对电子邮件/密码、魔法链接、OAuth 提供商和多因素身份验证的内置支持来处理身份验证。不需要插件。没有第三方代码在你的服务器上运行。

攻击面对比:WordPress vs 无头架构

让我们并排放置这个。

攻击向量 WordPress Next.js + Supabase
SQL 注入 高风险 -- 插件构建原始查询 接近零 -- 通过 Supabase 客户端参数化查询,RLS 作为备份
PHP/远程代码执行 高风险 -- 插件执行服务器端 PHP 不适用 -- 没有 PHP 运行时
插件供应链 严重风险 -- 自动更新分发恶意软件 不适用 -- 没有插件生态系统
暴力破解(登录) 总是暴露(wp-login.phpxmlrpc.php 通过 Supabase Auth 或单独仪表板的管理员访问,不需要公共登录端点
XSS(存储型) 高风险 -- 共享管理员/公开上下文 低风险 -- React 默认转义输出,管理员和公共是单独的应用
文件上传利用 高风险 -- 上传的 PHP 文件可以执行 低风险 -- 上传到对象存储(Supabase Storage/S3),永远不会作为代码执行
数据库暴露 如果服务器受到破坏,直接 MySQL 访问 数据库在 Supabase 基础设施后面,RLS 策略作为最后的防线
DDoS 源 服务器必须处理每个请求 CDN 上的静态资产,很少打到源
已知路径枚举 wp-adminwp-contentwp-includes 都是可扫描的 没有可预测的路径,没有暴露的管理路由

迁移手册:WordPress 到 Next.js + Supabase

好的,你被说服了(或你被黑的网站说服了你)。这是实际如何做的。我们已经进行了足够多的这种迁移,有一个可重复的过程。

阶段 1:审查和内容审计(第 1 周)

在你接触任何代码之前,你需要了解你实际上拥有什么。

  1. 导出所有 WordPress 内容使用 WP-CLI 或 REST API。不要依赖 XML 导出——它们缺少元字段和自定义文章类型。
  2. 列出所有插件提供的功能。制作电子表格:插件名称、它做什么、你是否真的需要它,以及什么替代它。
  3. 映射 URL 结构为了 SEO 保护。每个现有 URL 都需要一个重定向或在 Next.js 中的匹配路由。
  4. 识别动态功能 -- 表单、搜索、用户帐户、电商 -- 需要 API 端点。
# 通过 REST API 导出 WordPress 内容
curl -s "https://yoursite.com/wp-json/wp/v2/posts?per_page=100&page=1" | jq '.' > posts_page1.json
curl -s "https://yoursite.com/wp-json/wp/v2/pages?per_page=100" | jq '.' > pages.json
curl -s "https://yoursite.com/wp-json/wp/v2/media?per_page=100" | jq '.' > media.json

阶段 2:Supabase 架构和数据迁移(第 2 周)

基于内容审计设计你的 Supabase 数据库架构。不要只是复制 WordPress 架构——它充满了元数据表和序列化数据块。

-- 干净、专用的架构
CREATE TABLE posts (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  title TEXT NOT NULL,
  slug TEXT UNIQUE NOT NULL,
  content TEXT,
  excerpt TEXT,
  featured_image TEXT,
  status TEXT DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')),
  published_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  author_id UUID REFERENCES auth.users(id)
);

-- 立即启用 RLS
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Published posts are public"
  ON posts FOR SELECT
  USING (status = 'published');

CREATE POLICY "Authors can manage own posts"
  ON posts FOR ALL
  USING (auth.uid() = author_id);

写一个迁移脚本(Node.js 或 Python),将 WordPress JSON 导出转换为你的新架构,并将它们插入到 Supabase。

阶段 3:Next.js 构建(第 3-5 周)

构建你的 Next.js 前端。如果你正在与熟悉该技术栈的团队合作,这进展很快。如果你需要帮助,我们的 Next.js 开发团队已经进行过足够多次这种迁移,对正确的模式有强烈的看法。

关键的架构决策:

  • 内容页面的静态生成 -- 博客文章、登陆页面、关于页面。这些成为 CDN 上的 HTML 文件。
  • 动态数据的服务器组件 -- 在请求时从 Supabase 获取,带缓存。
  • 表单提交的路由处理程序 -- 联系表单、通讯注册等。
  • 重定向的中间件 -- 处理所有旧的 WordPress URL。
// next.config.ts -- 处理 WordPress URL 重定向
const nextConfig = {
  async redirects() {
    return [
      {
        source: '/category/:slug',
        destination: '/blog/category/:slug',
        permanent: true,
      },
      {
        source: '/:year(\\d{4})/:month(\\d{2})/:slug',
        destination: '/blog/:slug',
        permanent: true,
      },
      // wp-login.php -- 发送机器人到一个 410
      {
        source: '/wp-login.php',
        destination: '/gone',
        permanent: true,
      },
      {
        source: '/wp-admin/:path*',
        destination: '/gone',
        permanent: true,
      },
    ]
  },
}

阶段 4:测试和 SEO 验证(第 6 周)

  • 针对新网站运行 Screaming Frog,验证每个旧 URL 要么解析要么重定向。
  • 验证结构化数据(JSON-LD)存在于所有页面上。
  • 测试所有表单和动态功能。
  • 运行 Lighthouse 和 Core Web Vitals 检查 -- 你几乎肯定会看到改进,因为你现在从 CDN 提供。
  • 用 Vercel Analytics 或你喜欢的工具设置监控。

阶段 5:启动和 DNS 切换(第 6-7 周)

部署到 Vercel 或 Netlify,更新 DNS,并设置监控。保持旧 WordPress 实例离线但可访问 30 天,以防你需要参考任何内容。

如果你的网站有重大流量或电商功能,考虑一个无头 CMS 集成用于内容管理,并与我们讨论将 Astro 作为替代前端,用于内容丰富的网站,其中构建性能很重要。

迁移后的安全加固

一旦你在新的技术栈上,这里是你的安全检查清单:

  1. 在每个表上启用 Supabase RLS。 没有例外。如果表没有策略,它要么是无法访问的(好默认),要么是完全开放的(不好)。
  2. 为所有秘密使用环境变量。 Vercel 和 Netlify 都处理得很好。永远不要提交 API 密钥。
  3. 设置 Supabase 数据库备份。 时间点恢复在专业计划上可用($25/月)。
  4. 在你的 Next.js 中间件中配置内容安全策略头。
  5. 启用 Vercel 的 DDoS 保护(包含在所有计划中)。
  6. 设置正常运行时间监控 -- 我们使用 Better Uptime,但 Checkly 和 Vercel 的内置监控也行。
  7. 季度审计你的 Supabase RLS 策略。 使用 Supabase 的 SQL 编辑器用不同的用户上下文测试策略。
// middleware.ts -- 安全头
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const response = NextResponse.next()
  
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-Content-Type-Options', 'nosniff')
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
  response.headers.set(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
  )
  response.headers.set(
    'Permissions-Policy',
    'camera=(), microphone=(), geolocation=()'
  )
  
  return response
}

WordPress 安全与迁移的真实成本

让我们谈钱,因为那是真正驱动决策的。

成本类别 WordPress(年度) Next.js + Supabase(年度)
托管 $300-1,200(托管 WP) $0-240(Vercel Pro)
安全插件(Wordfence/Sucuri) $200-500 $0(不需要)
SSL/CDN $0-200 $0(包含)
恶意软件清理(如果被黑) 每次事件 $500-2,500 不适用
开发人员在安全补丁上的时间 $2,000-5,000 $500-1,000
数据库(Supabase) 包含在托管中 $0-300(免费层到专业版)
总计 $3,000-9,400 $500-1,540

这还没有考虑停机时间、失去客户信任的成本,以及如果客户数据被破坏可能的监管罚款。单一的 GDPR 可报告的违规可能会导致数万美元的法律和合规开销。

迁移本身通常花费 $10,000-40,000,取决于网站的复杂性。对于大多数企业,这在 1-2 年内就能通过减少安全支出而收回——你还能获得更快、更易维护的网站。查看我们的定价页面了解迁移项目的具体情况。

常见问题

WordPress 真的那么不安全,还是这被夸大了? WordPress 核心得到了良好的维护。问题在于几乎没有人只运行核心。插件生态系统是 96% 漏洞的所在地,你无法运行一个有用的 WordPress 网站而不使用插件。这没有被夸大——Sucuri 在 2024 年清理了超过 60,000 个 WordPress 网站的恶意软件。该架构要求你信任第三方 PHP 代码在你的服务器上,这种信任不断被利用。

我不能只是使用更好的安全插件而不迁移吗? 安全插件本身就是在你的服务器上运行的 PHP 代码,具有深度系统访问权限。Wordfence 和 Sucuri 得到了很好的维护,但它们是对架构问题的创可贴。他们还增加了服务器负载,可能与其他插件冲突,并且多年来有自己的漏洞。你在添加复杂性来解决复杂性问题。

WordPress 到 Next.js 的迁移通常需要多长时间? 对于标准商业网站(10-50 页、博客、联系表单),我们通常在 5-7 周内完成迁移。带有 WooCommerce 的电商网站更复杂,取决于产品目录大小和自定义功能,可以花费 8-14 周。如果你有一个更简单的网站,联系我们,我们可以给你一个更具体的时间表。

从 WordPress 迁移到新网站时,我会失去 SEO 排名吗? 不会,如果你做得对的话。关键步骤是:保留所有 URL 结构或设置适当的 301 重定向、维护你的结构化数据标记、保持内容完整,并向 Google Search Console 提交更新的站点地图。我们大多数迁移客户在 2-3 个月内看到排名改进,因为当你迁移到由 CDN 提供的静态网站时,Core Web Vitals 分数会大幅提高。

内容编辑怎么办?WordPress 对非技术用户来说很容易。 这是一个合理的问题。你有选项:带有自定义管理仪表板的 Supabase,或像 Sanity、Contentful 或 Payload CMS 这样的无头 CMS,为内容编辑者提供类似于 WordPress 的可视化编辑体验。我们定期处理无头 CMS 集成,并可以推荐适合你团队需求的方案。

Supabase 对生产使用足够安全吗? Supabase 在 AWS 基础设施上运行,具有 SOC 2 Type II 合规性。底层数据库是 PostgreSQL,具有强大的安全跟踪记录。行级安全策略在数据库级别强制执行访问控制,这实际上比 WordPress 的基于 PHP 的权限系统更安全。Supabase 还在付费计划上提供时间点恢复、加密连接和网络限制。

如果我的 WordPress 网站被黑了,我需要立即帮助怎么办? 首先,立即将网站脱机以停止进一步的损害和数据泄漏。其次,保留取证证据(数据库转储、访问日志、文件系统快照)。第三,不要只是清理它并放回去——你可能在几周内被重新感染。使用该事件作为迁移的催化剂。联系我们团队,我们可以帮助进行紧急分类和迁移规划。

我可以一次迁移所有内容,还是可以逐步迁移? 增量迁移是可能的,但增加了复杂性。你可以运行 Next.js 作为前端,同时保持 WordPress 作为无头 CMS 后端暂时,然后完全逐步停止 WordPress。但是,这意味着 WordPress 仍在运行,并且在过渡期间仍需要安全维护。对于大多数网站,干净的切换更快、更便宜,并且更快地消除安全风险。