Passing / denying PHP requests

Hello-

I am trying to allow only the PHP files required for a given PHP
package to function correctly, then deny access to all other PHP files
to prevent people from snooping on the site’s configuration. I have
created the location block, but I’m not so good with regular
expressions and the block is assembled mostly through copy & paste.

location /installdirectory/ {
# from nginx pitfalls page
location ~*
(installdirectory/file_a|installdirectory/file_b|installdirectory/file_c).php$
{
include global-configs/php.conf;
}
location ~* installdirectory/.*.php$ {
deny all;
}
}

If someone can let me know if I am at least on the right track, I
would appreciate it.

Thanks!

Paul

On Wed, Oct 23, 2013 at 07:30:19AM -0700, Paul N. Pace wrote:

Hi there,

created the location block, but I’m not so good with regular
expressions and the block is assembled mostly through copy & paste.

If you don’t like regex, don’t use regex.

location = /installdirectory/file_a.php {
include global-configs/php.conf;
};
location = /installdirectory/file_b.php {
include global-configs/php.conf;
};
location = /installdirectory/file_c.php {
include global-configs/php.conf;
};

You probably want another location{} to “deny”, and that might be
“location ~ php$ {}”, or it might be that nested inside

location ^~ /installdirectory/ {}

depending on what else you want in the server config.

http://nginx.org/r/location for how the one location{} is chosen to
handle a request.

f

Francis D. [email protected]

On Wed, Oct 23, 2013 at 11:32:33AM -0700, Paul N. Pace wrote:

On Wed, Oct 23, 2013 at 9:49 AM, Francis D. [email protected] wrote:

Hi there,

“location ~ php$ { deny all; }” does not deny access to any php files,
even when nested in “location ^~ /installdirectory/ {}”. The previous
configuration “location ~* installdirectory/..php$ { deny all; }"
did block access to all php files. The ".
.” - is that why one works
and the other doesn’t?

I suspect not.

What “location” lines do you have in the appropriate server{} block in
your config file?

What one request do you make?

From that, which one location{} block is used to handle this one
request?

http://nginx.org/r/location for how the one location{} is chosen to
handle a request.

I read through the nginx.org explanation of the location directive,
but it isn’t helping me with understanding how to build the deny
statement.

Do whatever it takes to have these requests handled in a known
location{}
block.

Put the config you want inside that block.

If you enable the debug log, you will see lots of output, but it will
tell
you exactly which block is used, if it isn’t clear from the “location”
documentation.

Cheers,

f

Francis D. [email protected]

Thank you, Francis.

On Wed, Oct 23, 2013 at 9:49 AM, Francis D. [email protected]
wrote:

If you don’t like regex, don’t use regex.

You probably want another location{} to “deny”, and that might be
“location ~ php$ {}”, or it might be that nested inside

location ^~ /installdirectory/ {}

depending on what else you want in the server config.

“location ~ php$ { deny all; }” does not deny access to any php files,
even when nested in “location ^~ /installdirectory/ {}”. The previous
configuration “location ~* installdirectory/..php$ { deny all; }"
did block access to all php files. The ".
.” - is that why one works
and the other doesn’t?

http://nginx.org/r/location for how the one location{} is chosen to
handle a request.

I read through the nginx.org explanation of the location directive,
but it isn’t helping me with understanding how to build the deny
statement.

Hi Francis, and again thanks for your help in this matter. I would
have responded sooner but the day I was planning to resolve this issue
I had an unseasonably long power outage.

On Wed, Oct 23, 2013 at 11:41 AM, Francis D. [email protected]
wrote:

I suspect not.

What “location” lines do you have in the appropriate server{} block in
your config file?

hese are the location directives that would apply to the /forums/
directory, the /installdirectory/ of the server block that I’m
currently working on. This is an installation of Vanilla, but I’m
trying to come up with a general template that I can apply to other
packages (not a template as in one single file, but a way to apply
directives to each package I use):

server {

location = /forums/index.php {
include global-configs/php.conf;
fastcgi_split_path_info ^(.+.php)(.*)$;
}

location ^~ forums/ {
location ~ php$ { deny all;}
}

#location ~* forums/.*.php$ {

deny all;

#}

location ~* ^/forums/uploads/.*.(html|htm|shtml|php)$ {
types { }
default_type text/plain;
}

location /forums/ {
try_files $uri $uri/ @forum;
location ~* /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ {
return 404;
}
}

location @forum {
rewrite ^/forums/(.+)$ /forums/index.php?p=$1 last;
}
}

statement.

