=======================================
PHP BASIC OPEN_BASEDIR CONCEPT
=======================================
Files and media can be protected by storing them outside of the document root so
that there is no direct access to them. A script could then be used to validate a
request and decide to serve it or not.
We can extend this feature and move ALL files outside of the htdocs directory.
The htdocs directory would be keep to a bare minimum.
/path/to/site/
|
|_ htdocs/
| |_ .htaccess
| |_ index.php
|
|_ base/
|_ about.php
|_ error.php
|_ index.php
|_ test.php
|
|_ public/
| |
| |_ css/
| | |_ bootstrap.min.css
| | |_ site.min.css
| |
| |_ js/
| | |_ bootstrap.min.js
| | |_ jquery.min.js
| | |_ site.min.js
| |
| |_images/
| |_batman.jpg
|
|_ private/
|
|_ images/
|_ batman.jpg
All urls will have no suffixes to hide the language that is used and all urls
with get vars will be simplified. For example these pretty urls would be valid
https://www.site.foo
https://www.site.foo/
https://www.site.foo/file
https://www.site.foo/file/var0/var1/var2/var3
and these urls would generate error 404
https://www.site.foo/index
https://www.site.foo/index.php
https://www.site.foo/file.php
This example uses jquery and bootstrap to demonstrate how files can be installed
and served up from outside of the document root.
https://code.jquery.com/jquery-3.7.0.min.js
https://github.com/twbs/bootstrap/releases/download/v4.6.2/bootstrap-4.6.2-dist.zip
=======================================
apache www.site.foo.conf
---------------------------------------
Add open_basedir directive to the apache site configuration .conf file.
DocumentRoot "/path/to/site/htdocs"
Options -Indexes
php_admin_value open_basedir "/path/to/site/"
=======================================
.htaccess
---------------------------------------
RewriteEngine on
# custom error page
ErrorDocument 400 /error
ErrorDocument 401 /error
ErrorDocument 403 /error
ErrorDocument 404 /error
ErrorDocument 405 /error
ErrorDocument 406 /error
ErrorDocument 407 /error
ErrorDocument 408 /error
ErrorDocument 409 /error
ErrorDocument 410 /error
ErrorDocument 411 /error
ErrorDocument 412 /error
ErrorDocument 413 /error
ErrorDocument 414 /error
ErrorDocument 415 /error
ErrorDocument 416 /error
ErrorDocument 417 /error
ErrorDocument 421 /error
ErrorDocument 422 /error
ErrorDocument 423 /error
ErrorDocument 424 /error
ErrorDocument 426 /error
ErrorDocument 429 /error
ErrorDocument 431 /error
ErrorDocument 451 /error
ErrorDocument 500 /error
ErrorDocument 501 /error
ErrorDocument 502 /error
ErrorDocument 503 /error
ErrorDocument 504 /error
ErrorDocument 505 /error
ErrorDocument 506 /error
ErrorDocument 507 /error
ErrorDocument 508 /error
ErrorDocument 510 /error
ErrorDocument 511 /error
# pass everything to index.php
RewriteRule ^/*$ index.php?uri=%{REQUEST_URI} [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1 [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1&v0=$2 [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1&v0=$2&v1=$3 [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/([^/]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1&v0=$2&v1=$3&v2=$4 [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1&v0=$2&v1=$3&v2=$4&v3=$5 [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1&v0=$2&v1=$3&v2=$4&v3=$5&v4=$6 [NC,END]
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/*$ index.php?uri=%{REQUEST_URI}&file=$1&v0=$2&v1=$3&v2=$4&v3=$5&v4=$6&v5=$7 [NC,END]
=======================================
/path/to/site/htdocs/index.php
---------------------------------------
=======================================
/path/to/site/base/inc_ini.php
---------------------------------------
=======================================
/path/to/site/base/inc_inc.php
---------------------------------------
=======================================
/path/to/site/base/inc_nav.php
---------------------------------------
=======================================
/path/to/site/base/error.php
---------------------------------------
'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Reserved',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Payload Too Large',
414 => 'URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a teapot',
421 => 'Misdirected Request',
422 => 'Unprecessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
425 => 'Too Early',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
451 => 'Unavailable For Legal Reasons',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
508 => 'Loop Detected',
510 => 'Not Extended',
511 => 'Network Authentication Required'
);
if(isset($_SERVER['REDIRECT_STATUS']) && !empty($_SERVER['REDIRECT_STATUS']) && is_numeric($_SERVER['REDIRECT_STATUS']) && $_SERVER['REDIRECT_STATUS'] != 200 && array_key_exists($_SERVER['REDIRECT_STATUS'], $status)) {
$err['code'] = $_SERVER['REDIRECT_STATUS'];
$err['text'] = $status[$_SERVER['REDIRECT_STATUS']];
} else {
$err['code'] = 404;
$err['text'] = 'Not Found';
}
?>
');
print('name: /path/to/site/'.basename($_SERVER['SCRIPT_FILENAME']).'
');
print('file: /path/to/site/'.basename(__FILE__).'
');
if(isset($_GET) && !empty($_GET)) {
print('
'.'GET:'.'
');
foreach($_GET as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
if(isset($_POST) && !empty($_POST)) {
print('
'.'POST:'.'
');
foreach($_POST as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
?>
'.$_SERVER['REQUEST_URI'].'');
print('
'.$err['code'].' '.$err['text'].'');
if(isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER'])) {
print('referrer: '.$_SERVER['HTTP_REFERER'].'
');
}
print(''.date('Y-m-d H:i:s T').'');
if(isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'])) {
print(''.$_SERVER['REMOTE_ADDR'].' : '.$_SERVER['REMOTE_PORT'].'');
}
print(''.$_SERVER['HTTP_USER_AGENT'].'');
?>
=======================================
/path/to/site/base/index.php
---------------------------------------
open_basedir
');
print('name: /path/to/site/'.basename(dirname($_SERVER['SCRIPT_FILENAME'])).'/'.basename($_SERVER['SCRIPT_FILENAME']).'
');
print('file: /path/to/site/'.basename(dirname(__FILE__)).'/'.basename(__FILE__).'
');
if(isset($_GET) && !empty($_GET)) {
print('
'.'GET:'.'
');
foreach($_GET as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
if(isset($_POST) && !empty($_POST)) {
print('
'.'POST:'.'
');
foreach($_POST as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
?>
=======================================
/path/to/site/base/test.php
---------------------------------------
open_basedir
');
print('name: /path/to/site/'.basename(dirname($_SERVER['SCRIPT_FILENAME'])).'/'.basename($_SERVER['SCRIPT_FILENAME']).'
');
print('file: /path/to/site/'.basename(dirname(__FILE__)).'/'.basename(__FILE__).'
');
if(isset($_GET) && !empty($_GET)) {
print('
'.'GET:'.'
');
foreach($_GET as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
if(isset($_POST) && !empty($_POST)) {
print('
'.'POST:'.'
');
foreach($_POST as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
?>
Public Image
Accessible for PUBLIC viewing
<img src="/public/image/batman.jpg">
Private Image
Accessible for PRIVATE viewing
<img src="/private/image/batman.jpg">
=======================================
/path/to/site/base/about.php
---------------------------------------
open_basedir
');
print('name: /path/to/site/'.basename(dirname($_SERVER['SCRIPT_FILENAME'])).'/'.basename($_SERVER['SCRIPT_FILENAME']).'
');
print('file: /path/to/site/'.basename(dirname(__FILE__)).'/'.basename(__FILE__).'
');
if(isset($_GET) && !empty($_GET)) {
print('
'.'GET:'.'
');
foreach($_GET as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
if(isset($_POST) && !empty($_POST)) {
print('
'.'POST:'.'
');
foreach($_POST as $key => $val) {
print('['.$key.'] => '.$val.'
');
}
}
?>
=======================================
/path/to/site/base/public.php
---------------------------------------
$val) {
if($key != 'uri' && $key != 'file' && $val != '.' && $val != '..') {
$file_test .= '/'.$val;
}
}
$file = BASE.'/'.$file_test;
if(is_file($file)) {
header('Content-Disposition: inline; filename="'.basename($file).'"');
$ext = pathinfo($file, PATHINFO_EXTENSION);
if($ext == 'css') {
header('Content-type: text/css');
} elseif($ext == 'js') {
header('Content-type: text/javascript');
} elseif($ext == 'txt') {
header('Content-type: text/plain');
} elseif($ext == 'jpg') {
header('Content-type: image/jpg');
} elseif($ext == 'png') {
header('Content-type: image/png');
} else {
$finfo = finfo_open(FILEINFO_MIME);
$mime = explode(';', finfo_file($finfo, $file))[0];
header('Content-Type: '.$mime);
header('Connection: Keep-Alive');
header('Keep-Alive: timeout=5 max=100');
header('Accept-Ranges: bytes');
}
header('Content-Length:'.filesize($file));
readfile($file);
} else {
$_SERVER['REDIRECT_STATUS'] = 404;
$file = BASE.'/error.php';
require_once($file);
}
?>
=======================================
/path/to/site/base/private.php
---------------------------------------
$val) {
if($key != 'uri' && $key != 'file' && $val != '.' && $val != '..') {
$file_test .= '/'.$val;
}
}
$file = BASE.'/'.$file_test;
if(is_file($file) && isset($ok)) {
header('Content-Disposition: inline; filename="'.basename($file).'"');
$ext = pathinfo($file, PATHINFO_EXTENSION);
if($ext == 'css') {
header('Content-type: text/css');
} elseif($ext == 'js') {
header('Content-type: text/javascript');
} elseif($ext == 'txt') {
header('Content-type: text/plain');
} elseif($ext == 'jpg') {
header('Content-type: image/jpg');
} elseif($ext == 'png') {
header('Content-type: image/png');
} else {
$finfo = finfo_open(FILEINFO_MIME);
$mime = explode(';', finfo_file($finfo, $file))[0];
header('Content-Type: '.$mime);
header('Connection: Keep-Alive');
header('Keep-Alive: timeout=5 max=100');
header('Accept-Ranges: bytes');
}
header('Content-Length:'.filesize($file));
readfile($file);
} else {
$_SERVER['REDIRECT_STATUS'] = 404;
$file = BASE.'/error.php';
require_once($file);
}
?>
=======================================
demo site
---------------------------------------
https://base.oetec.com
=======================================
:0)
=======================================