【问题标题】:Disable all CGI (php, perl, …) for a directory using .htaccess使用 .htaccess 禁用目录的所有 CGI(php、perl、...)
【发布时间】:2013-09-21 12:43:12
【问题描述】:

我有一个用户可以上传文件的目录。

为了避免安全问题(例如有人上传恶意 php 脚本),我目前通过附加 .data 来更改文件的扩展名,但是在下载文件时,他们必须手动删除 .data

另一种常见的解决方案是通过调用readfile() 将文件上传到Apache 不提供服务的目录和have a php script manage all downloads

我想做的是简单地禁止在上传文件夹中执行任何脚本(php、perl、cgi 脚本,无论我将来可能安装什么)。 This SO answer 建议在该文件夹的 .htaccess 文件中添加以下行:

SetHandler default-handler

但是,在我的情况下,这没有任何效果(我放在该文件夹中的示例 php 脚本仍然执行)。我做错了什么?

Apache 配置

这台机器是一个运行Debian GNU/Linux 6.0.7 (squeeze) 的 VPS(虚拟专用服务器),据我所知(我记下了我在该服务器上运行的所有命令,所以我的“记忆”应该非常准确),我认为'不要更改 apache2 配置中的任何内容,除了运行 sudo apt-get install php5 并使用以下内容创建文件 /etc/apache2/sites-enabled/mysite.com

<VirtualHost *:80>
  ServerAdmin webmaster@localhost
  ServerName  mysite.com
  ServerAlias www.mysite.com

  DocumentRoot /home/me/www/mysite.com/www/
  <Directory />
    Options FollowSymLinks
    AllowOverride All 
  </Directory>
  <Directory /home/me/www/mysite.com/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All 
    Order allow,deny
    allow from All
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/error.log

  # Possible values include: debug, info, notice, warn, error, crit,
  # alert, emerg.
  LogLevel warn

  CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

【问题讨论】:

  • SetHandler default-handler 可以很好地防止在子目录中执行 PHP 代码。确保将此作为第一行放在DOCUMENT_ROOTsubdir/.htaccess
  • @anubhava 感谢您的回复。在/etc/apache2/sites-enabled/mysite.com 中,我的DocumentRoot 设置为/home/me/www,而文件/home/me/www/subdir/.htaccess 包含一行SetHandler default-handler,可由www-data 读取(我使用sudo su www-data; whoami; cat /home/me/www/subdir/.htaccess 进行检查,所以我怀疑这个问题与AllowOverride 或类似的东西有关。
  • 请确保 .htaccess 已启用,方法是在其中放入一些垃圾文本,看看它是否会产生 500 错误。
  • @anubhava 是的,当我将垃圾放入.htaccess 时,我得到一个Internal Server Error,感谢您的提示,我不知道如何检查它是否已启用。我尝试在/etc/apache2/sites-enabled/mysite.com 中设置AllowOverride All,现在我得到一个奇怪的行为:访问http://mysite.com/subdir/ 时出现404 Not Found 错误,但访问http://mysite.com/subdir/script.php 仍然运行php 脚本。
  • 我尝试了各种选项(直接在/etc/apache2/sites-enabled/mysite.com 中),发现禁用PHP 脚本的唯一方法是输入&lt;Directory /home/me/www/subdir/&gt;php_flag engine off&lt;/Directory&gt;,甚至RemoveHandler .php .php3 .php4 .php5 .phtml 都不起作用。这对我来说意味着 PHP 似乎会短路 SetHandler 指令。不幸的是,这意味着如果有一天我安装了另一个 CGI 引擎,例如perl,那么我也需要记住禁用它,因此使用 php_flag engine off 绝对不是禁用文件夹执行脚本的可靠方法。

标签: apache .htaccess security


【解决方案1】:

把这个放在你的.htaccess:

<Files *>
    # @mivk mentionned in the comments that this may break
    # directory indexes generated by Options +Indexes.
    SetHandler default-handler
</Files>

但这有一些安全漏洞:可以在子目录中上传 .htaccess,并覆盖这些设置,它们也可能会覆盖 .htaccess 文件本身!

如果您担心该选项的行为将来会发生变化,请将其放入您的/etc/apache2/sites-enabled/mysite.com

    <Directory /home/me/www/upload/>
            # Important for security, prevents someone from
            # uploading a malicious .htaccess
            AllowOverride None

            SetHandler none
            SetHandler default-handler

            Options -ExecCGI
            php_flag engine off
            RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo
            <Files *>
                    AllowOverride None

                    SetHandler none
                    SetHandler default-handler

                    Options -ExecCGI
                    php_flag engine off
                    RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo
            </Files>
    </Directory>

如果无法修改apache配置,则将文件放在.htaccess,目录结构如下:

/home/me/www/
          |- myuploadscript.php
          |- protected/
              |- .htaccess
              |- upload/
                  |- Uploaded files go here

这样,没有人应该能够覆盖您的 .../protected/.htaccess 文件,因为他们上传的文件位于 .../protected 的子目录中,而不是 protected 本身。

AFAICT,你应该很安全。

【讨论】:

  • 好主意。一个更简单的解决方案是让 .htaccess 只对所有人可读。关闭原因,取决于 .htaccess 文件的编辑人员和方式,并非在所有情况下都有效。
  • @Tilebeck 虽然在文件上有chmod 444(只读)将阻止直接修改文件,但不会阻止替换文件(删除并创建新文件),如only the directory's permissions are involved in that operation,所以如果你不想改变它们的内容,我不建议你依赖只读文件。
  • 在某些情况下使用“SetHandler default-handler”会破坏目录索引(“Options +Indexes”)。我花了一段时间来缩小范围,所以如果有人遇到同样的问题,我会提到它。我收到 404 错误,日志只显示“[error] [client ...] Attempt to serve directory: /...”。
【解决方案2】:

我的 Godaddy 设置不允许我编辑 httpd.conf 文件,并且 php_flag 命令不起作用,因为他们为我实现了 php。

我可以在我的.htaccess 文件中使用它:

SetHandler default-handler
AddType text/plain php

我把它放在上面允许我的 FTP 用户访问的目录中,这会强制该目录中的所有 PHP 文件以及所有子目录将 php 显示为纯文本。

这也适用于其他文件类型。您需要做的就是添加另一行,其中包含您希望强制以纯文本显示的任何文件扩展名。以AddType text/plain cgi 为例

【讨论】:

  • 请注意保护您的.htaccess 文件,以免上传名为.htaccess 的文件并覆盖您的文件。请参阅我的答案结尾,了解如何在不访问 httpd.conf 的情况下执行此操作。
  • 好像我忽略了你帖子的结尾。在我自己实现它之前,我认为我不太了解它。你的建议正是我正在做的事情。 htaccess 在“/protected”中,而 FTP 用户只能访问“/protected/user”。我想我应该测试用户子目录中的附加 htaccess 文件不会覆盖顶级限制。我会假设它不会......但我不知道一切,并且假设以前让我陷入困境。
  • 我认为 AllowOverride None 应该解决这个问题,但我不能 100% 确定它是否不能以任何方式被覆盖。不过,您是对的,强化设置需要仔细考虑并仔细检查此类故障点。
猜你喜欢
  • 2010-11-19
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
相关资源
最近更新 更多