php开发之文件下载的实现
前言
php是网络安全学习里必不可少的一环,简单理解php的开发环节能更好的帮助我们去学习php以及其他语言的web漏洞原理
正文
在正常的开发中,文件下载的功能是必不可少,比如我们在论坛看到好看图片好听的歌时,将其下载下来时就涉及到文件的下载等等文件功能。但也会出现漏洞,或者一些bug。这部分是php开发部分的文件下载部分,为啥不写完?感觉有点多。
文件下载代码的实现
完整的css代码
/* css样式初始化 */ * { font-family: 'Poppins', sans-serif; margin: 0; padding: 0; box-sizing: border-box; outline: none; border: none; text-decoration: none; text-transform: capitalize; transition: .2s linear; } html { font-size: 62.5%; } /* header样式初始化*/ .header { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; background: #3F3D56; display: flex; align-items: center; justify-content: space-between; } .header .logo { color: white; padding: 0 1rem; } /* 导航样式 */ .navbar ul{ display: flex; } .navbar ul li{ font-weight: bold; width: 128px; list-style: none; text-align:center; } .navbar ul li a { width: 128px; line-height: 45px; font-size: 1.7rem; color: white; } .navbar ul li a:hover{ color: #009933; } /* 二级菜单样式 */ .navbar ul li ul{ position: absolute; display: none; width: 128px; line-height: 45px; } .navbar ul li ul li{ background-color: #3F3D56; } /* 悬浮展开二级菜单 */ .navbar ul li ul li a:hover{ color: white; } .navbar ul li ul li:hover{ background-color: #009933; } .navbar ul li:hover ul{ display: block; } /* 网站内容*/ .content{ margin-top:50px; } /*让文件下载的文件列表居中显示*/ .download-links { text-align: center; /* 使链接居中 */ font-family: 'LiSu', 'STLiti', cursive; /* 尝试使用隶书字体,如果不可用则退回到通用草书字体 */ font-style: italic; /* 设置字体为斜体 */ } .download-links ul { list-style: none; padding: 0; margin: 0; display: inline-block; /* 使 <ul> 内容居中对齐 */ } .download-links li { margin: 10px; /* 添加一些间距 */ } .download-links a { font-size: 18px; /* 可以根据需要调整大小 */ text-decoration: none; color: #000; } .download-links a:hover { text-decoration: underline; }
php列出当前目录下的文件及文件夹
<?php // 列出当前目录下的所有文件和目录 $files = scandir('.'); /*// 只保留文件,过滤掉目录 $files = array_filter($files, function($file) { return is_file($file); });*/ // 打印所有文件名 foreach ($files as $file) { echo $file . '<br>'; }
运行效果如下:
直链下载
这是比较安全的方式,就不给参数,直接使用链接进行文件的下载,即不由用户决定,而是服务器决定。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Head</title> <link rel="stylesheet" href="index.css"> </head> <body> <div class="header"> <a href="index.html" class="logo"> <h1>wushiyiwuzhong</h1> </a> <nav class="navbar"> <ul> <li><a href="file_index.php">文件功能导航</a></li> <li><a href="file_upload.php">文件上传</a></li> <li><a href="file_downlaod.php">文件下载</a></li> <li><a href="#">文件删除</a></li> <li><a href="#">文件读取</a></li> <li><a href="#">文件写入</a></li> </ul> </nav> </div> <div class="download-links"> <ul> <?php $files = scandir('.'); $files = array_filter($files, function($file) { return is_file($file); }); foreach ($files as $file) { // 创建下载链接 echo '<li><a href="' . htmlspecialchars($file) . '" download>' . htmlspecialchars($file) . '</a></li>'; } ?> </ul> </div> </body> </html>
运行效果如下
随便下载一个文件进行测试
下载成功
直连下载的好处是当用户想下载文件时只能在服务器允许的下载范围里下载,而不能下载其他文件
PS:直连下载的方式中文件命令规则最好不要把文件命名的太像,比如202101.jpg、202102.jpg等等,这种情况攻击者可能会通过枚举遍历的方式下载到一些隐私文件
参数下载
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Head</title> <link rel="stylesheet" href="index.css"> </head> <body> <div class="header"> <a href="index.html" class="logo"> <h1>wushiyiwuzhong</h1> </a> <nav class="navbar"> <ul> <li><a href="file_index.php">文件功能导航</a></li> <li><a href="file_upload.php">文件上传</a></li> <li><a href="file_downlaod.php">文件下载</a></li> <li><a href="#">文件删除</a></li> <li><a href="#">文件读取</a></li> <li><a href="#">文件写入</a></li> </ul> </nav> </div> <div class="download-links"> <ul> <?php $files = scandir('.');//扫描当前目录 $files = array_filter($files, function($file) { return is_file($file); }); foreach ($files as $file) { // 创建下载链接,指向 download.php,并传递 filename 参数 echo '<li><a href="file_downlaod.php?filename=' . urlencode($file) . '">' . htmlspecialchars($file) . '</a></li>'; } ?> </ul> </div> </body> </html> <?php // 读取 filename 参数 $filename = isset($_GET['filename']) ? $_GET['filename'] : ''; // 白名单机制,确保只能下载指定文件夹下的文件 $filePath = './' . $filename; // 安全性检查,防止目录遍历攻击 if (file_exists($filePath) && is_file($filePath) && preg_match('/^.\//', $filePath)) { // 设置 headers header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($filePath).'"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($filePath)); // 清空输出缓冲区并关闭输出缓冲 ob_clean(); flush(); // 发送文件到浏览器 readfile($filePath); exit; }
代码细节解释
1、file_exists($filePath) - 这个函数检查指定路径的文件或目录是否存在。如果文件存在,则返回 true,否则返回 false。
2、is_file(
3、preg_match('/^.//',
通常我们希望的是正则表达式能够确保文件路径是在一个特定的目录下,例如 /^downloads//,这样的表达式会匹配所有以 downloads/ 开始的路径。
运行效果如下:
随便下载一个文件进行测试,此时可以明显的看到文件的下载链接里多了一个filename参数
http://localhost:63342/wushiyiwuzhong.com/file_downlaod.php?filename=index.php
这种时候我们可以控制filename参数去下载我们想下载的东西
比如我这里下载网站的上一级目录中的txt文件
我们通过../
去下载test.txt
成功下载网站上一级目录的文本文件
总结
可控参数在文件下载功能是比较危险的
本文来自博客园,作者:夜未至,转载请注明原文链接:https://www.cnblogs.com/wushiyiwuzhong/p/17825830.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?