http 直接显示目录下文件_代码审计常见场景之文件操作

文件上传

1、关键词搜索

move_uploaded_file    ( string $filename   , string $destination   ) : bool

本函数检查并确保由 filename   指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 destination 指定的文件。

4ae25c3baa646dd764d8325b78b17843.png

2、场景代码

html>
"en">

    "UTF-8">
    Upload


"upload.php" method="post" enctype="multipart/form-data">type="file" name="file">type="submit" name="上传文件">



<?php
header("Content-type:text/html;charset=utf-8");
$upload_dir = 'E:\phpstudy\PHPTutorial\WWW\upload';
if(isset($_FILES['file'])){
    move_uploaded_file($_FILES['file']['tmp_name'],$upload_dir.'\\'.$_FILES['file']['name']);
    $upload_name = $_FILES['file']['name'];
    $upload_size = $_FILES['file']['size'];
    $upload_type = $_FILES['file']['type'];
    echo $upload_name.'
';
    echo $upload_size.'
';
    echo $upload_type.'
';
}else{
  echo '上传失败';
}

3、常见绕过

    https://www.freebuf.com/vuls/128846.html

4、修复方案

• 检测文件上传内容

–黑白名单验证,检测文件扩展名是否合法

–MIME验证,检测文件的MIME类型

–检索内容中的敏感关键词

• 限制文件大小

• 更改临时文件夹的路径,修改文件名

• 读取上传文件的绝对路径 与文件名称

• 隐藏文件路径

文件包含

1、漏洞经验

文件包含漏洞大多出现在模块加载、模板加载以及cache调用的地方,比如传入的模块名参数,实际上是直接把这个拼接到了包含文件的路径中,所以我们在挖掘文件包含漏洞的时候可以先跟踪一下程序运行流程,看看里面模块加载时包含的文件是否可控。

2、函数说明

include() 使用此函数,只有代码执行到此函数时才将文件包含进来,发生错误时只警告并继续执行。

inclue_once() 功能和前者一样,区别在于当重复调用同一文件时,程序只调用一次。

require() 使用此函数,只要程序执行,立即调用此函数包含文件,发生错误时,会输出错误信息并立即终止程序。

require_once() 功能和前者一样,区别在于当重复调用同一文件时,程序只调用一次。

3、搜索关键词

include()、include_once()、require()和require_once()

4、分类说明

本地文件包含(Local File Include,LFI),LFI允许攻击者通过浏览器包含本机上的文件。当一个WEB应用程序在没有正确过滤输入数据的情况下,就有可能存在这个漏洞,该漏洞允许攻击者操纵输入数据、注入路径遍历字符、包含web服务器的其他文件。

远程文件包含(Remote File Include,RFI), RFI允许攻击者包含远程文件,远程文件包含需要设置allow_url_include = On,四个文件都支持HTTP、FTP等协议,相对本地文件包含更容易利用,出现的频率没有本地包含多

//文件包含
<?php
$file = $_GET['name'];
if(isset($file)){
    include($file);
}

5、区分本地文件包含与目录遍历的关系

按目录遍历的定义会产生一个问题,这样的话目录遍历和上边的本地文件包含引起的本地敏感文件泄漏有什么区别呢?

• 从技术上来看,文件包含造成的信息泄漏是通过include、read等函数把文件读取到当前文件内进行展示;而目录遍历是中间件配置引发的问题。

• 从url表现上看,文件包含造成的信息泄漏文件名是一个参数,而目录遍历中的文件名在url中而不是一个参数。

• 从内容表现来看,文件包含造成的信息泄漏泄漏的信息是展示在html文件中;而目录遍历引发的信息泄漏是泄漏文件自己。

• 比如同是/etc/passwd:

漏洞url内容表现
文件包含http://www.vuln.com/vlun.php?filename=../../etc/passwd访问到的是vlun.php对应的html文件,/etc/passwd的内容被插入在该html文件中显示
目录遍历http://www.vuln.com/../../etc/passwd访问到的就是/etc/passwd本身,而不是将其内容显示在其他文件中

6、修复方案

• 关闭远程包含参数开关,彻底切断这个业务相比较。

