热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP临时文件的安全性分析

这篇文章主要介绍了PHP临时文件的安全性分析,对于临时文件的安全性及防范措施作出了比较详细的阐述,需要的朋友可以参考下
一、简介
  临时文件,顾名思义是临时产生的文件,且文件的生命周期很短。

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

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?tmp_file=spellcheck46 ,攻击者分析你的url参数后使用http://bad.example.com/spellcheck.php?tmp_file=spellcheck45 就可以访问到前一个用户的验证结果了。

3.2 可执行性

  通常临时文件是不可执行,但如果攻击者上传了一个php脚本到你的临时目录,而且通过某种方式执行了它,那可能造成悲剧了。

3.3 临时文件被劫持

  攻击者可能为了自己的目的,而劫持你的临时文件。他可能替换你的临时文件,也可能在你的临时文件后面追加一些信息。

  劫持临时文件的目的包括:

(1)让你的应用程序处理他的数据,而不是你自己的数据
(2)暴露隐私数据,比如系统的密码文件,或者其它php安全模式不能正常读的文件
(3)删除数据,阻碍请求的正常进行
(4)创建并输出虚假的数据,破坏请求的结果
(5)通过提供虚假的数据,对使用数据进行下一步处理的应用程序造成破坏
(6)将你的输出重定向到其它地方,可以方便攻击者访问或者覆盖系统文件

  劫持通常与竞争条件相关。当两个不同的进程操作同一个文件的时候,就可能产生竞争条件。例如,一个读进程和一个写进程同时操作一段数据,当写进程只完成了一部分的时候,读进程已经完成,这样读的到内容一部分是新的,一部分是旧的,也就是我们常说的读脏数据。

  临时文件的劫持,在一定程度上会造成竞争条件,除非劫持者准确的把握时间和位置,否则就会造成此类安全问题。

三、预防临时文件被恶意使用

  前面我们介绍了临时文件的概念,以及临时文件被恶用可能带来的危害,这个部分主要介绍一些策略来预防临时文件被恶意利用,以及减少其带来的危害。

1.调整存放位置

  防止临时文件被恶意利用的最重要,也是最简单的一步就是让你的临时文件目录以及名字不容易被猜到。任何对临时文件的恶意利用,攻击者都必须知道临时文件的名字和路径,因此你应该尽可能的让他难以猜到你的临时文件名字及路径。

  建议你在临时文件目录的选择时,还是将你的临时文件放在默认的目录下吧,这样系统进程可以方便找到以及读写。而把精力花费放在为文件名想个合适的难猜的名字。

  php的tempnam()函数,可以创建一个临时文件,并且其自动生成的文件名不会与当前目录下的其它文件名冲突,此函数创建的文件默认权限是600,即rw——-。

例如

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

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

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

<&#63;php
// define the parts of the filename
define(‘TMP_DIR','/tmp/');
$prefix = ‘skiResort';
// construct the filename
$tempFilename = uniqid( $prefix, TRUE );
// create the file
touch( $tempFilename );
// restrict permissions
chmod ( $tempFilename, 0600 );
// now work with the file
// … assuming data in $value
file_put_contents( $tempFilename, $value );
// …
// when done with temporary file, delete it
unlink ( $tempFilename );
&#63;>

 这个脚本通过uniqid()函数,生成的文件名格式为:/tmp/skiResort392942668f9b396c08.03510070,并通过chmod将文件的权限设置为600。

  如果你需要与其它应用共享信息,比如用户密码或运行时生成的随机token,这里你可能需要对文件名加密,只有知道这个密钥的应用程序才能读取或修改文件内容。

  如下是一个简单的生成加密文件名文件的示例:

<&#63;php
$pathPrefix = ‘/tmp/skiResort';
// for demonstration, construct a secret here
$secret = ‘Today is ‘ . date( “l, d F.” );
$randomPart = sha1( $secret );
$tempFilename = $pathPrefix . $randomPart;
touch( $tempFilename );
chmod ( $tempFilename, 0600 );
// now work with the file
// … assuming data in $value
file_put_contents( $tempFilename, $value );
// …
// when done with temporary file, delete it
unlink ( $tempFilename );
&#63;>

2.约束访问权限

  为了降低临时文件被执行或劫持的可能性,需要设置临时文件和临时文件目录的访问权限。通常情况下,将临时文件的权限设置为rw——-,临时文件目录的权限设置为rwx——。

  此外,也可以通过设置apache的配置文件来限制访问(只有你将临时文件放在www目录下的时候),如下:

order deny,allow
deny from all

3.只写已知文件

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

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

<&#63;php
if ( filesize( $tempFilename ) === 0 ) {
// write to the file
} else {
exit ( “$tempFilename is not empty.\nStart over again.”);
}
&#63;>

  如果文件不为空,可能你创建的有问题,也有可能劫持者在你创建与写文件的这个时间段内作了手脚。

还有可能,你第一次成功写入了临时文件,但在你后面的写的过程中,劫持者对这个临时文件进行了一些操作,这种情况可以通过检验码的方式来检查,如下:

<&#63;php
// write something to the file; then hash it
$hashnow = sha1_file( $tempFilename );
$_SESSION['hashnow'] = $hashnow;
// later, get ready to write again
$hashnow = sha1_file( $tempFilename );
if ( $hashnow === $_SESSION['hashnow'] ) {
// write to the file again
// get and save a new hash
$hashnow = sha1_file( $tempFilename );
$_SESSION['hashnow'] = $hashnow;
} else {
exit ( “Temporary file contains unexpected contents.\nStart over again.”);
}
&#63;>

4.只读已知文件

  与只写已知文件类似,在读文件前需要检查检验码是否一致,防止临时文件被篡改。除此之外,如果你使用了openssl,可以在写文件的时候,将合法证书放在文件的末尾,这样的读的时候可以先检查文件末尾是否存在合法的证书;如果你没有使用openssl,也可以写入一段特定的算法生成的token,原理类似。

5.检查上传的文件

  判断文件是否是通过 HTTP POST 上传的

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']查看。

推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
author-avatar
一恒谢永泰_661
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有