首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将PHP(/PHP/Apache)的临时上传文件存储在RAM中,而不是文件系统(或仅加密)中?

将PHP(/PHP/Apache)的临时上传文件存储在RAM中,而不是文件系统(或仅加密)中?
EN

Stack Overflow用户
提问于 2011-04-18 10:25:06
回答 9查看 4.6K关注 0票数 38

原始问题

所以我正在做的项目是对文件上传的极度偏执。

在这个问题的范围内,我没有在有效载荷方面使用这个术语;我说的是机密性。

程序总是会崩溃,并让临时文件在文件系统中徘徊。这很正常。稍微保密的偏执狂可以写一个cronjob,每隔几分钟点击临时文件文件夹,并删除在cronjob调用之前几秒钟以上的任何内容(不是所有东西,只是因为它可能在上传过程中捕捉到一个文件)。

...unfortunately,我们让这个偏执狂更进一步:

理想情况下,除了进程相关的RAM之外,我们永远不会从任何地方看到文件上传的临时文件。

有什么方法可以教在内存中而不是在文件系统中查找临时文件吗?我们使用PHP作为CGI处理程序,Apache作为我们的We服务器,这样做更容易。(还请注意:这里的关键字是“filesystem”,而不是“disc”,因为当然有将文件系统映射到RAM的方法,但这并不能解决可访问性和自动崩溃后清理问题。)

或者,这些临时文件是否可以在写入磁盘时立即被加密的,以便在没有加密的情况下它们永远不会保存在文件系统中?

线程概述

不幸的是,我只能接受一个答案--但对于任何阅读这篇文章的人来说,整个帖子都是非常有价值的,并且包含了许多人的集体见解。根据你希望达到的目标,接受的答案对你来说可能并不有趣。如果你是通过搜索引擎来到这里的,请花点时间阅读的整个线程。

下面是用于快速参考的用例汇编:

Re: PHP的临时文件

  • RAM而不是光盘(例如,由于I/O考虑) RAMdisk/comparable (plasmid87,Joe )
  • 立即(每个文件系统-用户)加密encFS (ADW) (+ 抓到了 (按砂砂机))
  • 安全文件权限( ) )或SELinux (参见各种注释)
  • 进程附加内存而不是文件系统(因此进程崩溃会删除文件)(最初是问题的目的)
