I am learning PHP and Apache configurations, i am using XAMPP Version: 5.6.19. I have a page named default.php, this page will load a header, a footer and a content subpage between them, this content subpage will be saved on a folder named "content". So to load the site showing the content subpage i would write:
localhost/misite/default.php?page=subpage
to do so i have coded the default.php the following way:
<!--INCLUDE HEADER-->
<?php include 'includes/header.php';?>
<!--LOAD CONTET-->
<?php
/*if page is not set, redirect to index*/
if(!isset($_GET['page']) || strlen($_GET['page']) == 0)
{
header("Location: index.php");
die();
}
/*if page is set*/
else
{
/*search page on contet directory*/
$page = 'content/'.$_GET['page'].'.php';
/*if page not found on content directory, redirect to index*/
if(!glob($page))
{
header("Location: index.php");
die();
}
/*if page is found, load as subpage*/
else
{
?>
<main class = "<?php echo basename($page, '.php'); ?>">
<?php include $page;?>
</main>
<?php
}
}
?>
<!--INCLUDE FOOTER-->
<?php include 'includes/footer.php';?>
I coded it this way in order to only allow load of php files of content folder and most important to prevent access from there to another folder by doing the ../ trick, so if someone try that the result would be:
default?page=../.php
and that will produce a redirect to index page instead.
The problem emerged when i tried to have the same functionality with SEF URL's. I coded the following on the .htaccess:
RewriteEngine On
RewriteBase /misite/
RewriteRule ^([a-zA-Z0-9-]*)$ default.php?page=$1
So i could be able to write
localhost/misite/subpage
So i was expecting the same result as the parameter $1 would be now the value for the "page" parameter on default.php and expected that everything else would be exaclty the same, so i didn't expect to be able to access another folder. But when i tried the following:
localhost/../
As result i got to the dashboard page (localhost/dashboard/) which is a page located outside of mi site folder, and if i try
localhost/..img/ i can access the img folder and so on. It looks like it is not even executing my default.php conditional validations.
I am worried if this could be a security issue and worried if i could get hacked by this. And i don't know why this happens. In case this is a security issue, how can i fix it?
The security risk is with this line:
$page = 'content/'.$_GET['page'].'.php';
Without checking, you're allowing any input to search your disk with the subsequent call to glob. Relative paths will be evaluated, letting the user reference any PHP file on your server.
If all of your PHP files are within 'content' and not in deeper directories, one solution is
// Check "page" only contains letters, numbers, underscore
if (!preg_match('/^\w+$/', $_GET['page'])) {
header("HTTP/1.0 404 Not Found");
exit();
}
$page = 'content/'.$_GET['page'].'.php';
Then you can be confident the path in $page is only referencing a PHP file in your content directory.
Related
I am trying to reference a file from a subdirectory of my root folder in a way that only the "main" changes.
I have this pice of code in my home.php file:
<div id="main" class="main">
<?php require $_GET['main'] . ".php"; ?>
</div>
All the navigation buttons should change the "main" to certain files in various folders under the folder which contains home.php.
The below code snippet works perfectly if the file I am referencing is in the same folder as my working file:
Dashboard 1
What I want to do is (I imagine) like this:
Dashboard 1
where the file I am referencing is in a different folder.
Also, if I reference the file in question with
Dashboard 1
the file loads, but it does not target the "main" like it should with ?main=
I tried myriad ways that I read about / though would work, but nothing did so far. Any help would be much appreciated.
Don't require files from user input without validation!
<?php
// For Security a list of granted paths.
$allowedPaths = [
'folder/dashboard.php',
];
$main = isset($_GET['main']) ? $_GET['main'] : '';
if(!in_array($main, $allowedPaths) {
// Error handling
die('Path not allowed');
}
require $main;
?>
The link could look like
<a href="?main=folder%2Fdashboard.php">
Note, that the URL values must be encoded -> echo urlencode('folder/dashboard.php'); to make the slash valid.
Note to not add .php extension twice (once in URL and again in code).
Hi guys i m building a website in php i created my first 3 page
-header
-index
-footer
in index.php i use:
<?php include("header.php"); ?>
<?php include("footer.php"); ?>
My question is:
if i go to my url http://localhost:8888/project/index.php
every its'ok
but if i write http://localhost:8888/project/header.php or footer
How i can not display the content it s in this two pages?
Because if i m using a redirect i have a blank page in index.php because the index.php include header and footer
Thanks a lot
Define a constant in your scripts before including header or footer:
index.php:
define('MY_CONSTANT', 1);
include 'header.php';
//
include 'footer.php';
Then, in header.php and footer.php check if constant is not defined:
if(!defined('MY_CONSTANT')) {
// You can show a message
die('Access not allowed!');
// Or send user to index.php, first delete above line (die)
header('Location:index.php');
exit; // This line is needed to stop script execution
}
// rest of header and footer code
go to your footer and header scripts, and make then a variable, for example:
$header = "<!doctype html><html><head>#head Content</head>";
and replace every qoutes with \" (look at the div class in $footer)
$footer = "<footer><div class=\"class\">#footer Content</div></footer></html>";
then in the index.php make it echo the variables
<?php
require_once("header.php");
require_once("footer.php");
echo $header;
echo $body;
echo $footer;
?>
then you can add this code to make it look like the file doesn't exist
<?php
header('HTTP/1.0 404 Not Found');
readfile('www.link.to/error-page/404');
exit();
?>
Note: it's all up to you how you make your website, but this is the method I use, and it works fine.
extra:
you can make your $body like this
let's say you have a folder call scripts, you create a file called pager.php
and you add the code
<?php
$dir = $_SERVER['PATH_INFO'];
if(empty($dir)) {
require_once("templates/mainpage.php");
} elseif ($dir == "page2") {
require_once("templates/page2.php");
} else {
require_once("templates/pages-doesnt-exist.php");
}
?>
remember to make a folder called "templates" and add all your pages in there,
then you'll be able to access all page from http://example.com/index.php/{pagename}
you can also add this code to your .htaccess
RewriteEngine On
RewriteRule ^page2$ /index.php/page2 [L] --page wise condition
so http://example.com/page2 will access http://example.com/index.php/page2
Compare $_SERVER['REQUEST_URI'] to make sure the requested page/file is neither header.php nor footer.php
I am trying to include a specific css file depending on the URL provided by the browser.
My website has the following format:
Header information
php include for content
Footer information
I am doing this so when I change my header menu links, I don't have to change every page on the website.
The php include code is as follows:
<?php
$page = $_GET['page'];
$pages = array('main', 'contact');
if (!empty($page)) {
if(in_array($page,$pages)) {
$page .= '.php';
include($page);
}
else {
include('404.php');
}
}
else {
include('main.php');
}
?>
The URL is made up as follows
index.php?page= for example index.php?page=contact
As part of the php include code, when the page=???? element isn't within the array it loads page 404.php which is an error page.
As can be seen, the array currently contains two pages, main (the home page content) and contact (the contact form). If a user tries to load a page called test (index.php?page=test) my webpage will display the 404 page (however doesn't load index.php?page=404 - the URL in browser stays as index.php?page=test.
What I'm trying to achieve is to load 404.css file when page=test(or any other page name not included in the array) is loaded.
Does anyone know how i'd go about achieving this? I've tried writing an if statement in the header to load 404.css however I was using strstr that fetches the browser URL (so test, not 404), therefore the correct css file doesn't get loaded.
Any help is much appreciated (or a better way to achieve what i'm trying to do).
Thanks in advance
Iain
An easy way of doing this is to make use of the ob_* php functions like bellow:
PHP get all the information from within the ob_start and the ob_get_clean functions and concatenate them all together as a single variable $_page_content, that variable can be used anywhere you need.
<?php
$page = $_GET['page'];
$pages = array('main', 'contact');
if (!empty($page))
{
if(in_array($page, $pages))
{
ob_start('ob_gzhandler');
?>
<link rel="stylesheet" href="css/<?=$page?>.css" type="text/css">
<?
include($page . '.php');
$_page_content = ob_get_clean();
echo $_page_content;
}
else
{
include('404.php');
}
}
else
{
include('main.php');
}
?>
I have searched all over the web trying to figure this out and am now trying to get a direct answer from some experienced users. I hope I can explain myself completely.
I know HTML and CSS and some PHP and Javascript, but no mean an expert. This is my questions:
When creating a website by hand (no Drupal, or Wordpress or predesigned templates), The first thing I do is create an index.php file that shows my HTML page layout. The second thing I do is create my links.inc.php file that will show all the links to my pages, ex: Home, About Us, Contact Us. Now on the index.php page I create php include files for the header, footer, and link pages. (these would read header.inc.php, footer.inc.php, links.inc.php) Now here is where I am trying to figure if there is an easier way to do the next step.
My normal steps would next to be to create a home.inc.php, aboutus.inc.php, contactus.inc.php files which will have all the "content" I want shown for each page.
I would then create a duplicate of the index.php and create aboutus.php where I would use the php include function to add the aboutus.inc.php into the "main content" area I would want this information displayed at. Then I would create anther duplicate of the index.php and name it contactus.php and "include" the contactus.inc.php file.
Is there any way to use the index.php file and have all the inc.php files on that page? For instance,
<div id="main">
<?php
include ("home.inc.php");
include ("aboutus.inc.php");
include ("contactus.inc.php")
?>
</div>
Obviously this does not work they way I have it laid out above, it shows all the pages at the same time instead of only showing the one page that is clicked on from the menu. Any suggestions? Is there a different way or am I doing it correctly with creating multiple pages?
Thank you for any help and I hope I was clear, if not I can try to explain a different way.
My suggestion is to include files conditionally, based on a variable that defines the current page.
For example, given the following navigation:
Home
About Us
Contact Us
Configure your index.php file to include external files, something like this:
// determine the requested page, default to the home page
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
// check if the requested include file exists
$include_file = is_file($page.'.inc.php') ? $page.'.inc.php' : false;
// if the requested include file exists, include it
if ($include_file) {
include $include_file;
}
Feel free to adjust the logic. For example, if a $page value is not recognized as a valid page on your site, you may want to show a 404 page, default to the "home" page, etc.
Edit
If your include files are in a different directory, you'll need to provide the correct path:
// define the path to includes
$path = 'inc/';
// check if the requested include file exists
$include_file = is_file($path.$page.'.inc.php') ? $path.$page.'.inc.php' : false;
You could send a variable to PHP index.php?action=home; then, inside index make some verifications
if($action=="home") {include index.inc.php; }
else if ($action=="contact") {include contact.inc.php }
and so on.
So I'm trying to make a theme from my Html file. And using require('file.php') where file.php is a series of different components of my theme. Now when I access the file directly, I still see the html. How do I make it display a blank page when user accesses the file.php directly?
Explanation
So let's say I make index.php and I want to include the header file(header.php)
When I require('header.php'), everything works perfect. Now when I try to access the header.php, I can see the html content of it. How to I make this appear blank instead of seeing the header.php piece?
Thanks
In that case, If you want to execute header.php inside the index.php or etc. You need to add or define a flag in parent files (wherever you want header.php to be executed or simply adding in to the common file which is called in all parent files), In header.php file you need check the defined flag is set or has some value. If it is not set, then stop execution by using die(); function.
In index.php,
<?php $HeaderAllow ='1'; ?>
In header file,
<?php
if($HeaderAllow=='' or !isset($HeaderAllow)){
die();
}
?>
you can use $_SERVER['SCRIPT_FILENAME'] here to check and then make page blank in header.php.
<?php
if($_SERVER['SCRIPT_FILENAME'] == 'header.php') {
exit();
}
Putting the include files in a seperate folder and protectinng with .htaccess is good idea.
Same issue here.
deny direct access to a folder and file by htaccess
The easiest way is to put your includes in a directory and deny access to that directory in your .htaccess file