NGINX:防止下载脚本文件并执行

时间:2017-03-23 07:46:16

标签: php nginx

我看到这个问题要求1001次以上,并且坦率地说,无法通过nginx和PHP设置来实现这一点。我必须在生产中修复遗留应用程序,nginx和php-fpm在同一个盒子上运行 - 这意味着他们共享这个目录。

我的情况不同于99.999%的设置,因为我只允许提供类似STATIC的网站;但是,允许加载2或3个小PHP脚本页面。 除非已经匹配了显式URI,否则我不想允许执行PHP运行时。

不幸的是,如果有人要猜测'它是服务器上的一个php文件,下载了!

Blanket no-hold-bar temp-fix

我认为这是一个解决方案。但我需要有比我更多nginx经验的人来验证这个,因为它是一个敏感的网站。我只是无视任何PHP来做到这一点:

#
# case-insensitive match of anything *.php
location ~* \.php {
    # never allow a single .php page to run, ever.
    # no parsing, no lookup, nada.  stop dead in tracks.
    return 404;
}

没有此块,nginx会将下面的/var/www/cat-videos/cats.php文件作为下载文件发送!

Nginx下载的根本原因

我发现nginx会下载文件,因为( drumroll - 因为没有人能够解释为什么会发生这种情况 - 鼓声):

  • nginx.conf将default_type设置为application/octet-stream(也称为下载)。将此更改为,例如,text/plain显示PHP而不是下载它。这证明了这个配置变量是它的一部分。
  • nginx将提供root目录中的所有文件,无论其类型如何。如果没有匹配的mime-type,它将使用上面的default_type

你有它。如果您不想要它,请不要将文件放在nginx可以看到的地方! (相反,将所有php文件移动到root指令之外的另一个目录,并配置fastcgi以在其他地方进行通话)。例如。 /var/www/mysite-scripts-only/代替/var/www/mysite-static-version/

NGINX安全最佳实践?

php和静态网站有哪些最佳做法可以防止这种情况发生?将脚本移动到其他目录?运行两个不同的服务器,并使用proxy_pass

我认为最好将所有脚本文件(python,php,ruby等 - 所有类型的脚本)从静态文件中完全分开。并为类型设置特定的location指令,您可以通过proxy_passfastcgipassenger或类似的方式控制脚本访问。

这允许nginx默认提供静态站点中的任何内容,非常静态。

不,我不是在谈论"只需将X添加到location,而fastcgi应该阻止下载 - 不。我需要完全保证这永远不会再发生。从静态文件中分离脚本文件似乎是唯一100%这样做的方法,因为nginx只想在其根目录中提供所有内容。

可能会有更多特定的location覆盖或网址重写,这也会阻止所有请求在nginx中传递。还有可能在 root中使用其他location指令 - 但从我读到的内容来看,这通常是不受欢迎的。但是,解决这个问题超出了范围和时间。

工作原理

对于记录,这是我以前的nginx配置阻止php下载:

  • Nginx 1.10
  • php-fpm 7.0
  • 使用泊坞窗,而不是触碰/etc/nginx/conf.d/default.conf

以下是/etc/nginx/nginx.conf的相关内容。 (不使用conf.d/*,并不重要。)

http {
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    gzip                on;
    ...
    proxy_cache_path    /var/cache/nginx levels=1:2 keys_zone=reverse_cache:60m inactive=90m max_size=1000m;
    ...

    server {
        ...

        # Domain
        server_name      somerandomurl.blah;
        root             /var/www/cat-videos;

        ############################################
        # STATIC FILES SECTION
        ############################################
        location  / {
            index index.html
            try_files index.html =404;
        }
        location /assets/css/ {
        }
        location ~* .(jpg|png|gif|jpeg|css|txt)$ {
            proxy_cache_valid  200 120m;
            proxy_cache_lock   on;
            expires            1d;
            access_log         off;
        }

        ############################################
        # DYNAMIC PHP AREA ** DANGER ZONE **
        ############################################

        #
        # case-insensitive match of anything *.php
        location ~* \.php {
            # never allow a single .php page to run, ever.
            # no parsing, no lookup, nada.  stop dead in tracks.
            return 404;
        }

        # expose only 1 PHP page.
        # NOTE the SCRIPT_FILENAME I am setting manually.  This works fine.
        # for normal php sites, you'd most likely want to setup clean urls
        # and not use the php suffix, and use some of the normal vars you
        # see in the 1001+ tutorials out there.
        location ~ /process/cat-videos {
            include                 fastcgi_params;
            #fastcgi_pass            unix:/var/run/php/php7.0-fpm.sock;
            fastcgi_pass            php:9000;
            fastcgi_param           SCRIPT_FILENAME  /var/www/cat-videos/cats.php;
        }

那是旧的配置。我已经从静态目录中分离出所有脚本,并将fastcgi配置为与其他目录通信,如:

fastcgi_param SCRIPT_FILENAME /var/www/mysite-scripts-only/cats.php;

那些想让它保持动态的人可能想把它改成:

# don't use $document_root prefix on the path, move scripts elsewhere
fastcgi_param SCRIPT_FILENAME /var/www/mysite-scripts-only$fastcgi_script_name;

谢谢!

1 个答案:

答案 0 :(得分:0)

我已经与nginx和这个设置上的更多用户进行了交谈,并且除了我在原始问题中描述的内容之外,似乎没有任何其他方式。

他们说通过使用不同的根目录从静态文件中拆分脚本真的是最好的方法,我已经做到了。

因此,标记我自己的问题,因为它现在应该是一个Wiki。