Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Which PHP files are necessary for public access?

I am installing Vanilla to a LEMP stack and my preference is to tell nginx which PHP files to send to the PHP interpreter. I'll admit PHP is still mostly PFM for me, but I know that most PHP packages only require a limited number of files to be accessed. For example, I configure nginx for Piwik by enabling only 3 PHP files be sent to the PHP interpreter.

I want to accomplish the same thing with Vanilla so that I don't have to enable PHP for the directory and subdirectories the forum is located in.

Tagged:

Best Answer

Answers

  • PFM = Pure Freaking Magic

    Thanks for the info. So far having only that PHP file enabled isn't causing any issues.

  • clarification...

    the access controls you are setting are only modifying what files can be "requested directly" via an http:// request. all of the php files are available to the php interpreter which uses all of the files necessary to process the request. basically, all calls are actually routed to the index.php file, which using the PFM of MVC determines what cascade of files will be processed to generate the http response... all in the name of index.php.

  • @hbf Thanks for the info! I don't know if you're familiar with nginx, but a location has to be configured to allow PHP to run. The nginx.org common pitfalls page recommends enabling only the PHP files that are required. All other PHP files will load as plain text. Obviously this can present other issues so configuration locations (such as the /conf/ directory in Vanilla) have to be completely blocked from public access. And, unfortunately, nginx does not support .htaccess files, which Vanilla has at least one that I'm aware of.

    BTW, you wouldn't happen to know why Vanilla always creates a new config.php file with 775 permissions, would you?

  • You don't want other php to be loaded an plaintext, becuase then the van view the content . Like hbf says you want all requests except static content to be routed through php. You can simply deny access to other php files.

    There are tutorial here an on the web on nginx server rules for vanilla. You can tighten the shop more.

    Generally you want to use try read how if is evil. You only want to use if if you properly understand the limitation and special counter-intuitive behaviour of using `if.

    grep is your friend.

  • @x00 I don't know all of the issues regarding broad enabling of PHP, but most places I've been to, including the nginx.org pitfalls page, recommend using the specific file locations. What would there be to learn about my configuration outside of the /conf directory? And how does that weigh against the risk of running a vicious PHP file?

  • @openletter said:
    x00 I don't know all of the issues regarding broad enabling of PHP, but most places I've been to, including the nginx.org pitfalls page, recommend using the specific file locations. What would there be to learn about my configuration outside of the /conf directory? And how does that weigh against the risk of running a vicious PHP file?

    @openletter I think you need to a broader under of nginx server rules. I'm not advocating a server wide enabling of php files.

    I would maybe read some books on the subject. We can give you pointer, and even share setups, but if you don't understand the rules you won't know what it all means.

    Every setup is different, and you take responsibility for your own server.

    But you don't want other php to be served in plain text. You deny access to any files you don't want direct access to. There is no advantage of serving file as plain text, you are revealing clues about your server.

    Note the framework like many already includes a piece of code at the stop of ever include file the prevent direct access. But you can take extra precautions.

    Include file do need to be parse by php even if they are not accessed directly. So interfering with that mean the framework will not work.

    So it is about getting a better grasp of what you are doing and want rules do what.

    grep is your friend.

  • regarding the question it has already been answered.There may be specific exceptions, however on a basic install that is basically what you need to know.

    MVC simplifies things, it all goes through the one dispatcher.

    grep is your friend.

  • @openletter said:
    hbf Thanks for the info! I don't know if you're familiar with nginx, but a location has to be configured to allow PHP to run. The nginx.org common pitfalls page recommends enabling only the PHP files that are required. All other PHP files will load as plain text. Obviously this can present other issues so configuration locations (such as the /conf/ directory in Vanilla) have to be completely blocked from public access. And, unfortunately, nginx does not support .htaccess files, which Vanilla has at least one that I'm aware of.

    BTW, you wouldn't happen to know why Vanilla always creates a new config.php file with 775 permissions, would you?

    Every web server approaches it a little different. I'm intimately (more than I ever planned to be) familiar with IIS and Apache. But the basic idea of a master level set of configurations what can be overwritten at the individual directory level is usually consistent. In IIS it is through the web.config file, in Apache it's the .htaccess, in nginx -- well, I don't know exactly.

    Your description of how php is handled would be consistent with a configuration where at the global level the .php extension is not associated to a filter type that routed to the php preprocessor, and instead is just treated as an available resource (since it's not being blocked)

    In Apache the global setting is to associate the .php with php.exe on the server side. in IIS it depend on the server version and how you set up the server if it auto associates file extensions such as .asp with the .NET interpreter. In both, you can override the default, dis-associating the extension with the ISAPI filter or even associating it with a different interpreter. in fact this is how you can actually serve PHP pages using Windows IIS, you just install PHP, then set an ISAPI Filter to route the php files through PHP.Exe, again this can be done at the server level or at an individual folder.

    The choice of how you set up your filters is, to me, a matter of preference more than anything. Most web applications will not give you specific guidance on what path you need to go down. Generally people (myself included) choose the most general purpose, AKA broadest application of settings possible, since it rarely presents a security issue if the application is well defined to begin with. others will go for the most secure approach possible. If you go that route then you can lock down everything and only serve resources that are explicitly green lighted. I don't use a least access security model, because it's a royal PITA to manage and get right.

  • @x00 If given the choice, I would still rather serve PHP files as plain text. Most of the PHP files are the same as the ones downloaded. I forgot to mention that I was blocking access to conf directories. However, I have researched creating more general rules to block access to PHP files specifically, while allowing access to other files.

    @hbf I'm not comfortable trusting that Vanilla developers, or any developers, for that matter, will create their software perfectly. By allowing only specific files to be passed to the PHP interpreter, I can make it just that much more difficult for a hacker to abuse my server.

    The configuration of nginx seems different from other web server software. Nginx is the only one that I'm familiar with, so I don't really have a basis for comparison. The way nginx works is that it will only pass PHP files to the PHP interpreter if it has instructions to do so, otherwise they are treated as any other file type.

    It is relatively easy to pass specific PHP files while denying access to other PHP files. My Vanilla configuration file looks like this:

    location = /forums/index.php {
        include global-configs/php.conf;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
    }
    
    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 ~ php$ { deny all; }
    }
    
    location @forum {
        rewrite ^/forums/(.+)$ /forums/index.php?p=$1 last;
    }
    

    Nginx will process these rules in the order they are written.

    The first location block tells nginx to pass the file /forums/index.php to the PHP interpreter using my usual PHP configuration file plus an additional rule that makes Vanilla forums a little better.

    The second location block tells nginx to treat some specific file types in the stated location as text/plain file types so they are not used to exploit the nginx index directive settings.

    The third location block applies some rules to make Vanilla forums a little better, prevent snoops from guessing hidden forums, and block access to php files. Note that /forums/index.php will not be denied because the above location directive specifies this location and thus nginx will have selected that directive to be applied to requests using that location.

    The last location block finishes up a directive condition created in the previous block.

    As you can see, this is not an overly complicated or difficult setup to use. Without the somewhat more complex directives being applied specifically for the Vanilla forum, the directive configuration set can be altered and applied to work with nearly any PHP package.

  • Yep, I get it. Definitely more work to set up your directives using least access. But potentially safer. Maybe I'll get bitten sometime by a hacker hell bent on bringing down my infamous forum, IDK. Until then, global directives basically location * or some such nonsense shall instruct my webserver to route php files through php.exe

  • edited October 2013

    @hbf Maybe I wrote that assuming others understood nginx as I do. For nginx, it's literally just one additional line: location ~ php$ { deny all; }.

  • x00x00 MVP
    edited October 2013

    @openletter said:
    hbf Maybe I wrote that assuming others understood nginx as I do. For nginx, it's literally just one additional line: location ~ php$ { deny all; }.

    I know nginx pretty well.

    Regardless of if you are using open source or not some sniffing protection is good. You want to future proof, and they don't just want to know about the core.

    It makes sense slightly performances wise to nest locations where you are using regexp like you are doing, but within literal matching, no real advantage, it is binary tree sorting. You want to avoid nesting more than one level.

    I think your category sniffing matching could be done better. for one it doesn't cover the eventuality with an optional trailing slash and any additional characters so it is easy to circumvent. Also there is little logic in how you have done the number matching, why not match any numerals of any length? Also you should put this block before the try_files, it more readable and efficient.

    I take it you already have general server rule this is just you vanilla configuration?

    grep is your friend.

  • @x00 Thanks for the tips! I've only been using nginx since around the beginning of this year. I was inspired by the Ars Technica Web Served series. I had messed around with Linux web servers before, but since my home ISP is unforgiving to web servers, I gave up some years ago, however I relatively recently learned about using cloud servers/VPS and using that series as a springboard I've taught myself a little bit about managing a web server. I definitely do not consider myself an expert!

    Yes, that is only the vanilla.conf file that I posted. I prefer to use conf files so my sites-available files stay nice and tidy and easy to read.

    The location blocks came from a discussion I had on the nginx mailing list. One of the senior members on the list suggested using the location = directive because when nginx sees that match, it immediately selects it. For the other blocks, nothing was mentioned about the issues you're describing, which they may have omitted as the issue I was trying to get at was not about overall efficiency, but passing specific php locations and blocking all others.

    The snoop-preventing block is a straight copy-and-paste from the Ars article Form the forum. Do you have an example recommendation to make on that block?

    I'm working on a site that is targeted at novice/enthusiast/would-be web server admins. In teaching myself how to manage a server, I have seen many people get turned off from other popular resources, most especially StackExchange (for all the wonderful help I've received there, the moderators are brutal unforgiving Nazis). In the Ars Technica article comments, forum posts, and IRC channels, I see people looking for solutions to things I have discovered (e.g. how to build a mail server), but they haven't had the same success in finding answers as I have. Also, for the people coming late to the Ars Web Served series (which pops up in many Google search results), many of the instructions are out of date and have broken links. My hope is that I can build a community of these admins where we welcome anyone of any level instead of banning n00bs onsite.

    Any information you want to provide on nginx and Vanilla (or anything else you want to contribute) would be very helpful! I have been working on a wiki for the site and have drafted several articles. There will be one article on installing Vanilla, which I will also post a link to in these forums for critique and usage by others (if someone wants to add something from it to the Vanilla wiki, for example).

  • The snoop-preventing block is a straight copy-and-paste from the Ars article Form the forum. Do you have an example recommendation to make on that block?

    simply

      location ~* /categories/[0-9]*(/.*)?$ {
          return 404;
      }
    

    I don't get why they did it like that, it is almost as it they are working round some limitation, but there is no such limitation. The bit on end the parenthesis is the main improvement, before you could simply ad / and anything else on the end, and the restriction was not there.

    grep is your friend.

  • @x00 I updated my vanilla.conf file to this:

    location = /forums/index.php {
        include global-configs/php.conf;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
    }
    
    location /forums/ {
        location ~* /categories/[0-9]*(/.*)?$ { return 404; }
        location ~* /uploads/.*.(html|htm|shtml|php)$ {
            types { }
            default_type text/plain;
        }
        try_files $uri $uri/ @forum;
        location ~ php$ { deny all; }
    }
    
    location @forum {
        rewrite ^/forums/(.+)$ /forums/index.php?p=$1 last;
    }
    

    I'm still not sure what you mean by binary tree sorting and nesting more than one level. Am I still doing those things?

  • Oops, the actual file I used has a ^ before /uploads/:

    location = /forums/index.php {
        include global-configs/php.conf;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
    }
    location /forums/ {
        location ~* /categories/[0-9]*(/.*)?$ { return 404; }
        location ~* ^/uploads/.*.(html|htm|shtml|php)$ {
            types { }
            default_type text/plain;
        }
        try_files $uri $uri/ @forum;
        location ~ php$ { deny all; }
    }
    location @forum {
        rewrite ^/forums/(.+)$ /forums/index.php?p=$1 last;
    }
    
Sign In or Register to comment.