代码审计
PHP
前期准备
SQL注入篇
文件操作函数汇总
命令执行篇
XML实体注入篇
前端漏洞篇
反序列化篇
小技巧篇
其它资料
本文档使用 MrDoc 发布
-
+
首页
文件操作函数汇总
# 任意文件操作篇 ## 文件操作函数汇总 - 文件包含 - include/require/include_once/require_once/spl_autoload文件读取 - 文件读取 - file_get_contents/fread/readfile/file/highlight_file/show_source - 文件写入 - file_put_contents/fwrite/mkdir/fputs - 文件删除 - unlink/rmdir - 文件上传 - move_uploaded_file/copy/rename ## 文件上传漏洞 ### 文件上传流程 1. 检查文件大小、后缀、类型 2. 检查文件内容(如图片头等) 3. 提取文件后缀 4. 生成新文件名 5. 将上传临时文件拷贝到新文件名位置 ### 文件上传逻辑常见错误 - 只检查文件类型不检查文件后缀 - 文件后缀黑名单导致遗漏(如php3,php4等都可以被当作php文件执行) - 使用原始文件名,导致\0截断等漏洞(第四步出现问题,文件名用户可控) ### 文件上传案例 - **完全没校验** - 泛微Eoffice三处任意文件上传可直接getshell > https://wy.zone.ci/bug_detail.php?wybug_id=wooyun-2015-0125592 - 什么也没过滤 - 特点: - 常见于路由设备、内部平台等 - 可使用扫描器批量发现 - **前端验证** - 泛微Eoffice三处任意文件上传可直接getshell > https://wy.zone.ci/bug_detail.php?wybug_id=wooyun-2015-0125592 - 特点: - 服务器源码和前一种无任何差异 - JS进行文件名处理,无任何意义 - 可使用扫描器批量发现 - **Mime Type 检查的绕过** - 建站之星任意文件上传漏洞1 > https://wy.zone.ci/bug_detail.php?wybug_id=wooyun-2014-048841 - 特点: - 上传时检查Mime-Type,不检查文件后缀 - 或用Mime-Type生成文件后缀 - 利用:修改数据包中的Mime-Type - 可使用扫描器批量发现 ```php elseif ( !in_array( $file_info['type'], $typeArr ) ) 就检查了type ``` - PHP中上传的文件会被保存到`$_FILES`变量下。 ```php <?php var_dump($_FILES); ?> ``` - 用 burp 生成一个 URI 表单请求 1. 打开 burp,点击进入 Repeater 2. 右键 Paste URI as request ,将URI转为请求 3. 右键,Change request method 4. 在body中随便输入点什么,然后右键,Change body encoding。就能变成文件表单形式 - 请求如下: ``` 请求: POST /test.php HTTP/1.1 Host: localhost Accept-Encoding: gzip, deflate, br Accept: */* Accept-Language: en-US;q=0.9,en;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.127 Safari/537.36 Connection: close Cache-Control: max-age=0 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary3mM1hA5SoY2aAKsQ Content-Length: 151 ------WebKitFormBoundary3mM1hA5SoY2aAKsQ Content-Disposition: form-data; name="a"; filename="c.php" Content-Type: image/gif 1 ------WebKitFormBoundary3mM1hA5SoY2aAKsQ-- 响应: array(1) { ["a"]=> array(5) { ["name"]=> string(5) "c.php" ["type"]=> string(9) "image/gif" ["tmp_name"]=> string(50) "C:\Users\ZhangYudan\AppData\Local\Temp\php48D8.tmp" ["error"]=> int(0) ["size"]=> int(1) } } ``` - $_FILES是一个文件数组,key就是我们上传的name。结果里面的 type 就是上传时的 Content-Type,可以由用户自定义。 - tmp_name 就是临时文件的文件名,php上传时先将文件放入临时文件夹下,然后再经过 move_uploaded_file($_FILES['a']['tmp_name'],'./' . $FILES['a']['name']),如下: ```php <?php // 允许上传的图片后缀 $allowedExts = array("gif", "jpeg", "jpg", "png"); $temp = explode(".", $_FILES["file"]["name"]); echo $_FILES["file"]["size"]; $extension = end($temp); // 获取文件后缀名 if ((($_FILES["file"]["type"] == "image/gif") || ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/jpg") || ($_FILES["file"]["type"] == "image/pjpeg") || ($_FILES["file"]["type"] == "image/x-png") || ($_FILES["file"]["type"] == "image/png")) && ($_FILES["file"]["size"] < 204800) // 小于 200 kb && in_array($extension, $allowedExts)) { if ($_FILES["file"]["error"] > 0) { echo "错误:: " . $_FILES["file"]["error"] . "<br>"; } else { echo "上传文件名: " . $_FILES["file"]["name"] . "<br>"; echo "文件类型: " . $_FILES["file"]["type"] . "<br>"; echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>"; echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"] . "<br>"; // 判断当前目录下的 upload 目录是否存在该文件 // 如果没有 upload 目录,你需要创建它,upload 目录权限为 777 if (file_exists("upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " 文件已经存在。 "; } else { // 如果 upload 目录不存在该文件则将文件上传到 upload 目录下 move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]); echo "文件存储在: " . "upload/" . $_FILES["file"]["name"]; } } } else { echo "非法的文件格式"; } ?> ``` - **文件没有重命名** - 建站之星任意文件上传漏洞2 > https://wy.zone.ci/bug_detail.php?wybug_id=wooyun-2014-048760 - 特点: - 从POST变量中获取文件名(目录名) - 服务端语言不检查 \0 - 不重命名文件,导致 \0 进入操作系统 - 截断文件名,留下 xxx.php - 描述 - 检查了文件,但是没有重命名文件 - 在php5.4.7之前,move_uploaded_file是允许通过\0截断的。 - 在5.3.4之前,还允许其他的\0截断。 ```php <?php var_dump($_FILES); $filename = "1.php\0x001.gif" // 0x00 截断 move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $filename); ?> ``` ## 文件包含漏洞 - 视频教程讲师说目前不怎么考虑文件包含的情况了,除非系统比较老。 - 文件包含不等于文件读取漏洞 - PHP文件包含漏洞危害 - 文件读取 - 代码执行 - 常见位置 - 模板文件名(切换模板):MVC架构的模板文件名可控 - 语言文件名(切换语言):比如Cookie中保存了用户的语言,如下: - 文件包含漏洞限制 - 寻找可被包含的文件:上传文件、临时文件、Session文件、日志文件 - 后缀无法控制的情况:\0截断、协议利用 ```php <?php // 文件读取 readfile($_REQUEST['f']); echo file_get_contents($_REQUEST['f']); // 文件包含 include_once $_REQUEST['f']; ?> ``` ```php <?php $lang = $_COOKIE['lang']; // lang = zh-cn // 这里已经不算是一颗文件包含漏洞了 include_once 'template/'.$lang.'/index.php'; // lang=../../upload/1.gif // 前提是上传了一个内容才能getshell。需要找一些我们能控制的文件,上传文件、临时文件、Session文件、日志文件 include_once $lang; // 如果发现能上传1.html依旧可以getshell include_once $lang."html"; ?> // 没有上传文件,想执行任意代码,需要找到日志文件。将webshell通过数据包传入服务器,服务器可能在某些情况下将数据包文件保存到.log文件中。 ``` - **文件包含案例** - **什么过滤也没有的任意文件包含漏洞** - ThinkSNS任意文件包含(可getshell) > https://wy.zone.ci/bug_detail.php?wybug_id=wooyun-2014-056641 - 特点: - 使用 ThinkPHP框架 - ThinkPHP老版本模板位置变量副高 - 可包含任意文件 - 效果: - 包含上传的图片->执行任意代码 - **需要截断的任意文件包含漏洞** - ThinkSNS任意文件包含2 > - 特点: - 使用ThinkPHP框架 - 没有全局转义 - \0 不受过滤函数影响 - \0 截断导致任意文件包含漏洞 - 限制: - PHP5.3.4+对包含\0的文件操作函数进行了限制 - 突破:也有一些疏忽(CVE-2015-2348) - **可以控制协议的任意文件包含漏洞** - metinfo 5.3.10版本Getshell漏洞 > - 特点: - 可控前部分:inlcude $file.'.php'; // 只能包含php文件,这里如果开启了远程文件包含可以包含一个远程文件,如果不能的话,就有点鸡肋。 - http 协议利用:http://example.com/1.php - PHP 协议利用:zip/phar - 制作包含2.php的压缩包2.zip,然后重命名为2.jpg - 压缩包文件包含利用:zip:///var/www/upload/head/2.jpg#2.php - **# 号用于表示一个 fragment identifier(片段标识符),它通常用于指向文档中的特定部分。在 zip:// 这样的 URI 中,# 号后的内容可以表示压缩文件内的特定文件或目录。** ## 文件删除漏洞 - 案例:Discuz!X≤3.4 任意文件删除漏洞 > https://paper.seebug.org/411/ - 危害: - 删除服务器任意文件,DOS服务器 - 删除安装锁文件,导致目标环境可被重新安装 - 重新安装->任意重置管理员密码。网站安装完了有个文件,比如lock文件,删除了访问会重新安装。
别卷了
2024年9月25日 18:11
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码