织梦禁止上传php文件设置
上传 PHP 文件是织梦站点被植入 webshell 的最直接途径。一旦攻击者成功上传 .php 文件到 uploads 目录并访问执行,就等同于拿到服务器命令执行权限。彻底禁止上传 PHP 文件,需要从代码层白名单、MIME 校验、服务器层执行禁用三个维度同时加固,缺一不可。
一、PHP 文件上传的危害
- 上传
shell.php后访问/uploads/shell.php即可获得 webshell; - 绕过技巧多:双扩展名
shell.php.jpg、大小写shell.PHP、.phtml、.phar; - 配合
.htaccess可让任意扩展名被当作 PHP 解析; - webshell 一旦执行,可读写所有文件、连接数据库、提权控制服务器。
二、织梦默认上传机制
织梦上传校验位于 /include/uploadsafe.class.php、/include/dialog/select_media.php、/include/dialog/select_images.php。默认配置存在以下问题:
- 允许的扩展名包含
phtml、phar; - 仅校验扩展名,不校验 MIME;
- 部分老版本对大小写、双扩展名处理不严。
三、代码层加固:严格白名单
编辑 /include/uploadsafe.class.php,把允许类型改为严格白名单:
// 仅允许图片与文档
$this->allowTypes=array(
'jpg','jpeg','gif','png','bmp','webp','ico',
'pdf','doc','docx','xls','xlsx','ppt','pptx',
'zip','rar','7z','tar','gz',
'mp4','mp3','wav','ogg',
'txt','csv','md'
);
// 显式禁止的可执行扩展名
$forbidden=array(
'php','php5','php7','php8','phtml','phar',
'asp','aspx','jsp','jspx',
'cgi','pl','py','sh','exe','bat','cmd',
'htaccess','htpasswd','ini','conf','user.ini'
);
$ext=strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if(in_array($ext, $forbidden)){
exit('禁止上传可执行文件');
}
if(!in_array($ext, $this->allowTypes)){
exit('文件类型不在允许范围');
}
处理双扩展名
// 检测文件名中是否包含多个 .
$parts=explode('.', $filename);
if(count($parts) > 2){
// 检查除最后一个外的所有扩展名
for($i=1; $i < count($parts) - 1; $i++){
if(in_array(strtolower($parts[$i]), $forbidden)){
exit('文件名包含可执行扩展名');
}
}
}
四、MIME 一致性校验
扩展名校验可能被绕过,必须配合 MIME 检查:
$finfo=finfo_open(FILEINFO_MIME_TYPE);
$mime=finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
$ext_mime_map=array(
'jpg'=> ['image/jpeg','image/pjpeg'],
'png'=> ['image/png'],
'gif'=> ['image/gif'],
'pdf'=> ['application/pdf'],
'zip'=> ['application/zip','application/x-zip-compressed']
);
if(!isset($ext_mime_map[$ext]) || !in_array($mime, $ext_mime_map[$ext])){
exit('文件扩展名与内容不匹配');
}
MIME 校验只能防御低级攻击,攻击者可通过修改文件头绕过。仍需服务器层执行禁用作为最终防线。
五、服务器层:uploads 禁止执行 PHP
1. Nginx
# 完全禁止 uploads 目录执行 PHP
location ~* /uploads/.*\.(php|php5|php7|phtml|phar)$ {
deny all;
return 404;
}
# 禁止 .htaccess 上传后被使用
location ~* /uploads/.*\.ht(access|passwd)$ {
deny all;
return 404;
}
# 禁止 user.ini(PHP 用户级配置)
location ~* /uploads/.*\.user\.ini$ {
deny all;
return 404;
}
2. Apache
在 uploads 目录放置 .htaccess:
# /uploads/.htaccess
<FilesMatch "\.(php|php5|phtml|phar|cgi|pl|py)$">
Require all denied
</FilesMatch>
# 禁止 PHP 解析
php_flag engine off
RemoveHandler .php .phtml .php3 .php4 .php5
3. PHP-FPM 配置
在 PHP-FPM pool 配置中限制 open_basedir,让 uploads 目录外的 PHP 无法访问核心文件:
; /etc/php-fpm.d/www.conf
php_admin_value[open_basedir]=/www/wwwroot/dede:/tmp
六、关闭不必要上传入口
织梦有多个上传通道,按需保留:
- 编辑器上传(必要):保留;
- 会员中心上传(如不需要会员功能):删除
/member/uploads.php; - 后台文件管理器(
/dede/file_manage_view.php):建议删除或禁用; /plus/upload.php:删除。
七、验证拦截效果
- 尝试上传
shell.php,应被拒绝; - 尝试上传
shell.php.jpg,应被拒绝; - 尝试上传
shell.PHP,应被拒绝; - 把
shell.php改名为shell.jpg上传,再尝试访问/uploads/shell.jpg.php,应 404; - 用 burpsuite 抓包修改 MIME,应仍被扩展名校验拦截。
八、后门排查
设置完成后,扫描 uploads 目录是否已存在历史 PHP 文件:
find /www/wwwroot/dede/uploads -name "*.php" -o -name "*.phtml" -o -name "*.phar"
find /www/wwwroot/dede/uploads -name ".htaccess"
find /www/wwwroot/dede/uploads -name ".user.ini"
发现任何匹配立即删除并查清来源。
九、注意事项
- Nginx 配置修改后用
nginx -t校验,避免语法错误导致全站 502; - Apache
.htaccess必须放在 uploads 根目录才生效; - 第三方编辑器可能自带上传逻辑,需单独加固;
- CDN 缓存可能让旧的可执行文件仍可访问,配置后清缓存。
禁止上传 PHP 文件是织梦防 webshell 的核心措施,建议把"代码白名单 + MIME 校验 + nginx 执行禁用 + 后门扫描"四件事一次性配齐。三层防御互为补充,即便某一层被绕过,仍有其他层兜底。配置完成后定期用 sqlmap、xray 等工具复测上传通道,确保防护持续有效。