Link to home
Start Free TrialLog in
Avatar of Torquil Beavis
Torquil BeavisFlag for Canada

asked on

Redirecting to private directory from the public browser-accessible directory in PHP

Hi:
I use AWS linux and PHP 7.0.27
I want to make access to my scripts more secure to prevent a hacker from adding to the URL to get access to a script directly. I read that putting scripts into a private, 'inaccessible from the browser' directory, then no access using the browser would be possible. Access would only be by PHP.

The directory structure ..

/var/www/html/index.php (public)      root:root

/var/www/private/script1.php (private)            root:apache

If I code an include script in index.php and place the include script in private, the include script is accessed as expected.

However, when I want to access a non-include script (script1.php) from index.php with ..

$url = "./private/script1.php";
ob_end_clean();
header("Location: $url");
exit();

the browser throws the error ..
'The requested URL /private/script1.php was not found on this server.'

I guess this is because index.php is in the public directory for access to/from the browser, and script1.php is in the disallowed private directory,

In this scenario, how can I code PHP to make index.php redirect to script1.php?
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

This statement... header("Location: $url");  tells the browser to go to that location.  Which it can't do because it is private and not web accessible.  You might be able to use an 'include' statement but I'm not sure.
Avatar of Torquil Beavis

ASKER

Hi Dave. Yes, includes work, however I was trying to find a way of not using includes.
Likely better to think of this in a much simpler way.

1) Disable all .php file execution from any external access.

2) Allow .php file execution from localhost.

3) Add any exceptions required, for example, wp-login.php for WordPress. With any CMS system you'll likely have exceptions.

4) This way when bare URLs are hit, they get converted to index.php locally, so the only way to execute any .php is by executing index.php files implicitly, by visiting URLS with index.php or any other filename in the URL.

Note: This is easy, if this is a new design + you build your entire system around this requirement. Bolting this onto an old system can require a bit of time.

I'm looking around for an example of how to do this + post it when I find one.
Effectively, I'm looking at hiding all my scripts (including includes) within private directories, only initially accessed by the index file.

I want to prevent hackers from taking the url for a script then adding on directories of other scripts or includes which may be within the seen directory.
Great, David. I'm keen to see an example of how to do this.
ASKER CERTIFIED SOLUTION
Avatar of David Favor
David Favor
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes, includes work, however I was trying to find a way of not using includes.
Why?  Unless your PHP code is poorly written, no one can see what's in the 'include' or where it came from.  They won't even know it's there.

I see two issues here.  #1:  PHP code runs only on the server and can't be seen by outsiders although the results may be sent to the browser.  #2:  Everything that the browser gets is visible and can not be hidden because that would hide it from the browser.
So, in my Apache-2.4 ..

<Files *.php>
	Require all denied
	Require local
</Files>

<Files index.php>
	Require all granted
</Files>

Open in new window


If I have browser menu choices to .php files, would these be excluded?
I should have provided a full 2.4 version.

Yes. Your version looks correct.

For browser menu choices... if these are .php files you'll exclude them.

Or... you can use alias your .php files to directories containing index.php files.
The reason for me not wanting includes in particular situations is when I need the script being redirected to having a completely different environment from the sending script. My other scripts all use includes.

My challenge, Dave, is that if in a script I have 3 possible results that each need redirection to appropriate scripts with completely different environments, then how should this best be done?

I hoped for a simple PHP statement that would accomplish this, however, perhaps there isn't one.
Ok. And how about giving the menu scripts names ending in name.menu.php and then ..

<Files *.php>
        Require all denied
        Require local
</Files>

<Files index.php>
        Require all granted
</Files>

<Files *.menu.php>
        Require all granted
</Files>

Open in new window


Does this make sense?
completely different environments
What does that mean?
I use generic scripts at the top of each parent script that calls a group of several other scripts and include scripts.
The 'appropriate scripts' use includes with the following ..

SELECTing and/or UPDATEing specific DB tables required for the includes
Cookie setting, session regenerating
Mail autoloader
Functions common to those specific scripts
Specific timeouts
Standard messages
Checking user levels for this group
Specific menus dependent on these user levels

.. followed by logic, DB table functions and includes and logic that leads to other script 'environments' (as above).

The way I've handled redirecting to each of the other parent groups from within the parent script is ..

    $url = BASE_URL."/path/script1.php";
    ob_end_clean();
    header("Location: $url");
    exit();

Open in new window

Thanks guys!
You're welcome!

Good luck!

Also, you're correct about your menu items, just add each of these files as an exception.