PHP应用文件操作安全上传下载任意读取删除目录遍历文件包含(2024小迪安全Day32笔记)
文章目录
- 文件遍历上传下载删除编辑包含等
- 文件显示
- 方法一:scandir() (返回数组,使用方便)
- 方法二:opendir() / readdir()(流式读,内存友好)
- 文件下载
- 文件删除
- 文件读取
- 文件包含
- 基于以上各文件操作的安全思考
- 代码审计案例
- 1、Rrzcms遍历读取
- 2、Metinfo文件下载
文件遍历上传下载删除编辑包含等
文件显示
方法一:scandir() (返回数组,使用方便)
函数返回指定目录中的文件和目录列表,以数组形式返回
<?php
$path='D:\\phpstudy_pro\\WWW\\';
$file_dist=scandir($path);
foreach ($file_dist as $file){echo $file."<br>";
}
方法二:opendir() / readdir()(流式读,内存友好)
opendir() 函数用于打开指定的目录,返回句柄,用来读取目录的文件和子目录
readdir() 函数用于从打开的目录句柄中读取目录中的文件和子目录
$filehandle=opendir($path);
while (($file = readdir($filehandle)) !== false){echo $file."<br>";
}
结果显示如上图
文件下载
$file='1.php';
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $file . "\"");
header("Content-Length: " . filesize($file));
readfile($file);
下载原因,回显的数据包中解析为下载
通过控制响应头(例如
Content-Disposition: attachment; filename=...
和Content-Type
),诱导浏览器将返回的内容识别为下载协议并触发下载。
文件删除
unlink() 文件删除函数
调用命令删除:system shell_exec exec等
文件读取
1、fopen() fread() 文件打开读入
$file=fopen('1.php','r');
$data=fread($file,filesize('1.php'));
echo $data;
fclose($file);
2、file_get_contents() 读取文件内容
echo file_get_contents('1.php');
结果右键源代码看到
文件包含
包含即执行,相当于包含文件以php代码执行 任何后缀都可以
include、require、include_once、require_once等
1.txt内容为phpinfo()
include_once('1.txt');
基于以上各文件操作的安全思考
1、$path=‘D:\phpstudy_pro\WWW\’; 如果这个内容可控,就可造成路径遍历
以上的所有函数可控的地方能操作,就会造成文件安全问题
2、删除文件通过更改正常删除的数据包,尝试更改为别的目录文件
但具体能否删除还是要看权限与校验,如果能越权操作那么就是漏洞
代码审计案例
1、Rrzcms遍历读取
参考:https://xz.aliyun.com/t/10932
因为漏洞产生在后台,并不是很严重
利用白盒测试手法
1、抓包分析URL
2、判断为MVC,根据规则分析,比对源码,找到此功能触发的代码
疑问:文件名怎么知道,用fuzz字典跑
代码解释:
strpos($dir, 'template') === false
只是检查字符串里是否包含 “template”。攻击者可以构造一个路径同时包含 template 字样,但又携带..
返回上层目录。举例:path = template/../../../../etc/passwd
2、Metinfo文件下载
参考:https://mp.weixin.qq.com/s/te4RG0yl_truE5oZzna3Eg
文件可读==文件下载
?dir=http…\config\config_db.php
代码解释
$dir = str_replace(array('../','./'), '', $_GET['dir']);if(substr(str_replace($_M['url']['site'], '', $dir),0,4) == 'http' && strpos($dir, './') === false){header("Content-type: image/jpeg");ob_start();readfile($dir);ob_flush();flush();die;}
str_replace(array('../','./'), '', $input)
只是简单的字符串替换,并不能消除所有变体(例如反斜杠 \
、URL 编码、混合编码、符号链接、驱动器盘符等)。
后续检查 substr(...,0,4) == 'http'
与 strpos($dir,'./') === false
也都基于未规范化/未解码的 $dir
,容易被绕过。
readfile($dir)
会以文件或 URL wrapper 的方式读取并把原始内容输出 —— 没有做白名单/realpath/安全校验就可能把服务器上的任意文件(例如 config_db.php
)的源码泄露出来,或让用户下载任意文件。