Score:0

How can I return 404 when a user tries to manually browse to any ".php" extension on my site?

ml flag

I use PHP. I like to hide that I do. I used to have all of my PHP inside .html files, but frankly it's annoying having to reconfigure every editor/tool I use that .html actually means a PHP file.

So I've moved them all to .php, like a grown-up.

The extensions are hidden via try_files anyway - I didn't know about that when I was first setting out.

But a user can guess www.domain.com/index.php, and given that it loads fine, they'll know the site is built using PHP.

A minor issue, but one I'd like to quash. But how?

I naively tried this, near the top of my server block:

location ~ (\.php$) {
    return 404;
}

But that 404'd everything on the site. I guess because the location matches on the actual script that gets run, as opposed to what's in the user's address bar?

I then commented out the 404 line which had the LOVELY (/s) effect of sending my backend code to visitors as a download, along with their 404 page. I think because you can only match one location block, so it was matching, but then doing nothing with it, and just serving the code up?

Eurgh.

Before that I had tried

if( $request_uri ~ '\.php$' ) { return 404 ; }

In my server block. But that didn't seem to have any effect.

Given the disaster I created, I've decided to ask the experts...

Thank you!

Codemonkey avatar
ml flag
I see now my error was just in not having a space between `if` and `(`. Added a space and `reload`ed nginx and it works as expected
Score:1
ar flag

Don't. There's a few ways to solve this:

  1. Give up. Let people do what you want to avoid. The downside is negligible; any attacker worth their salt won't be defeated by what you do.
  2. Use a URL rewrite to rewrite URLs so what people see in the browser doesn't correspond to the filename. Keep your files as foo.php, but rewrite URL to example.com/foo.html.

For #2, something like

rewrite ^(.*)\.html$ $1.php last;

should probably work.

Codemonkey avatar
ml flag
I agree with point 1, largely. But if I DID want to do it... I don't think your point 2 answers what I was asking. That wouldn't stop someone going to `example.com/foo.php` and seeing that that file appears to exist.
vidarlo avatar
ar flag
@Codemonkey rewrite `^.*php$` to 404.
Codemonkey avatar
ml flag
Thanks, I don't think I knew you could use `rewrite` like that. Is that better than `if ($request_uri ~ '\.php$') { return 404; }`, and if so why? Thank you (See comment on my question)
Codemonkey avatar
ml flag
And why did you change it from `^(.*)\.html$` to `^.*php$`? (Other than - obviously - the `html`/`php` change!)
vidarlo avatar
ar flag
I don't know Nginx, so you would have to look up the particulars. If `if` is better? Maybe, I don't know.
us flag
`if` is a tricky concept that has confusing side effects: https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
vidarlo avatar
ar flag
@Codemonkey the syntax is regexp. That's worthy of a book and a box of aspirin, but in short `(.*)` matches any number of any character and saves it for reuse, so we can use it as `$1` later. `^` matches start of line, `$` end of line. `.` is any character, and `*` is zero or more of preceeding character.
Codemonkey avatar
ml flag
Yep, I'm fine with regexps - nginx is an unintuitive beast though, and I wondered if there was good reason why you changed it between your answer and your follow-up comment. I realise now it's just because you didn't need the capturing group for the 404 rewrite
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.