You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress Forminator表单文件上传安全过滤的正确实现方案

解决Forminator表单恶意文件上传绕过问题的方案

核心思路

仅靠文件名后缀校验无法拦截伪装的恶意文件,必须结合文件真实MIME类型检测、文件名关键字过滤,再配合上传目录的权限限制,从上传校验和文件执行两个层面阻断风险。

具体实现代码

1. 双重校验文件类型与文件名

这段代码针对Forminator表单的上传字段,先读取文件真实MIME类型,再匹配允许的后缀,同时拦截含可疑关键字的文件名。

add_filter( 'forminator_custom_upload_validation', 'custom_forminator_file_upload_validation', 10, 4 );
function custom_forminator_file_upload_validation( $valid, $file, $field, $form_id ) {
    // 替换为你的目标表单ID,仅对指定表单生效
    if ( $form_id != 123 ) {
        return $valid;
    }

    // 定义允许的文件类型:键为真实MIME类型,值为对应允许的后缀
    $allowed_types = [
        'application/pdf' => ['pdf'],
        'image/jpeg' => ['jpg', 'jpeg'],
        'image/png' => ['png'],
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'],
        'application/msword' => ['doc']
    ];

    // 获取文件真实MIME类型
    $real_mime = wp_check_filetype( $file['tmp_name'], null )['type'];

    // 校验真实MIME是否在允许列表
    if ( ! array_key_exists( $real_mime, $allowed_types ) ) {
        $valid = false;
        $field->add_error( '上传文件类型不允许,请上传指定格式的文件。' );
        return $valid;
    }

    // 获取并校验文件后缀
    $file_ext = strtolower( pathinfo( $file['name'], PATHINFO_EXTENSION ) );
    if ( ! in_array( $file_ext, $allowed_types[$real_mime] ) ) {
        $valid = false;
        $field->add_error( '文件后缀与实际类型不匹配,禁止上传。' );
        return $valid;
    }

    // 拦截含可疑脚本关键字的文件名
    $suspicious_keywords = ['php', 'asp', 'cgi', 'pl', 'py', 'sh'];
    $filename_lower = strtolower( $file['name'] );
    foreach ( $suspicious_keywords as $keyword ) {
        if ( strpos( $filename_lower, $keyword ) !== false ) {
            $valid = false;
            $field->add_error( '文件名包含可疑内容,禁止上传。' );
            return $valid;
        }
    }

    return $valid;
}

2. 限制上传目录执行权限

即使恶意文件侥幸上传,也要阻断其执行权限。可以在Forminator默认上传目录wp-content/uploads/forminator下创建.htaccess文件,添加以下规则:

# 禁止执行任何脚本文件
AddHandler cgi-script .php .pl .py .jsp .asp .sh .cgi
Options -ExecCGI -Indexes

# 仅允许访问指定格式的文件
<FilesMatch "\.(pdf|jpg|jpeg|png|docx|doc)$">
    Order Allow,Deny
    Allow from all
</FilesMatch>
<FilesMatch ".*">
    Order Deny,Allow
    Deny from all
</FilesMatch>

若担心.htaccess被插件更新覆盖,可添加以下PHP代码自动维护该文件:

add_action( 'admin_init', 'secure_forminator_upload_dir' );
function secure_forminator_upload_dir() {
    $upload_dir = wp_upload_dir();
    $forminator_dir = $upload_dir['basedir'] . '/forminator';
    
    if ( ! file_exists( $forminator_dir ) ) {
        wp_mkdir_p( $forminator_dir );
    }

    $htaccess_path = $forminator_dir . '/.htaccess';
    $htaccess_content = <<<EOF
# 禁止执行任何脚本文件
AddHandler cgi-script .php .pl .py .jsp .asp .sh .cgi
Options -ExecCGI -Indexes

# 仅允许访问指定格式的文件
<FilesMatch "\.(pdf|jpg|jpeg|png|docx|doc)$">
    Order Allow,Deny
    Allow from all
</FilesMatch>
<FilesMatch ".*">
    Order Deny,Allow
    Deny from all
</FilesMatch>
EOF;

    if ( ! file_exists( $htaccess_path ) || file_get_contents( $htaccess_path ) !== $htaccess_content ) {
        file_put_contents( $htaccess_path, $htaccess_content );
        chmod( $htaccess_path, 0644 );
    }
}

代码部署位置

  1. 主题functions.php:后台进入「外观→主题文件编辑器」,找到当前主题的functions.php,将代码粘贴到文件末尾后保存。注意:更换主题时需重新添加代码。
  2. 自定义代码插件:安装激活「Code Snippets」插件,新建代码片段粘贴代码,设置运行范围后保存启用。这种方式不受主题更换影响,更推荐。

注意事项

  • 替换代码中的表单ID(123)为你实际的Forminator表单ID(可在表单编辑页URL中找到)。
  • 根据业务需求调整$allowed_types和suspicious_keywords数组,增减允许的文件类型和可疑关键字。
  • 测试时上传伪装文件(如将PHP文件改名为PDF后缀),验证拦截效果。

内容的提问来源于stack exchange,提问作者zakiblacki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:42:54