劫持通常与竞争条件相关。当两个不同的进程操作同一个文件的时候,就可能产生竞争条件。例如,一个读进程和一个写进程同时操作一段数据,当写进程只完成了一部分的时候,读进程已经完成,这样读的到内容一部分是新的,一部分是旧的,也就是我们常说的读脏数据。
临时文件的劫持,在一定程度上会造成竞争条件,除非劫持者准确的把握时间和位置,否则就会造成此类安全问题。
三、预防临时文件被恶意使用
前面我们介绍了临时文件的概念,以及临时文件被恶用可能带来的危害,这个部分主要介绍一些策略来预防临时文件被恶意利用,以及减少其带来的危害。
1.调整存放位置
防止临时文件被恶意利用的最重要,也是最简单的一步就是让你的临时文件目录以及名字不容易被猜到。任何对临时文件的恶意利用,攻击者都必须知道临时文件的名字和路径,因此你应该尽可能的让他难以猜到你的临时文件名字及路径。
建议你在临时文件目录的选择时,还是将你的临时文件放在默认的目录下吧,这样系统进程可以方便找到以及读写。而把精力花费放在为文件名想个合适的难猜的名字。
php的tempnam()函数,可以创建一个临时文件,并且其自动生成的文件名不会与当前目录下的其它文件名冲突,此函数创建的文件默认权限是600,即rw——-。
例如
$filename = tempnam( ‘..', ‘myTempfile');
运行后可能生成一个名为myTempfile1af的文件,当第二次运行的时候就生成了名为myTempfile1b0的文件名。
也许一些编程实践指南会建议你在使用tempnam()生成文件的时候,用一些有意义的前缀来命名,这样能通过文件名看出文件中包含的数据或者需要此数据的应用,但从安全性的角度来看最好不要这样,这样等于为攻击者指明了方向。
这里介绍一种方法,即能有一定意义的前缀同时也让攻击者不那么好猜,如下:
<?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 ); ?>
这个脚本通过uniqid()函数,生成的文件名格式为:/tmp/skiResort392942668f9b396c08.03510070,并通过chmod将文件的权限设置为600。
如果你需要与其它应用共享信息,比如用户密码或运行时生成的随机token,这里你可能需要对文件名加密,只有知道这个密钥的应用程序才能读取或修改文件内容。
如下是一个简单的生成加密文件名文件的示例:
<?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 ); ?>
2.约束访问权限
为了降低临时文件被执行或劫持的可能性,需要设置临时文件和临时文件目录的访问权限。通常情况下,将临时文件的权限设置为rw——-,临时文件目录的权限设置为rwx——。
此外,也可以通过设置apache的配置文件来限制访问(只有你将临时文件放在www目录下的时候),如下:
order deny,allow deny from all
3.只写已知文件
既然你是临时文件的创建者和作者,那你应该随时知道哪些文件存在,文件里有哪些内容。前面提到的方法,只是让临时文件劫持更困难,但不能完全杜绝劫持者替换文件或者在文件后面追加一些内容的可能,所以在你创建或写文件时,需要仔细检查文件内容是否满足要求。
当你使用w+的方式,创建了一个文件,在你开始写之前,这个文件应该为空,如下
<?php if ( filesize( $tempFilename ) === 0 ) { // write to the file } else { exit ( “$tempFilename is not empty.\nStart over again.”); } ?>
如果文件不为空,可能你创建的有问题,也有可能劫持者在你创建与写文件的这个时间段内作了手脚。