网络编程 
首页 > 网络编程 > 浏览文章

PHP临时文件的安全性分析

(编辑:jimmy 日期: 2024/11/20 浏览:3 次 )

一、简介
  临时文件,顾名思义是临时产生的文件,且文件的生命周期很短。

  然而,很多应用的运行都离不开临时文件,临时文件在我们电脑上无处不在,主要有以下几种形式的临时文件:

1.文件或图形编辑程序,所生成的中间文件
2.数据库查询时,生成的临时缓存文件,提供之前的结果数据而,以减少再次访问数据库的代价;通常用于远程数据库或远程xml的服务
3.文件被上传后在服务端的临时储存,其文件名为php的全局变量$_FILES['userfile']['tmp_name']的值
4.在http请求中,用于存放session的临时文件,这些文件名通常就是sessionid(如 sess_7483ae44d51fe21353afb671d13f7199)
5.在不同应用或相同应用传递数据,而对方要求基于文件的输入,此时用临时文件存放数据

二、临时文件的安全特征

  临时文件的最大特征就是它的非持久性,除此之外,从安全性的角度,可以从以下几个方面关注临时文件的其它特点或风险:

1.临时文件的位置

  临时文件通常被创建并存放在默认的路径,在一个典型的Linux系统中,至少有两个目录或分区保持着临时文件。其中之一是/tmp目录,再者是/var/tmp。在更新的Linux内核的系统中,还可能有/dev/shm,它是用tmpfs文件系统装载的。有时临时文件,也可能放在用户home目录下的隐藏子目录中。使用默认临时文件目录的好处在于,系统进程可以方便查找和读写。

  然而,默认临时文件的存放目录可能成为损害系统安全的僵尸和rootkit的温床。这是因为在多数情况下,任何人(或任何进程)都可以向这些目录写入东西,有不安全的许可问题。比如我们都知道sticky bit,该位可以理解为防删除位。如果希望用户能够添加文件但同时不能删除文件, 则可以对文件使用sticky bit位。设置该位后,就算用户对目录具有写权限,也不能删除该文件。多数Linux发行版本在临时目录上设置sticky位,这意味着用户A不能清除属于用户B的一个文件,反之亦然。但是,根据文件自身的许可,用户A有可能查看并修改那个文件的内容。

2.临时文件的持久性

  前面提到临时文件是非持久的,在程序结束时,会被删除,但有的时候临时文件也会被迫持久保存了,没有被删除,如:

2.1 应用程序在关闭前崩溃了,还没有机会删除临时文件
2.2 应用程序还跑着,但操作系统崩溃了
2.3 文件复制过程中由于空间问题而复制失败,导致中间文件没有删除
2.4 操作系统进程通常会定期清空的默认临时文件目录,但可能因为某些原因,而删除失败
2.5 写得不好的应用程序,可能忽略或者忘记了删除临时文件

3.临时文件的风险性

  无用的临时文件像幽灵一样存在你的服务器上,一方面占用硬盘,另一方面,可以被其它人非法使用,存着如下一些风险:

3.1 可见性

  众所周知,将私有数据公开很有风险。一旦用户通过某些手段(如shell或者ftp)窃取了你的临时文件,就可以获取到用户或企业的私有数据,从而对你造成影响。

  例如:临时文件2011_Confidential_Sales_Strategies.tmp,可能暴露你们公司2011年的商业策略,这对你的竞争对手来说,将很有用处;而对于session劫持者来说,存放用户session信息的临时文件sess_95971078f4822605e7a18c612054f658非常关键。

  除此之外,还有别的情况临时文件可能会被偷窥,如:一个拼写检查的服务,返回结果的url是:http://bad.example.com/spellcheck.php"htmlcode">

$filename = tempnam( ‘..', ‘myTempfile');

  运行后可能生成一个名为myTempfile1af的文件,当第二次运行的时候就生成了名为myTempfile1b0的文件名。
也许一些编程实践指南会建议你在使用tempnam()生成文件的时候,用一些有意义的前缀来命名,这样能通过文件名看出文件中包含的数据或者需要此数据的应用,但从安全性的角度来看最好不要这样,这样等于为攻击者指明了方向。

  这里介绍一种方法,即能有一定意义的前缀同时也让攻击者不那么好猜,如下:

<"htmlcode">
<"htmlcode">
order deny,allow
deny from all

3.只写已知文件

  既然你是临时文件的创建者和作者,那你应该随时知道哪些文件存在,文件里有哪些内容。前面提到的方法,只是让临时文件劫持更困难,但不能完全杜绝劫持者替换文件或者在文件后面追加一些内容的可能,所以在你创建或写文件时,需要仔细检查文件内容是否满足要求。

当你使用w+的方式,创建了一个文件,在你开始写之前,这个文件应该为空,如下

<"htmlcode">
<"htmlcode">
bool is_uploaded_file ( string $filename )

  如果 filename 所给出的文件是通过 HTTP POST 上传的则返回 TRUE。这可以用来确保恶意的用户无法欺骗脚本去访问本不能访问的文件,例如 /etc/passwd。 如果上传的文件有可能会造成对用户或本系统的其他用户显示其内容的话,这种检查显得格外重要。

  为了能使 is_uploaded_file() 函数正常工作,必须指定类似$_FILES['userfile']['tmp_name'] 的变量,而不是从客户端上传的文件名 $_FILES['userfile']['name']。需要注意的是is_uploaded_file返回false,不一定是上传文件被劫持了,也有可能是文件太大或者上传部分等,这些可以通过$_FILES['userfile']['error']查看。

上一篇:PHP实现的英文名字全拼随机排号脚本
下一篇:PHP curl实现抓取302跳转后页面的示例