CVE-2025-1128

描述

在广受欢迎的 WordPress 插件Everest Forms中发现了一个严重的安全漏洞,编号为 CVE-2025-1128,这使得超过 10 万个网站即刻面临被完全攻陷的风险。该漏洞在通用漏洞评分系统(CVSS)中被评为 9.8 的严重等级,它允许未经身份验证的攻击者上传任意文件、执行远程代码,甚至删除关键配置文件,有可能导致网站被完全控制

该插件EVF_Form_Fields_Upload 类的 format()方法未对文件类型或后缀名进行检查。黑客能够直接将包含恶意 PHP 代码的 CSV 或 TXT 文本文件重命名为 PHP 文件并进行上传。而 WordPress 网站会自动把这些文件移动到任何人都可公开访问的上传目录。如此一来,黑客便可在未经过身份验证的情况下上传恶意 PHP 代码,从而触发漏洞在服务器上远程执行任意代码

fofa : body=”/wp-content/plugins/everest-forms/“

环境搭建

wordpress下载后使用phpstudy搭建,然后再安装Everest Forms插件即可

插件下载:https://downloads.wordpress.org/plugin/everest-forms.3.0.9.4.zip

漏洞复现

进入后台,随便找个表单编辑一下

image-20250310162059522

将上传的表单添加上

image-20250310162321895

保存,然后随便找个页面添加上这个表单,这里就用首页文章

image-20250310162539354

把刚刚的简码复制粘贴即可,然后保存

image-20250310162649130

访问首页对应文章就存在一个文件上传的功能了

image-20250310162906873

这里不能直接上传php,简单构造个csv进行上传(还没点击确定)

image-20250310163240171

然后点击确定,拦截改包,将name改为php

image-20250310163453920

发包后虽然提示报错说不运行上传,其实已经上传成功了

image-20250310163642869

即使正常的上传也没有返回上传路径,这个是比较鸡肋的地方

image-20250310164110788

漏洞分析

漏洞出现在EVF_Form_Fields_Upload 类的 format()方法

在没有点击确定按钮时,上传的文件会保存到wp-content/uploads/everest_forms_uploads/tmp中,会返回一个包含文件名的json,例如

{"success":true,"data":{"file":"7fdc87c553a1c8e5bde5c9646ca57657.csv","name":"_67ceaad6e77452.28796521.csv"}}

其中file是上传后的文件名,name是后面操作需要的文件名

修改请求包,将name改为1.php点击确定进行调试

------WebKitFormBoundaryIj90kBE9JN9xA6L8
Content-Disposition: form-data; name="everest_forms_7_lFYiSaif7v-1"

[{"file":"7fdc87c553a1c8e5bde5c9646ca57657.csv","name":"1.php"}]

这里只提关键点

$file = $this->generate_file_info( $file );

这个方法是生成文件路径的,这个文件路径需要使用到上面json的name,根据name的文件名和拓展名进行构造

protected function generate_file_info( $file ) {
    $dir = $this->get_form_files_dir();
    $file['tmp_path'] = trailingslashit( $this->get_tmp_dir() ) . sanitize_file_name($file['file']);
    $file['type']     = 'application/octet-stream';
    if ( is_file( $file['tmp_path'] ) ) {
        $filetype     = wp_check_filetype( $file['tmp_path'] );
        $file['type'] = $filetype['type'];
    }

    // Data for no media case.
    $file_ext              = pathinfo( $file['name'], PATHINFO_EXTENSION );
    $file_base             = wp_basename( $file['name'], ".$file_ext" );
    $file['file_name_new'] = sprintf( '%s-%s.%s', $file_base, wp_hash( $dir['path'] . $this->form_data['id'] . $this->field_id ), strtolower( $file_ext ) );
    $file['file_name_new'] = wp_unique_filename( trailingslashit( $dir['path'] ), sanitize_file_name( $file['file_name_new'] ) );
    $file['file_url']      = trailingslashit( $dir['url'] ) . $file['file_name_new'];
    $file['path']          = trailingslashit( $dir['path'] ) . $file['file_name_new'];
    $file['attachment_id'] = 0;

    return $file;
}

有上方法可知,最终路径的拓展名为json中name的拓展名,所以最终会将.csv变成.php

往下检测后缀

$wp_filetype = wp_check_filetype_and_ext( $file['tmp_path'], $file['name'] );

因为$file[‘name’]是1.php所以检测结果过不了下面判断,所以会提示File type is not allowed

if ( $proper_filename || ! $ext || ! $type ) {
    evf()->task->errors[ $form_data['id'] ][ $field_id ] = esc_html__( 'File type is not allowed.', 'everest-forms' );
    update_option( 'evf_validation_error', 'yes' );
}

重点来了

这个if判断之后,并没有退出程序,而是继续往下运行,继续保存文件

所以就是这里导致文件上传

修复

建议更新到最新版本

官方修复如下:

if ( $proper_filename || ! $ext || ! $type ) {
    evf()->task->errors[ $form_data['id'] ][ $field_id ] = esc_html__( 'File type is not allowed.', 'everest-forms' );
    update_option( 'evf_validation_error', 'yes' );
    wp_die( 'File type is not allowed' );
}

就是添加了wp_die( ‘File type is not allowed’ );判断不允许上传后就结束运行

总结

这个漏洞应该是利用不了,首先是,要想前台利用,前台必须要有这个插件生成的上传点,这种情况是比较少的。其次无法获取上传路径,而且路径是有加盐md5的,不好搞,若是能够读取wp-config.php,路径还有一线生机

参考

https://plugins.trac.wordpress.org/changeset/3243663/everest-forms

https://www.anquanke.com/post/id/304733