文件遍历上传下载删除编辑包含等
$_FILES:PHP中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,并将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、临时文件名等信息。
$_FILES"表单值" 获取上传文件原始名称
$_FILES"表单值" 获取上传文件MIME类型
$_FILES"表单值" 获取上传文件字节单位大小
$_FILES"表单值" 获取上传的临时副本文件名
$_FILES"表单值" 获取上传时发生的错误代码
move_uploaded_file() 将上传的文件移动到指定位置的函数
#文件显示:
1.打开目录读取文件列表
2.递归循环读取文件列表
3.判断是文件还是文件夹
4.PHP.INI目录访问控制
is_dir() 函数用于检查指定的路径是否是一个目录
opendir() 函数用于打开指定的目录,返回句柄,用来读取目录的文件和子目录
readdir() 函数用于从打开的目录句柄中读取目录中的文件和子目录
open_basedir:PHP.INI中的设置用来控制脚本程序访问目录
scandir() 函数返回指定目录中的文件和目录列表,以数组形式返回
ini_set('open_basedir',DIR); 设置配置文件中,只能访问本目录
scandir 函数遍历目录
用opendir 加 readdir 函数遍历文件目录 用两个“\\\\” 防止一个\\时识别为转义字符
#文件删除:
unlink() 文件删除函数
调用命令删除:system shell_exec exec等
unlink() 函数 1.txt和file.php 在同一级 访问地址后1.txt被删除,输出文件名
用系统命令删除文件
#文件下载:
修改HTTP相应头实现文件读取解析下载:
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename="" . $file . """);
header("Content-Length: " . filesize($file));
readfile($file);
这里正常访问1.php 是可以正常显示内容的
当访问file.php 时就变成下载1.php文件了,这里可以打开f12 查看数据包响应头内容 ,就会出现代码中的那几句修改头参数的值 的内容
#文件读取:
1、file_get_contents() 读取文件内容
2、fopen() fread() 文件打开读入
右键 点击查看页面源代码
#文件包含:
include、require、include_once、require_once等
直接访问写有php代码的txt文件时,只会讲php代码输出出来,而不会执行
当访问file.php 时,1.txt中的php代码就会被执行
require
include_once
require_once
实践:
让ai写一个文件编辑,下载,读取,删除的功能
<?php // 设置默认路径 $directory = isset($_GET['dir']) ? $_GET['dir'] : './'; // 文件操作 if (isset($_POST['action'])) { if ($_POST['action'] == 'create_folder' && !empty($_POST['folder_name'])) { // 创建文件夹 mkdir($directory . '/' . $_POST['folder_name']); } elseif ($_POST['action'] == 'delete' && isset($_POST['file'])) { // 删除文件或文件夹 $path = $directory . '/' . $_POST['file']; if (is_dir($path)) { rmdir($path); // 删除文件夹 } else { unlink($path); // 删除文件 } } elseif ($_POST['action'] == 'rename' && isset($_POST['file']) && isset($_POST['new_name'])) { // 重命名文件或文件夹 rename($directory . '/' . $_POST['file'], $directory . '/' . $_POST['new_name']); } elseif ($_POST['action'] == 'save_edit' && isset($_POST['file']) && isset($_POST['file_content'])) { // 保存文件内容 file_put_contents($directory . '/' . $_POST['file'], $_POST['file_content']); } } // 下载文件 if (isset($_GET['download']) && !empty($_GET['download'])) { $file = $directory . '/' . $_GET['download']; if (file_exists($file)) { // 设置下载头 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($file) . '"'); header('Content-Length: ' . filesize($file)); readfile($file); exit; } else { echo '文件不存在!'; } } // 读取文件内容 $content = ''; if (isset($_GET['read']) && !empty($_GET['read'])) { $file = $directory . '/' . $_GET['read']; if (file_exists($file)) { $content = file_get_contents($file); } else { $content = '文件不存在!'; } } // 列出目录中的文件和文件夹 $files = scandir($directory); $files = array_diff($files, array('.', '..')); // 排除 . 和 .. ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PHP 文件管理器</title> <style> body { font–family: Arial, sans–serif; } .file–manager { max–width: 800px; margin: 0 auto; padding: 20px; } table { width: 100%; border–collapse: collapse; } th, td { padding: 10px; border: 1px solid #ddd; } th { text–align: left; } .action–buttons { margin–top: 20px; } .action–buttons form { display: inline–block; margin–right: 10px; } .content–area { margin–top: 20px; } textarea { width: 100%; height: 300px; } </style> </head> <body> <div class="file-manager"> <h2>文件管理器</h2> <h3>当前目录:<?php echo $directory; ?></h3> <!– 文件和文件夹列表 –-> <table> <thead> <tr> <th>名称</th> <th>类型</th> <th>操作</th> </tr> </thead> <tbody> <?php foreach ($files as $file): ?> <tr> <td> <?php if (is_dir($directory . '/' . $file)): ?> <a href="?dir=<?php echo urlencode($directory . '/' . $file); ?>"><?php echo $file; ?>/</a> <?php else: ?> <?php echo $file; ?> <?php endif; ?> </td> <td><?php echo is_dir($directory . '/' . $file) ? '文件夹' : '文件'; ?></td> <td> <!– 删除操作 –-> <form action="" method="POST" style="display:inline;"> <input type="hidden" name="action" value="delete"> <input type="hidden" name="file" value="<?php echo $file; ?>"> <button type="submit" onclick="return confirm('确定要删除此文件吗?');">删除</button> </form> <!– 下载操作 –-> <?php if (!is_dir($directory . '/' . $file)): ?> <a href="?download=<?php echo urlencode($file); ?>">下载</a> <?php endif; ?> <!– 重命名操作 –-> <form action="" method="POST" style="display:inline;"> <input type="hidden" name="action" value="rename"> <input type="hidden" name="file" value="<?php echo $file; ?>"> <input type="text" name="new_name" placeholder="新名称" required> <button type="submit">重命名</button> </form> <!– 编辑操作 –-> <?php if (!is_dir($directory . '/' . $file)): ?> <a href="?read=<?php echo urlencode($file); ?>">编辑</a> <?php endif; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <!– 创建新文件夹 –-> <div class="action-buttons"> <h3>创建新文件夹</h3> <form action="" method="POST"> <input type="hidden" name="action" value="create_folder"> <input type="text" name="folder_name" placeholder="文件夹名称" required> <button type="submit">创建</button> </form> </div> <!– 文件内容区 –-> <?php if (!empty($content)): ?> <div class="content-area"> <h3>编辑文件</h3> <form action="" method="POST"> <input type="hidden" name="action" value="save_edit"> <input type="hidden" name="file" value="<?php echo $_GET['read']; ?>"> <textarea name="file_content"><?php echo htmlspecialchars($content); ?></textarea><br> <button type="submit">保存更改</button> </form> </div> <?php endif; ?> </div> </body> </html>
效果
点击目录时会进到该目录下,上面会有一个参数,通过修改参数实现跳级 %2F 就是 /
在后面加一个../ 就跳一级,就到了上级目录 这里跳不了盘,可能有限制 这里是文件显示
当点击编辑某个文件时,上面的参数名变了 那这里是不是可以实现对上级文件的编辑呢,从而拿到代码
在这个目录上级中有一个upload.html 文件,这里尝试读取它,发现可以成功读取, 当目标有这个编辑功能时,可以测试一下,黑盒中用fuzz工具去跑文件名,拿到文件名再来测试
删除文件,这里先测试一下,先删除了1.txt 在f12 下的负载中看到delete 字样 ,下面还有一个1.txt,猜想,如果我把1.txt 改成上级目录下的某个文件,是否可以对其进行删除呢?
打开butp 拦截 删除操作数据包 ,将1.txt 修改成../upload.html 然后把数据包放出去,在回到浏览器中点击确认删除,再去上级目录查看一下,upload.html 文件是否被删除了,这里测试是可以删除的
上述测试,可以对任意文件进行修改,删除,读取
#代码审计案例
1、Rrzcms遍历读取
https://xz.aliyun.com/t/10932
先安装一下
这里其实是一个伪静态的页面
登录一下后台页面
进来后找到有关文件的地方,这里演示时虽然是在后台管理员里面操作,但是实战时只要普通用户也有文件操作的功能也可以作为测试点,这里分黑盒和白盒,黑盒就尝试是否可以跳级等等,白盒就直接从代码里面看
黑盒测试
打开burp 拦截数据包,然后修改参数值在放出去
这里看到一个参数 path ,尝试修改它,看是否能跳级
将path值改成 ../ 再放出去,发现不行
白盒中,先按照url找到对应的文件
然后进到文件里面找调用的方法,直接搜索,发现这里是要带 template 如果参数值没有这个就会报错
这里保留template 然后输入,,/index.php 成功读取到上级目录的index.php 文件
2、Metinfo文件下载
任意文件下载+读取+删除
3、Xhcms文件包含
https://xz.aliyun.com/t/11310
评论前必须登录!
注册