###5.1 文件操作漏洞
简述
文件操作包括文件包含、文件读取、文件删除、文件修改以及文件上传,这几种文件操作的漏洞有部分的相似点,但是每种漏洞都有各自的漏洞函数以及利用方式,下面我们来具体分析下它们的形成原因、挖掘方式以及修复方案。
文件包含漏洞
PHP的文件包含可以直接执行包含文件的代码,包含的文件格式是不受限制的,只要能正常执行即可。文件包含又分为本地文件包含和远程文件包含,不管哪种都是非常高危的,滲透过程中文件包含漏洞大多可以直接利用获取webshell。文件包含两数有 include()、include_once()、require()和require_once(),它们之间的区别在于:include() 和include_once() 在包含文件时即使遇到错误,下面的代码依然会继续执行;而 require() 和 require_once() 则会直接报错退出程序。
本地包含
<?php
//初始化...
define("ROOT", dirname(__FILE__)."/");
//加载模块
$mod = $_GET['mod'];
echo ROOT.$mod.".php";
include(ROOT.$mod.".php');
?>
在统计目录下有另一个PHP文件info.php,内容如下;
<?php phpinfo();?>
此时,我们get请求,给mod的指定参数2,则会包含info的内容,从而被执行。
远程包含
<?php
include($_GET['url']);
?>
利用则在 GET 请求 url 参数里面传人 “http:/remotehost/1.txt”,其中远程机器上的1.txt 是一个内容为<?php phpinfo();?>。访问后返回本机的phpinfo信息。
值得注意的是,程文件包含需要设置 allow_url_include=On
也可以使用流操作方式:这里我们仍然用上面这个代码测试,只要执行 POST 请求 xx.php?a=php://input,POST 内容为 PHP 代码”<?php phpinfo();?>“即可打印出 phpinfo 信息。
截断
<?php
include $_GEI['a'].'.php'
?>
像上面代码方式的包含,就需要用到截断的方法进行成功包含。
第一种方式,利用%00来截断,%00 截断受限于 GPC和 addslashes 等函数的过滤。在5.3 之后的版本是不可取的。请求方式:请求 http://localhost/x.php?a=x.txt%00
第二种方式,利用多个英文句号(.)和加斜杠(/)来截断。同样在 PHP 5.3 版本之后被修复。请求方式,就是在x.txt后面添加足够的点或者反斜杠。在 Windows下测试是240个连接的点(.)能够截断,同样的点(.)加斜杠(/)
也是 240 个能够截断,Linux下测试的是 2038个/.组合才能截断。
第三种方式,远程文件包含时利用问号(?)来伪截断,请求方式就是x.txt?
文件读取、下载漏洞
文件读取漏洞与下载漏洞差别不大,这里就合并在一起说,文件读取漏洞在很多大型应用上都出现过,印象比较深的是 2012 年的时候 phpemsv9 的任意文件读取,可以直接读取数据库配置文件,当时也是有很多企业因为这个漏洞被入侵。这个漏洞很容易理解,部分程序在下载文件或者读取显示文件的时候,读取文件的参数 filename 直接在请求里面传递,后台程序获取到这个文件路径后直接读取返回,问题在于这个参数是用户可控的,可以直接传入想要读取的文件路径即可利用。
文件读取涉及到的危险函数,读取函数列表如下:
file_get_contents()、 highlight_file()、 fopen()、readfile()、 fread()、 fgetss()、 fgets()、
parse_ini_file()、 show_source()、 file(),除了这些正常的读取文件的兩数之外,另外一些其他功能的函数也一样可以用来读取文件,比如文件包含函数 include 等,可以利用PHP 输人输出流 php://filter/ 来读取文件。
文件上传漏洞
文件上传漏洞是出现最早的漏洞,也是最容易理解的漏洞,应用程序都是代码写的,代码都是写在文件里面执行的,如果能把文件上传到管理员或者应用程序不想让你上传的目录,那就是存在文件上传漏洞。注意这里并不是说一定是上传一个WebServer 可以解析的代码文件到可以解析的目录,漏洞的定义是做攻击目标不想让你做的事情,而你又发现可以做到。
不带过滤
<?php
move_uploaded_file($_FILES["file"]["tmp_ name"],$_FILES ["file"]["name"]);
?>
// move_uploaded_file 函数直接把上传的临时文件 copy 到了新文件。
黑名单过滤
$savefile = preg_replace ("/(php|phtml|php3|php4|jsp|exe|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.1$)/i","\\1\\2", $savefile);
典型的 IIS 默认是支持解析 ASP 语言的,不过在 IIS 下执行 ASP 的代码
可不止 .asp 这个扩展名,还有 cdx、asa、cer 等,如果代码里面没有把这些写全,一且漏掉一个就相当于没做限制。很明显上面说的 cdx 不在这个列表里面。
或者可以绕过的如:
in_array($FilenameExt, %20%E6%98%AF%E8%BF%94%E5%9B%9E%20false%E3%80%82#card=math&code=disallowed_types%29%20%E6%98%AF%E8%BF%94%E5%9B%9E%20false%E3%80%82&id=OOJbh)FilenameExt 的值为”php “,后面添加一个空格。
在上传时使用“%00” 来截断写入,如 “1.php%00.jpg”,写入的时候为PHP扩展文件
文件头、content-type 验证绕过
比如上传一个非图片文件会被提示不是图片文件,getimagesize()函数做的校验,获取图片大小,只要文件头是“GIF89a”,就会返回一个图片的尺寸大小。
content-type 是在 http request 的请求头里面,所以这个值是可以由请求者自定义修改的。image/pjpeg、image/jpg、image/jpeg、image/gif、image/png在只允许图片上传的情况下。
文件删除
文件删除漏洞出现在有文件管理功能的应用上比较多,这些应用一般也都有文件上传和读取等功能,它的漏洞原理跟文件读取漏洞是差不多的,不过是利用的函数不一样而已,一般也是因为删除的文件名可以用../跳转,或者没有限制当前用户只能删除他该有权限删除的文件。常出现这个漏洞的函数是 unlink(),不过老版本下 session_destroy() 函数也可以删除文件。
判断如果不是 sql 文件后,就直接在 databack 目录删除提交的文件名,代码中$filenames 函数从 GET 中提交,只要请求:filenames=../../index.php
即可删除 index.php 文件。
文件操作漏洞防范
文件操作漏洞在部分原理及利用方式上面都有一定相似性,所以下面我们分为通用防御手段和针对性防御手段来介绍怎么防御文件操作漏洞。
通用文件操作防御
对权限的管理要合理,比如用户 A上传的文件其他平行权限的用户在未授权的情况下不能进行查看和删除等操作,特殊的文件操作行为限定特定用户才有权限,比如后台删除文件的操作,肯定是需要限制管理员才能操作。
有的文件操作是不需要直接传人文件名的,比如下载文件的时候,下载的文件是已知的,则我们可以用更安全的方法来替代直接以文件名为参数下载操作,在上传文件时,只要把文件名、文件路径、文件ID(随机 MD5 形式)以及文件上人存储在数据库中,下载的时候直接根据文件 ID 和当前用户名去判断当前用户有没有权限下载这个文件,如果有则读取路径指向的这个文件并返回下载即可。
要避免目录跳转的问题,在满足业务需求的情况下,我们可以使用上面第二种的方法,但是有的情况下如后台进行文件编辑等操作时,需要传入文件路径的,可以在后台固定文件操作目录,然后禁止参数中有〝..”两个点和反斜杠“/以及斜杠“\”来跳转目录,怎么禁止呢?检查到传人的参数有这些字符,之间提示禁止操作并停止程序继续往下执行即可。
更新时间:2023-04-12 16:17