• 设置类似白名单的方法,筛选固定文件名

• 常见目录穿越字符进行过滤,如(./ ../ ..\等)

文件读取和文件删除

1、常见读取函数

• fopen()

• file_get_contents()

• fread()

• fgets()

• fgetss()

• file()

• show_source()

• fpassthru()

• parse_ini_file()

• readfile()

• highlight_file()

allow_url_fopen选项激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象例如文件。默认的封装协议提供用 ftp 和 http 协议来访问远程文件,一些扩展库例如 zlib 可能会注册更多的封装协议

<?php 
if(isset($_GET['file'])){
    readfile("file".$_GET['file']);
}

2、文件删除函数

unlink    ( string $filename   [, resource $context  ] ) : bool

删除 filename。和 Unix C 的 unlink() 函数相似。发生错误时会产生一个 E_WARNING 级别的错误。

<?php 
$filename = $_GET['file'];
if(file_exists($filename)){
  unlink($filename);
  echo '文件删除成功';
}else{
  echo '获取文件失败';
}

漏洞防御

1、通用文件操作防御

文件操作漏洞利用有几个共同点如下:

1)由越权操作引起可以操作未授权操作的文件。

2)要操作更多文件需要跳转目录。

3)大多都是直接在请求中传入文件名。

我们需要这几个共同点来思考防御手段:

对权限的管理要合理,比如用户A上传的文件其他平行权限的用户在未授权的情况下不能进行查看和删除等操作,特殊的文件操作行为限定特定用户才有权限,比如后台删除文件的操作,肯定是需要限制管理员才能操作。

有的文件操作是不需要直接传入文件名的,比如下载文件的时候,下载的文件是已知的,则我们可以用更安全的方法来替代直接以文件名为参数下载操作,在上传文件时,只要把文件名、文件路径、文件ID(随机MD5形式)以及文件上传人存储在数据库中,下载的时候直接根据文件ID和当前用户名去判断当前用户有没有权限下载这个文件,如果有则读取路径指向的这个文件并返回下载即可。

要避免目录跳转的问题,在满足业务需求的情况下,我们可以使用上面第二说的方法,但是有的情况下如后台进行文件编辑等操作时,需要传入文件路径的,可以在后台固定文件操作目录,然后禁止参数中有“..”两个点和反斜杠“/”以及斜杠“\”来跳转目录,怎么禁止呢?检查到传入的参数有这些字符,之间提示禁止操作并停止程序继续往下执行即可。

2、文件上传漏洞防范

文件上传漏洞相比下载、删除更复杂,所以这里单独拿出来讲一下怎么防范,文件上传漏洞虽然定位起来比较简单,但是修复起来要考虑的东西还是不少,主要是不同环境下的利用场景比较多,需要比较完善的策略去防止漏洞出现。修复和防止一种漏洞之前,要比较全的清楚这种漏洞在不同环境下的利用方式,这样才能防御的比较全,文件上传漏洞主要有两种利用方式,分为上传的文件类型验证不严谨和写入文件不规范。针对这两种利用方式,我给出的防范方案如下:

1)白名单方式过滤文件扩展名,使用in_array或者三等于(===)来对比扩展名。

2)保存上传的文件时重命名文件,文件名命名规则采用时间戳的拼接随机数的MD5值方式"md5(time()+rand(1,10000))"。我们对之前的代码稍微改动下,给出示例代码如下:

function getExt ( $filename ) {
return substr ( $filename , strripos ( $filename , '.' ) +1 );
}
$disallowed_types = array ( 'jpg' , 'png' , 'gif' );
// 获取文件扩展名
$FilenameExt = strtolower ( getExt ( $_FILES["file"]["name"] ));
# 判断是否在被允许的扩展名里
if (! in_array ( $FilenameExt , $disallowed_types )) {
die ( "disallowed type" );
}
else
{
$filename = md5 ( time () +rand ( 1 , 10000 )) .".".$FilenameExt ;
// 移动文件
move_uploaded_file ( $_FILES["file"]["tmp_name"] , "upload/" . $FileName );
} ? >
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值