How do i Prevent remote file inclusion attack from php? - php

This is my code in index.php
include ($_GET['page']);
Actully i need to include page from url like
"?page=go.php"
on the other-hand i can not filter
"?page=example.com"
as for some case i need to include this value also. But this is a remote file inclusion (RFI) vulnerability. how can i prevent RFI attack from my site?
I am doing something like
$filename = $_GET['page'];
if (file_exists($filename)) {
{
include ($_GET['page']);
}
But it filters only
"?page=go.php"
this shorts of page.
And i am sucked with
"?page=example.com"
this shorts of page.

If I understand the question correctly; You could setup an array with 'allowed' pages such as:
$allowedPages = array('go.php', 'stop.php', 'file.php');
$filename = $_GET['page'];
if(in_array($filename, $allowedPages) && file_exists($filename)){
include ($filename);
}else{
//output error
}

I think this answer is too late, but for those who might search for this problem, I guess it can be done like this, too:
1.Define a constant with full path.
2.Define a white-list of allowed pages.
3.Get the $_GET variable, and convert it to lower case.
4.Then if the page returned by $_GET variable is in your white-list array, then require it, otherwise, redirect the user to the home page, and display an error message.
<?php
# this is abcd.php
define('SITE','http://www.yoursite.com/');
$allow = [SITE.'1.php', SITE.'2.php', SITE.'3.php'];
$get = strtolower(SITE.$_GET['page']);
if(in_array($get,$allow)){
include $get;
} else {
header('Location: index.php?param=incorrect');
}
?>
<?php
# this is index.php
if(isset($_GET['param']) && $_GET['param'] == 'incorrect'){
?>
<script type="text/javascript">
alert("INCORRECT PARAMETER PROVIDED");
</script>
<?php
} else die('ERROR');
I'm not 100% sure this will work without any probs, but I guess is a good start and you can play around with it and figure out what's suitable for you.

To be honest, your method of creating a dynamic website is definitely not the way to go.
To answer within the scope of this question, you'd do something like the following:
You'd have to set up a whitelist of files that are**ALLOWED** to be included through this function.
That could look something like this:
<?php
$whitelist = array(
'file1.php',
'file2.php',
'file3.php',
'file4.php',
'file5.php',
);
?>
Now before including the said file, you'd run a check with in_array()
<?php
if(in_array($_GET['page'] . '.php', $whitelist) && file_exists($_GET['page'] . '.php')) {
include($_GET['page'] . '.php');
}
?>
This, as you can see is not very pretty!
Another alternative would be doing something like:
<?php
$file = strtolower($_GET['page']) . '.php';
if(isset($whitelist[$file]) && file_exists($file)) {
include($_GET['page'] . '.php');
}
?>

Don't accept a page.php parameter, but just the name of the file.
"?page=go"
Then check if $_REQUEST["page"] is alphanumeric
if (ctype_alnum($_REQUEST["page"]))
And just don't give non-alpha-numeric names to your files.
Then do if file_exists on $_REQUEST["page"] and you should be quite good.
PS
$_REQUEST["page"] is about the same with $_GET["page"], it just intersects with $_POST

You can filter other domain urls instead of filtering files.
If parameter contains a hostname less than 3 letters, it is fine as no domain is 2 letters.
$tmp= parse_url ($_GET['page']);
if(strlen($tmp['host'])<3)
include($_GET['page']);
If there are some trusted hosts then you can validate them too.

Related

php variable to include

I am wondering what is the best option to use variables in an included file who are declared in his parent file.
When I want to check privileges in an included file because I do not want to copy the whole function to any file I want to check the privileges.
I tried a few ways. Which is the best, or should I do it another way?
just include:
<?php
// head file
$userlevel = 2;
$minimumlevel
include('testprivileges.php');
?>
<?php
// testprivileges file
if ($userlevel < $minimumlevel){
die('no privileges');
}
or
<?php
//head file
$userlevel;
$minimumlevel
include('checkprivileges.php?userlevel=$userlevel&minimumlevel=$minimumlevel');
// i dont care this wont work. you understand what I try to do
?>
<?php
$userlevel = $_GET['userlevel'];
// and check for privileges
?>
or
<?php
// testprivileges function file
function testprivileges($userlevel, $minimumlevel){
if($userlevel < $minimumlevel){
die('no privileges');
}
}
?>
<?php
//head file
$userlevel = 2;
$minimumlevel = 3;
include('testprivilegesfile.php');
testpriviles($userlevel, $minimumlevel);
?>
or are all of those options bad?
Your first code works, and its the best practice.
Your second example is bad because this:
include('checkprivileges.php?userlevel=$userlevel&minimumlevel=$minimumlevel');
cant work.
Your last code is also a bad practice because you have to copy paste the same function to every file. Not only is that duplication of code, but also hard to manage.
Like I said, the first code works best.
Some notes though:
$userlevel Should come from high above. You shouldn't have to re-declare it in every file. Just set it once in a global config.php.
$minimumlevel = minimum level for current page?
Ideal code:
<?php
$minimumlevel = 1;
require_once ('includes/config.php'); // Contains $userlevel
Checkrights($minimumlevel);
?>
functions.php
function Checkrights($minimumlevel){
global $userlevel;
if ($userlevel < $minimumlevel){
die('no privileges');
}
}
config.php
require_once ('functions.php');
$userlevel = 2;
Bitwise permission system
If you are really into a better permission system you might want to hit this tutorial about the bitwise permission system. I use it myself and its VERY simply. If you create a new table in SQL containing some permissions, you can give privileges PER module per sé. Highly recommended.
http://www.php4every1.com/tutorials/create-permissions-using-bitwise-operators-in-php/
Simply just include in the beginning of the file if you will use it.
<?php
include("testprivileges.php");
//use to check privilege
?>

Show diffrent content if there is a warning message

I have a little problem with a PHP warning:
I basically want to change the content of my page by clicking on links, like this:
<?php $page = ((!empty($_GET['page'])) ? $_GET['page'] : 'home'); ?>
<h1>Pages:</h1>
<ul>
<li>News</li>
<li>F.A.Q.</li>
<li>Contact</li>
</ul>
<?php include("$page.html");?>
This works really fine, but when I use a page that doesn't exist, for example
localhost/dir/index.php?page=notapage i get following error:
Warning: include(notapage.html): failed to open stream: No such file or directory in
C:\xampp\htdocs\dir\index.php on line 8
Warning: include(): Failed opening 'notapage.html' for inclusion (include_path='.;C:\xampp\php\PEAR') in C:\xampp\htdocs\dir\index.php on line 8
Is it possible to replace this warning by a custom message? (like a "404 not found")
Thanks in advance and happy easter!
You could use file_exists() but keep in mind that your approach is not very safe.
A safer approach would be using an array with allowed pages. This way you have a better control over user input. Something like this:
$pages = array(
'news' => 'News',
'faq' => 'F.A.Q.',
'contact' => 'Contact'
);
if (!empty($pages[$_GET['page']])) {
include($_GET['page'].'html');
} else {
include('error404.html');
}
You could also generate the menu using that array.
You can do
if (file_exists($page.html)) {
include("$page.html");
}
else
{
echo "404 Message";
}
Source: PHP Manual
You can check if the file exists() and then include a custom 404 template.
<?php
if (file_exists($page + '.html')) {
include ($page + '.html')
} else {
include ('404.html');
}
?>
The idea is to check if the file exists before trying to include() it:
if(!file_exists("$page.html"))
{
display_error404();
exit;
}
include("$page.html");
Yes it is possible, though I would recommend sending a 404 unless you are going to also use clean url's (like /news, /faq, /contact) that redirect behind the scenes to the index.php, writing the page parameter. This is because index.php really does exist, you just have a bad parameter. Thus a 404 would not be appropriate. This is not to mention that you actually can;t set a 404 header in this location anyway since you have already sent output to the browser.
For you case just set up a conditional on whether the file_exists and is readable like this:
$include_file = $page . '.html';
if (file_exists($include_file) && is_readable($include_file)) {
include($include_file);
} else {
// show error message
}

Using PHP to identify current page

I have a series of PHP page, and I would like to use conditional logic to apply different rules to each page. Im not sure if my method is the best way to go about it, so I wanted to see if the community had any recommendations, as this doesn't feel like the best approach. Code Below:
<?php
$nameurl = $_SERVER["REQUEST_URI"];
if ($nameurl == "/fs/about.php"){
echo "about page";
}
elseif ($nameurl == "/fs/index.php"){
echo "home page";
}
?>
Ideally, I would like to only use the filename (index.php or about.php) instead of having /fs/. Im not sure if there is another way of using $_SERVER with PHP but it seems like there might be a more efficient and reusable way of writing this. Thoughts?
You could use
// get script name
$script = explode('/', $_SERVER['PHP_SELF']);
$scriptname = $script[count($script) - 1];
switch ($scriptname) {
case "index.php":
// Something you only want to show on this page
break;
case "about.php":
// Something you only want to show on this page
break;
}
To save a couple of lines of code, you could replace the multiple ifs with a switch:
http://php.net/manual/en/control-structures.switch.php
$nameurl = $_SERVER["REQUEST_URI"];
switch ($nameurl) {
case "/fs/about.php":
echo "about page";
break;
case "/fs/index.php":
echo "home page";
break;
default:
echo "unknown page";
break;
}
Makes it a little easier to add new cases in the future, but it's essentially doing the same thing...
There might be ways to make it more optimized, but I think if you start doing too much you lose the ability to easily understand what's happening in the code, so unless you comment what you're doing future people looking at your work will curse you. :P
Try this
$nameurl = basename($_SERVER['REQUEST_URI'], '.php');
echo $nameurl, " page";
http://php.net/manual/en/function.basename.php
You could try :
$currentFile = $_SERVER["PHP_SELF"];
$current_filename = explode('/', $currentFile);
or
$current_filename = basename($_SERVER['REQUEST_URI']) .'php';

php , read file code problem

I was using this piece of php code for a site.
Now its old and I recently had a few attacks. Script was used for to include another file from someplace else and send spam. Obviously this makes my script as spam sender.
for the content
$htm = ".htm";
$pid = "$details$htm";
function show_details($pid)
{
if (!preg_match("/http/", $pid)) {
require($pid);
} else {
die;
}
}
and for the title, desc , keywords etc..
$txt = ".txt";
$title = "$details$txt";
function show_title($title)
{
if (!preg_match("/http/", $title)) {
if (file_exists($title)) {
require($title);
} else {
die;
}
}
}
and a display.php file with
print '
<!-- CONTENT -->
';
show_details("$pid");
print '
by this code ı was able to call any content by "/display.php?details=mycontentpage"
mycontentpage.htm
mycontentpage.txt
.............
Now this code has to be re-coded .. I can not change the construction as the site is just too big.
So I guess I just have to stick to this..
Can anyone help ? Any comments ?
To make scripts like this more secure, you have to ensure register_globals is set to OFF. This means you'll have to add a line like:
php_flag register_globals off
...To .htaccess. Then, declare all your user variables the first time you use them like:
$details = $_GET['details']
...Which assigns the data from the URI piece "details" to the PHP variable $details.
I can very much see how your attackers were able to get in via your code and register_globals set to on -- they'd need to merely create a .htm file with PHP code in it that reassigns other variables, include it, then viola.
For more info, see:
http://us2.php.net/manual/en/security.globals.php
Hope this helps!

PHP - include a php file and also send query parameters

I have to show a page from my php script based on certain conditions. I have an if condition and am doing an "include" if the condition is satisfied.
if(condition here){
include "myFile.php?id='$someVar'";
}
Now the problem is the server has a file "myFile.php" but I want to make a call to this file with an argument (id) and the value of "id" will change with each call.
Can someone please tell me how to achieve this?
Thanks.
Imagine the include as what it is: A copy & paste of the contents of the included PHP file which will then be interpreted. There is no scope change at all, so you can still access $someVar in the included file directly (even though you might consider a class based structure where you pass $someVar as a parameter or refer to a few global variables).
You could do something like this to achieve the effect you are after:
$_GET['id']=$somevar;
include('myFile.php');
However, it sounds like you are using this include like some kind of function call (you mention calling it repeatedly with different arguments).
In this case, why not turn it into a regular function, included once and called multiple times?
An include is just like a code insertion. You get in your included code the exact same variables you have in your base code. So you can do this in your main file :
<?
if ($condition == true)
{
$id = 12345;
include 'myFile.php';
}
?>
And in "myFile.php" :
<?
echo 'My id is : ' . $id . '!';
?>
This will output :
My id is 12345 !
If you are going to write this include manually in the PHP file - the answer of Daff is perfect.
Anyway, if you need to do what was the initial question, here is a small simple function to achieve that:
<?php
// Include php file from string with GET parameters
function include_get($phpinclude)
{
// find ? if available
$pos_incl = strpos($phpinclude, '?');
if ($pos_incl !== FALSE)
{
// divide the string in two part, before ? and after
// after ? - the query string
$qry_string = substr($phpinclude, $pos_incl+1);
// before ? - the real name of the file to be included
$phpinclude = substr($phpinclude, 0, $pos_incl);
// transform to array with & as divisor
$arr_qstr = explode('&',$qry_string);
// in $arr_qstr you should have a result like this:
// ('id=123', 'active=no', ...)
foreach ($arr_qstr as $param_value) {
// for each element in above array, split to variable name and its value
list($qstr_name, $qstr_value) = explode('=', $param_value);
// $qstr_name will hold the name of the variable we need - 'id', 'active', ...
// $qstr_value - the corresponding value
// $$qstr_name - this construction creates variable variable
// this means from variable $qstr_name = 'id', adding another $ sign in front you will receive variable $id
// the second iteration will give you variable $active and so on
$$qstr_name = $qstr_value;
}
}
// now it's time to include the real php file
// all necessary variables are already defined and will be in the same scope of included file
include($phpinclude);
}
?>
I'm using this variable variable construction very often.
The simplest way to do this is like this
index.php
<?php $active = 'home'; include 'second.php'; ?>
second.php
<?php echo $active; ?>
You can share variables since you are including 2 files by using "include"
In the file you include, wrap the html in a function.
<?php function($myVar) {?>
<div>
<?php echo $myVar; ?>
</div>
<?php } ?>
In the file where you want it to be included, include the file and then call the function with the parameters you want.
I know this has been a while, however, Iam wondering whether the best way to handle this would be to utilize the be session variable(s)
In your myFile.php you'd have
<?php
$MySomeVAR = $_SESSION['SomeVar'];
?>
And in the calling file
<?php
session_start();
$_SESSION['SomeVar'] = $SomeVAR;
include('myFile.php');
echo $MySomeVAR;
?>
Would this circumvent the "suggested" need to Functionize the whole process?
I have ran into this when doing ajax forms where I include multiple field sets. Taking for example an employment application. I start out with one professional reference set and I have a button that says "Add More". This does an ajax call with a $count parameter to include the input set again (name, contact, phone.. etc) This works fine on first page call as I do something like:
<?php
include('references.php');`
?>
User presses a button that makes an ajax call ajax('references.php?count=1'); Then inside the references.php file I have something like:
<?php
$count = isset($_GET['count']) ? $_GET['count'] : 0;
?>
I also have other dynamic includes like this throughout the site that pass parameters. The problem happens when the user presses submit and there is a form error. So now to not duplicate code to include those extra field sets that where dynamically included, i created a function that will setup the include with the appropriate GET params.
<?php
function include_get_params($file) {
$parts = explode('?', $file);
if (isset($parts[1])) {
parse_str($parts[1], $output);
foreach ($output as $key => $value) {
$_GET[$key] = $value;
}
}
include($parts[0]);
}
?>
The function checks for query params, and automatically adds them to the $_GET variable. This has worked pretty good for my use cases.
Here is an example on the form page when called:
<?php
// We check for a total of 12
for ($i=0; $i<12; $i++) {
if (isset($_POST['references_name_'.$i]) && !empty($_POST['references_name_'.$i])) {
include_get_params(DIR .'references.php?count='. $i);
} else {
break;
}
}
?>
Just another example of including GET params dynamically to accommodate certain use cases. Hope this helps. Please note this code isn't in its complete state but this should be enough to get anyone started pretty good for their use case.
You can use $GLOBALS to solve this issue as well.
$myvar = "Hey";
include ("test.php");
echo $GLOBALS["myvar"];
If anyone else is on this question, when using include('somepath.php'); and that file contains a function, the var must be declared there as well. The inclusion of $var=$var; won't always work. Try running these:
one.php:
<?php
$vars = array('stack','exchange','.com');
include('two.php'); /*----- "paste" contents of two.php */
testFunction(); /*----- execute imported function */
?>
two.php:
<?php
function testFunction(){
global $vars; /*----- vars declared inside func! */
echo $vars[0].$vars[1].$vars[2];
}
?>
Try this also
we can have a function inside the included file then we can call the function with parametrs.
our file for include is test.php
<?php
function testWithParams($param1, $param2, $moreParam = ''){
echo $param1;
}
then we can include the file and call the function with our parameters as a variables or directly
index.php
<?php
include('test.php');
$var1 = 'Hi how are you?';
$var2 = [1,2,3,4,5];
testWithParams($var1, $var2);
Your question is not very clear, but if you want to include the php file (add the source of that page to yours), you just have to do following :
if(condition){
$someVar=someValue;
include "myFile.php";
}
As long as the variable is named $someVar in the myFile.php
I was in the same situation and I needed to include a page by sending some parameters... But in reality what I wanted to do is to redirect the page... if is the case for you, the code is:
<?php
header("Location: http://localhost/planner/layout.php?page=dashboard");
exit();
?>

Categories