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 ); } }
代码部署位置
- 主题functions.php:后台进入「外观→主题文件编辑器」,找到当前主题的
functions.php,将代码粘贴到文件末尾后保存。注意:更换主题时需重新添加代码。 - 自定义代码插件:安装激活「Code Snippets」插件,新建代码片段粘贴代码,设置运行范围后保存启用。这种方式不受主题更换影响,更推荐。
注意事项
- 替换代码中的表单ID(
123)为你实际的Forminator表单ID(可在表单编辑页URL中找到)。 - 根据业务需求调整
$allowed_types和suspicious_keywords数组,增减允许的文件类型和可疑关键字。 - 测试时上传伪装文件(如将PHP文件改名为PDF后缀),验证拦截效果。
内容的提问来源于stack exchange,提问作者zakiblacki
相关产品推荐
相关产品推荐

