PHP中创建目录使用mkdir()函数,需严格校验用户输入路径、用basename()或正则过滤、结合realpath()验证是否在授权根目录内,并设置0755等最小权限,避免目录遍历与越权写入。

PHP 中使用 mkdir() 创建目录时,本身不直接导致目录遍历(穿越)攻击,但若其路径参数来自用户输入且未经净化,就可能被用于构造恶意路径(如 ../../../etc),进而配合其他函数(如 file_put_contents、ZipArchive::extractTo)实现越权写入或覆盖系统关键位置。因此,“防止目录穿越”不是 mkdir() 的内置能力,而是开发者在调用前必须完成的**路径安全控制**。
严格校验并规范化用户输入的路径
不要直接拼接用户传入的路径字符串。例如,避免这样写:
// 危险!用户可控 $dirname 可能含 ../
$path = '/var/www/uploads/' . $_GET['dirname'];<br>mkdir($path, 0755, true);
正确做法是:先提取合法部分,再拼接到白名单根目录下:
- 用
basename()提取纯文件名/目录名(丢弃所有路径分隔符和上级跳转) - 用正则限制只允许字母、数字、下划线、短横线等安全字符:
preg_match('/^[a-zA-Z0-9_-]+$/',$safe_name) - 最终路径由固定根目录 + 安全名称组成:
$real_path = '/var/www/uploads/' . $safe_name;
使用 realpath() 验证路径是否落在授权范围内
即使做了字符过滤,仍需防止绕过(如 Unicode 归一化、空字节等)。更可靠的手段是:构造完目标路径后,用 realpath() 获取其真实绝对路径,并检查是否以预期根目录开头:
$target = '/var/www/uploads/' . basename($_GET['dirname']);-
$abs = realpath($target);—— 若路径不存在或含非法跳转,realpath()返回false if ($abs === false || strpos($abs, '/var/www/uploads/') !== 0) { die('非法路径'); }
设置合理的权限与隔离环境
即便路径安全,也要降低误操作影响:
- 创建目录时显式指定权限(如
0755),避免0777等宽泛权限 - 确保 PHP 进程运行用户对父目录仅有必要写权限(如不赋予
/var/www写权,只给/var/www/uploads) - 生产环境建议配合容器(Docker)或 chroot 沙箱,从系统层限制可访问路径范围
替代思路:避免让用户决定目录名
最彻底的防御是消除风险源头:
- 由服务端生成唯一目录名(如
uniqid('upload_')或 UUID),不接受用户命名 - 按业务逻辑自动归类(如按日期
2026/11/03或用户ID哈希分片) - 前端仅提供“新建文件夹”按钮,后端统一处理命名与路径绑定
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











