Prevent Direct Access to a PHP Page

Prevent direct access to a php include file

The easiest way for the generic "PHP app running on an Apache server that you may or may not fully control" situation is to put your includes in a directory and deny access to that directory in your .htaccess file. To save people the trouble of Googling, if you're using Apache, put this in a file called ".htaccess" in the directory you don't want to be accessible:

Deny from all

If you actually have full control of the server (more common these days even for little apps than when I first wrote this answer), the best approach is to stick the files you want to protect outside of the directory that your web server is serving from. So if your app is in /srv/YourApp/, set the server to serve files from /srv/YourApp/app/ and put the includes in /srv/YourApp/includes, so there literally isn't any URL that can access them.

prevent direct url access to php file

You can do it with PHP

<?php
/* at the top of 'check.php' */
if ( $_SERVER['REQUEST_METHOD']=='GET' && realpath(__FILE__) == realpath( $_SERVER['SCRIPT_FILENAME'] ) ) {
/*
Up to you which header to send, some prefer 404 even if
the files does exist for security
*/
header( 'HTTP/1.0 403 Forbidden', TRUE, 403 );

/* choose the appropriate page to redirect users */
die( header( 'location: /error.php' ) );

}
?>

Prevent direct access to a php file but allow including it

Here are two options you could give a try:

<?php
/**
* Returns true if current file is included
*/

function isIncluded() {
$f = get_included_files();
return $f[0] != __FILE__;
}

if(!isIncluded()) {
// Do some stuff, eg: print some HTML
} else {
// Show 403/error
}

?>
<?php

// You can also use (recommended)
if(__FILE__ !== $_SERVER["SCRIPT_FILENAME"]) {
// this file is being included
}

?>

You may also opt to put the files into a directory protected by a .htaccess and a Deny from all since PHP can bypass that, but users cannot.

How to prevent direct access to a php page but can be accessed when redirected

Everything up to this working very fine...

Actually, I don't think it is...

...prevent direct access to a php page but can be accessed when redirected

This isn't just any PHP page. It is your 404 "Not Found" error document.

You should not be externally 3xx redirecting to your error document in the first place. The error document should be served in the same request (an "internal subrequest"). This is the root cause of your problem.

The redirected request is an entirely separate request, mostly indistinguishable from a "direct request", which will naturally make reliably blocking direct requests "impossible". However, do you really need to block "direct requests" to your 404 error document? (See below...)

ErrorDocument 404 http://localhost/news_21_off/404.php

By specifying an absolute URL (ie. with a scheme + hostname) in the ErrorDocument directive, Apache will trigger a 302 external redirect to the stated URL. The user sees a 302 response (not a 404), followed by a 200 "OK" (not a 404) from the redirected request, unless you manually send the 404 "Not Found" status in your PHP code (there is no evidence of that here).

Just because Apache allows you to "redirect" to the error document, doesn't mean you should. As noted in the Apache docs:

Note that when you specify an ErrorDocument that points to a remote URL (ie. anything with a method such as http in front of it), Apache HTTP Server will send a redirect to the client to tell it where to find the document, even if the document ends up being on the same server. This has several implications, the most important being that the client will not receive the original error status code, but instead will receive a redirect status code. This in turn can confuse web robots and other clients which try to determine if a URL is valid using the status code.

In addition, all the helpful PHP superglobals (passed from Apache) that ordinarily relate to the URL that triggered the 404 are lost (eg. $_SERVER['REDIRECT_STATUS'], $_SERVER['REDIRECT_URL'], etc.) because, as mentioned above, the redirected request is an entirely separate request.

99.99% of the time you should be using a root-relative URL-path in the ErrorDocument directive, so that Apache triggers an internal subrequest for the error document, for example:

ErrorDocument 404 /news_21_off/404.php
header('location:404.php');

Likewise, you should not be "redirecting" to your error document in your PHP code either.

In PHP, there are various ways to resolve this. You could simply include() the error document at the point in your code you wish to serve the 404.

For example, in your products.php script:

<?php
$pid = $_GET['pid'] ?? null;
if ($pid == '4') {
echo 'correct';
} else {
// 404 Not Found
include($_SERVER['DOCUMENT_ROOT'].'/news_21_off/404.php');
exit();
}

However, the above won't send a 404 HTTP status code to the client. In your PHP 404 error document you should set the HTTP status to ensure that a 404 status is sent by PHP and when/if the document is accessed directly by the user.

For example, in your 404.php script:

<?php
http_response_code(404);
?>
<h1>My 404 page</h1>

Incidentally, setting the HTTP status code in your PHP script will override any status that Apache might have set when serving an error document.

Now, back to your initial question...

I want to prevent direct access to my error page which is 404.php

Why?

Having implemented the changes above, if a user does "directly access" your 404 error document they are simply served a 404 and see the same response as if they had requested any other document that didn't exist.

So, unless you have a specific requirement, there is nothing more you need to do here.

preventing direct access to a php page, only access if redirected

What if everytime you were going to redirect you saved a value in the $_SESSION variable. So you have

//code
$_SESSION['fromMain'] = "true";
header("Location: noaccess.php");

Then in noaccess.php put

if($_SESSION['fromMain'] == "false"){
//send them back
header("Location: foo.php");
}
else{
//reset the variable
$_SESSION['fromMain'] = "false";
}

I really don't know if this would work or not, but this is what I would try off the top of my head.

How to deny direct access to php file on my website

The answers of Mudit Kashyap and Rohit Sahu are wrong and not reliable.

  1. The Client Request Header Field HTTP_X_REQUEST_WITH is not reliable because not every Client sends it. It is not a standard.

  2. The Client Request Header Field HTTP_REFERER is not reliable because there are situation when no Referer is sent or the user blocked to send it.

The only way to block the execution of the script for direct access is to check if a form is sent or not - if not then abort the execution of the script on the start of it.

// if you send your form with POST 
if(empty($_POST)) {
die("Access without a form sent using POST");
}

// if you send your form with GET
if(empty($_GET)) {
die("Access without a form sent using GET");

// if you send your form with POST but also allow GET
if(empty($_REQUEST)) {
die("Access without a form sent using REQUEST");


Related Topics



Leave a reply



Submit