Do whatever it takes to have these requests handled in a known location{}
block.

Put the config you want inside that block.

Do you mean that I should single out each php file and create a
location block to deny access the file?

If you enable the debug log, you will see lots of output, but it will tell
you exactly which block is used, if it isn’t clear from the “location”
documentation.

I navigated to /forums/login.php. Here seems to be the pertinent part
of error.log:

2013/10/25 21:39:19 [debug] 2771#0: *1 test location: “forums/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: “/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: “phpmyadmin/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: “forums”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: “/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: “index.php”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~
“/categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “/.”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “~$”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “piwik/config/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “piwik/core/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~
“(piwik/index|piwik/piwik|piwik/js/index).php$”
2013/10/25 21:39:19 [debug] 2771#0: 1 test location: ~
"^/forums/uploads/.
.(html|htm|shtml|php)$"
2013/10/25 21:39:19 [debug] 2771#0: *1 using configuration “/forums/”

I’m not sure which location block is “/forums/”. The login.php file is
served as a downloadable file.

Thanks!

Paul

On Fri, Oct 25, 2013 at 02:44:57PM -0700, Paul N. Pace wrote:

On Wed, Oct 23, 2013 at 11:41 AM, Francis D. [email protected] wrote:

On Wed, Oct 23, 2013 at 11:32:33AM -0700, Paul N. Pace wrote:

Hi there,

Hi Francis, and again thanks for your help in this matter. I would
have responded sooner but the day I was planning to resolve this issue
I had an unseasonably long power outage.

No worries, there’s no rush on this.

“location ~ php$ { deny all; }” does not deny access to any php files,
even when nested in “location ^~ /installdirectory/ {}”.

What “location” lines do you have in the appropriate server{} block in
your config file?

hese are the location directives that would apply to the /forums/
directory, the /installdirectory/ of the server block that I’m
currently working on.

nginx has very specific rules on how the one location to handle this
request is chosen. Until you understand those rules, you will be
guessing
whether or not your config will work. It’s simpler not to have to guess.

In this case, the request is “/forums/login.php”.

location = /forums/index.php {

It cannot match that, because the request and the location are not equal
(up to the first ? or # in the request).

location ^~ forums/ {

It cannot match that (in fact, nothing normal can) because if the first
character of a prefix match is not “/” it is unlikely to be useful.

location ~ php$ { deny all;}

It could match that, except it doesn’t because only top-level
location{}s
are considered initially.

#location ~* forums/.*.php$ {

It could have matched that, except it is commented out.

location ~* ^/forums/uploads/.*.(html|htm|shtml|php)$ {

It does not match that, because the request does not include “/uploads”.

location /forums/ {

It can match that, because the location and the request have the same
prefix.

location ~* /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ {

It does not match that.

location @forum {

It does not match that, because named locations are not considered for
an initial request.

So, of that set the only possible match is /forums/, where the
configuration

try_files $uri $uri/ @forum;

says “serve it if the file exists”. The file exists, and nothing says
to proxy_pass or fastcgi_pass or anything, so the file content should
be sent as-is.

Do whatever it takes to have these requests handled in a known location{}
block.

Put the config you want inside that block.

Do you mean that I should single out each php file and create a
location block to deny access the file?

You have one group of requests that you want handled in one way, and
another group handled in another. You need some way of distinguishing
those groups - either singly or using patterns.

“/categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “/.”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “~$”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “piwik/config/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~ “piwik/core/”
2013/10/25 21:39:19 [debug] 2771#0: *1 test location: ~
“(piwik/index|piwik/piwik|piwik/js/index).php$”
2013/10/25 21:39:19 [debug] 2771#0: 1 test location: ~
"^/forums/uploads/.
.(html|htm|shtml|php)$"

The bit after "location: " on each line should look familiar from the
complete list of location blocks in your real config file.

2013/10/25 21:39:19 [debug] 2771#0: *1 using configuration “/forums/”

I’m not sure which location block is “/forums/”. The login.php file is
served as a downloadable file.

You’ve shown only one location block that has “/forums/” as its
uri. That’s the one.

In that block, you say “send the file”, so that’s what nginx does.

I don’t think I can explain it any better than the combination of nginx
documentation and previous list mails.

Perhaps if you put as the first line inside each location block ‘return
200 “this is location N”;’, for varying values of N; then when you
use “curl” to access each request in turn, it will become clear which
location{} is chosen for each request, and it will become clear why that
location was chosen.

Then you’ll be able to put the config you want in the location{} that
is chosen.

Good luck with it,

f

Francis D. [email protected]