代码语言:javascript
复制
- don't let the file data reach PHP directly → [reverse-proxy](https://stackoverflow.com/questions/5701508/storing-php-php-fpm-apaches-temporary-from-upload-files-in-ram-rather-than-the/5878263#5878263) (_Cal_)
代码语言:javascript
复制
- disable PHP writing to the filesystem → [see PHP bug link in this answer](https://stackoverflow.com/questions/5701508/storing-php-php-fpm-apaches-temporary-from-upload-files-in-ram-rather-than-the/5867691#5867691) (_Stephan B_) or [run PHP in CGI mode](https://stackoverflow.com/questions/5701508/storing-php-php-fpm-apaches-temporary-from-upload-files-in-ram-rather-than-the/5877346#5877346) (_Phil Lello_)
代码语言:javascript
复制
- write-only files → [`/dev/null` filesystem](https://stackoverflow.com/questions/5701508/storing-php-php-fpm-apaches-temporary-from-upload-files-in-ram-rather-than-the/5904618#5904618) (_Phil Lello_) (this is useful if you have access to the data as a stream _additionally_ but cannot turn off the file-writing functionality that runs in parallel; whether PHP allows this is unclear)

Re:你的文件,上传

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2011-05-04 03:43:51

您考虑过在用户和web服务器之间放置一个层吗?在web服务器前面使用一些自定义代码的珀尔巴尔将允许您在上传的文件被写入任何地方之前拦截它们,对它们进行加密,将它们写入本地磁盘,然后在web服务器上代理请求本身(使用文件的文件名和解密密钥)。

如果PHP进程崩溃,加密的文件将被保留,但无法解密。没有未加密的数据被写入(Ram)磁盘。

票数 5
EN

Stack Overflow用户

发布于 2011-05-04 00:52:10

CGI到救援!

如果您创建一个cgi目录,并进行适当的配置,您将通过stdin获得消息(据我所知,文件不会以这种方式写入磁盘)。

所以,在apache配置中添加

代码语言:javascript
复制
ScriptAlias /cgi-bin/ /var/www/<site-dir>/cgi-bin/
<Directory "/var/www/<site-dir>/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>

然后编写一个CGI模式PHP脚本来解析post数据。从我的(有限)测试中,似乎没有创建任何本地文件。该示例转储它从stdin中读取的内容以及环境变量,以便您了解需要处理的内容。

示例脚本安装为/var/www//cgi/test

代码语言:javascript
复制
#!/usr/bin/php
Content-type: text/html

<html><body>
<form enctype="multipart/form-data" action="/cgi-bin/test" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
      <input type="submit" value="Send File" />
</form>
<pre>
<?
echo "\nRequest body\n\n";
$handle = fopen ("php://stdin","r");
while (($line = fgets($handle))) echo "$line";
fclose($handle);
echo "\n\n";
phpinfo(INFO_ENVIRONMENT);
echo "\n\n";
?>
</pre>
</body></html>

示例输出--这是我上传纯文本文件时的输出(源代码):

代码语言:javascript
复制
<html><body>
<form enctype="multipart/form-data" action="/cgi-bin/test" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
        <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
        <!-- Name of input element determines name in $_FILES array -->
        Send this file: <input name="userfile" type="file" />
          <input type="submit" value="Send File" />
</form>
<pre>

Request body

-----------------------------19908123511077915841334811274
Content-Disposition: form-data; name="MAX_FILE_SIZE"

30000
-----------------------------19908123511077915841334811274
Content-Disposition: form-data; name="userfile"; filename="uploadtest.txt"
Content-Type: text/plain

This is some sample text

-----------------------------19908123511077915841334811274--


phpinfo()

Environment

Variable => Value
HTTP_HOST => dev.squello.com
HTTP_USER_AGENT => Mozilla/5.0 (X11; U; Linux x86_64; en-GB; rv:1.9.2.16) Gecko/20110323 Ubuntu/10.04 (lucid) Firefox/3.6.16
HTTP_ACCEPT => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_LANGUAGE => en-gb,en;q=0.5
HTTP_ACCEPT_ENCODING => gzip,deflate
HTTP_ACCEPT_CHARSET => ISO-8859-1,utf-8;q=0.7,*;q=0.7
HTTP_KEEP_ALIVE => 115
HTTP_CONNECTION => keep-alive
HTTP_REFERER => http://dev.squello.com/cgi-bin/test
CONTENT_TYPE => multipart/form-data; boundary=---------------------------19908123511077915841334811274
CONTENT_LENGTH => 376
PATH => /usr/local/bin:/usr/bin:/bin
SERVER_SIGNATURE => <address>Apache/2.2.14 (Ubuntu) Server at dev.squello.com Port 80</address>

SERVER_SOFTWARE => Apache/2.2.14 (Ubuntu)
SERVER_NAME => dev.squello.com
SERVER_ADDR => 127.0.0.1
SERVER_PORT => 80
REMOTE_ADDR => 127.0.0.1
DOCUMENT_ROOT => /var/www/dev.squello.com/www
SERVER_ADMIN => webmaster@localhost
SCRIPT_FILENAME => /var/www/dev.squello.com/cgi-bin/test
REMOTE_PORT => 58012
GATEWAY_INTERFACE => CGI/1.1
SERVER_PROTOCOL => HTTP/1.1
REQUEST_METHOD => POST
QUERY_STRING =>  
REQUEST_URI => /cgi-bin/test
SCRIPT_NAME => /cgi-bin/test


</pre>
</body></html>
票数 4
EN

Stack Overflow用户

发布于 2011-05-05 23:30:18

我不熟悉PHP,所以我的答案不会直接映射到“如何做”,但我认为您是在对各种系统功能提供什么保护的一些误解下工作的,这导致您拒绝有效的解决方案,而选择具有完全相同安全属性的解决方案。从您的评论中,我估计您正在运行Linux;我的大部分回答都适用于其他unices,但不适用于其他系统,如Windows。

据我所见,你关心的是三种攻击场景:

  1. 攻击者获得对机器的物理访问权,关闭它,取出磁盘并将其内容读取给她的leasure。(如果攻击者能够读取您的RAM,您已经丢失了。)
  2. 攻击者可以以用户身份在计算机上运行代码。
  3. CGI脚本中的错误允许进程读取其他进程创建的临时文件。

第一类攻击者可以读取磁盘上所有未加密的内容,也不能读取任何用她没有的密钥加密的内容。

第二类攻击者能做什么取决于她是否能够作为运行CGI脚本的同一个用户运行代码。

如果她只能以其他用户的身份运行代码,那么保护这些文件的工具是权限。您应该有一个模式为700 (= drwx------)的目录,即只有用户可以访问,并且由运行CGI脚本的用户拥有。其他用户将无法访问此目录下的文件。你不需要任何额外的加密或其他保护。

如果她可以以CGI用户的身份运行代码(当然包括以root用户的身份运行代码),那么您已经失败了。如果您正在运行代码,您可以看到另一个进程的内存,因为同一个用户调试器总是这样做的!在Linux下,您可以通过/proc/$pid/mem轻松地看到它。与读取文件相比,读取进程的内存在技术上更具挑战性,但就安全性而言,两者没有区别。

因此,将数据保存在文件中本身并不是一个安全问题,

现在让我们来看看第三个关注点。令人担忧的是,CGI中的一个bug允许攻击者对文件进行窥探,但不允许运行任意代码。这与−的可靠性问题有关,如果CGI进程死亡,它可能会留下临时文件。但更通用的是:文件可能被并发运行的脚本读取。

防止这种情况的最佳方法实际上是完全避免将数据存储在文件中。这应该在PHP或其库级别完成,我无法控制。如果这是不可能的,那么空飞碟作为菲尔·莱洛是一个合理的解决方案: process会认为它在将数据写入一个文件,但是该文件将永远不会包含任何数据。

这里还有一个常见的unix技巧可能有用:一旦您创建了一个文件,您就可以取消链接(删除)并继续使用它。一旦文件未链接,就不能用它的前一个名称访问它,但是只要文件在至少一个进程中打开,数据就会留在文件系统中。但是,这对于可靠性非常有用,可以让操作系统在进程因任何原因而死时删除数据。可以使用进程权限打开任意文件的攻击者可以通过/proc/$pid/fd/$fd访问数据。可以随时打开文件的攻击者在创建文件到断开链接之间有一个小窗口:如果她能够打开该文件,她就可以查看随后添加到该文件中的数据。然而,这可能是有用的保护,因为它将攻击转化为时间敏感的攻击,可能需要多个并发连接,因此可以通过连接速率限制器进行反击,或者至少使其更加困难。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5701508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档