PHP Change Root path depending on localhost vs server - php

Using PHP, I would like to have a simple config.php file that enables me to check whether I am on localhost vs mydomain.com.
For example, on 'localhost':
$path = '/'
But when I upload to my server ('mydomain.com'), I'd like to have the path be:
$path = '/testing/
I'd like to be able to check whether I am developing locally vs when the site is uploaded to my ftp.

You can get your current running server using $_SERVER['SERVER_NAME']:
$default_path = ($_SERVER['SERVER_NAME'] == 'localhost') ? '/' : '/testing/';
There are plenty of other variables in the $_SERVER superglobal array, if you want to use another one you should debug it and find whichever one you want (I'm on Amazon servers and I've got tons of Amazon specific variables to choose from too):
echo '<pre>'; print_r($_SERVER); exit;
SERVER_NAME is more reliable than others like HTTP_HOST, see this article for details.

You could probably check using $_SERVER['REMOTE_ADDR']. On localhost, this would return 127.0.0.1:
if ($_SERVER['REMOTE_ADDR'] === '127.0.0.1') {
$path = '/';
} else {
$path = '/testing/;
}
It is not 100% reliable, but works for most cases.

I use to have this line in my config files for that purpose
$isLocal=($_SERVER['REMOTE_ADDR']=="127.0.0.1" );

Related

Exploiting file_get_contents() [duplicate]

This question already has an answer here:
Security vulnerabilities with file_get_contents() using variable location
(1 answer)
Closed 3 years ago.
Is it possible to read any file (not only those with the extension .html) from the server in the following script?
<?php
echo file_get_contents($_GET['display'].'.html');
?>
I know about wrappers (php://, file://, etc.) but achieved not too much.
I'm eager to hear all the possible vectors of attack.
The PHP configuration is default:
allow_url_fopen On, and let's assume the version is >= 7.0, so null character %00 doesn't work.
No, that will only ever read files ending in '.html', but that doesn't necessarily mean that it's secure! Generally, the more that you can sanitise and restrict the input, the better.
Also, for anyone planning to use file_get_contents like this, it's always good to remember that when serving from file_get_contents, you can serve files that are not normally accessible - either due to server configuration, e.g. .htaccess, or file permissions.
As #David said, this will only get files ending in '.html', but its not a good practice, if you have html folder and you want the user to get only files from that folder , you shouldn't do that, by using this method a hacker can access any .html file in your server, not just the ones you want him to see.
My suggestion is that if you have a specific folder that you want user to be able to get files from, scan the directory and check for the file name.
Here's an example:
<?php
$paths = scandir('/html');
$file = isset($_GET['display']) : $_GET['display'] ? null;
if(!$file)
{
die('no display provided');
}
$html = '';
foreach($paths as $path) {
if($path !== '.' && $path !== '..' && $path === $file.'.html') {
$html = file_get_contents($path);
}
}
echo $html;
?>
Exploidale as proxy:
http://example.com/script.php?display=https://hackme.com/passwords%3Extension%3D
echo file_get_contents("https://hackme.com/passwords?Extension=.html")
Your IP will be logged on hackme.com machine and return some passwords (when lucky).

file_exists() returns false, but the file DOES exist

I'm having a very weird issue with file_exists(). I'm using this function to check if 2 different files in the same folders do exist. I've double-checked, they BOTH do exist.
echo $relative . $url['path'] . '/' . $path['filename'] . '.jpg';
Result: ../../images/example/001-001.jpg
echo $relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension'];
Result: ../../images/example/001-001.PNG
Now let's use file_exists() on these:
var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.jpg'));
Result: bool(false)
var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension']));
Result: bool(true)
I don't get it - both of these files do exist. I'm running Windows, so it's not related to a case-sensitive issue. Safe Mode is off.
What might be worth mentioning though is that the .png one is uploaded by a user via FTP, while the .jpg one is created using a script. But as far as I know, that shouldn't make a difference.
Any tips?
Thanks
file_exists() just doesn't work with HTTP addresses.
It only supports filesystem paths (and FTP, if you're using PHP5.)
Please note:
Works :
if (file_exists($_SERVER['DOCUMENT_ROOT']."/folder/test.txt")
echo "file exists";
Does not work:
if (file_exists("www.mysite.com/folder/test.txt")
echo "file exists";
Results of the file_exists() are cached, so try using clearstatcache(). If that not helped, recheck names - they might be similar, but not same.
I found that what works for me to check if a file exists (relative to the current php file it is being executed from) is this piece of code:
$filename = 'myfile.jpg';
$file_path_and_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . "{$filename}";
if ( file_exists($file_path_and_name) ){
// file exists. Do some magic...
} else {
// file does not exists...
}
Just my $.02: I just had this problem and it was due to a space at the end of the file name. It's not always a path problem - although that is the first thing I check - always. I could cut and paste the file name into a shell window using the ls -l command and of course that locates the file because the command line will ignore the space where as file_exists does not. Very frustrating indeed and nearly impossible to locate were it not for StackOverflow.
HINT: When outputting debug statements enclose values with delimiters () or [] and that will show a space pretty clearly. And always remember to trim your input.
It's because of safe mode. You can turn it off or include the directory in safe_mode_include_dir. Or change file ownership / permissions for those files.
php.net: file_exists()
php.net: safe mode
Try using DIRECTORY_SEPARATOR instead of '/' as separator. Windows uses a different separator for file system paths (backslash) than Linux and Unix systems.
A very simple trick is here that worked for me.
When I write following line, than it returns false.
if(file_exists('/my-dreams-files/'.$_GET['article'].'.html'))
And when I write with removing URL starting slash, then it returns true.
if(file_exists('my-dreams-files/'.$_GET['article'].'.html'))
I have a new reason this happens - I am using PHP inside a Docker container with a mounted volume for the codebase which resides on my local host machine.
I was getting file_exists == FALSE (inside Composer autoload), but if I copied the filepath into terminal - it did exist! I tried the clearstatche(), checked safe-mode was OFF.
Then I remembered the Docker volume mapping: the absolute path on my local host machine certainly doesn't exist inside the Docker container - which is PHP's perspective on the world.
(I keep forgetting I'm using Docker, because I've made shell functions which wrap the docker run commands so nicely...)
It can also be a permission problem on one of the parent folders or the file itself.
Try to open a session as the user running your webserver and cd into it. The folder must be accessible by this user and the file must be readable.
If not, php will return that the file doesn't exist.
have you tried manual entry. also your two extensions seem to be in different case
var_dump(file_exists('../../images/example/001-001.jpg'));
var_dump(file_exists('../../images/example/001-001.PNG'));
A custom_file_exists() function inspired by #Timur, #Brian, #Doug and #Shahar previous answers:
function custom_file_exists($file_path=''){
$file_exists=false;
//clear cached results
//clearstatcache();
//trim path
$file_dir=trim(dirname($file_path));
//normalize path separator
$file_dir=str_replace('/',DIRECTORY_SEPARATOR,$file_dir).DIRECTORY_SEPARATOR;
//trim file name
$file_name=trim(basename($file_path));
//rebuild path
$file_path=$file_dir."{$file_name}";
//If you simply want to check that some file (not directory) exists,
//and concerned about performance, try is_file() instead.
//It seems like is_file() is almost 2x faster when a file exists
//and about the same when it doesn't.
$file_exists=is_file($file_path);
//$file_exists=file_exists($file_path);
return $file_exists;
}
This answer may be a bit hacky, but its been working for me -
$file = 'path/to/file.jpg';
$file = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/'.$file;
$file_headers = #get_headers($file);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
}else{
$exists = true;
}
apparently $_SERVER['REQUEST_SCHEME'] is a bit dicey to use with IIS 7.0 + PHP 5.3 so you could probably look for a better way to add in the protocol.
I found this answer here http://php.net/manual/en/function.file-exists.php#75064
I spent the last two hours wondering what was wrong with my if statement: file_exists($file) was returning false, however I could call include($file) with no problem.
It turns out that I didn't realize that the php include_path value I had set in the .htaccess file didn't carry over to file_exists, is_file, etc.
Thus:
<?PHP
// .htaccess php_value include_path '/home/user/public_html/';
// includes lies in /home/user/public_html/includes/
//doesn't work, file_exists returns false
if ( file_exists('includes/config.php') )
{
include('includes/config.php');
}
//does work, file_exists returns true
if ( file_exists('/home/user/public_html/includes/config.php') )
{
include('includes/config.php');
}
?>
Just goes to show that "shortcuts for simplicity" like setting the include_path in .htaccess can just cause more grief in the long run.
In my case, the problem was a misconception of how file_exists() behaves with symbolic links and .. ("dotdot" or double period) parent dir references. In that regard, it differs from functions like require, include or even mkdir().
Given this directory structure:
/home/me/work/example/
www/
/var/www/example.local/
tmp/
public_html -> /home/me/work/example/www/
file_exists('/var/www/example.local/public_html/../tmp/'); would return FALSE even though the subdir exists as we see, because the function traversed up into /home/me/work/example/ which does not have that subdir.
For this reason, I have created this function:
/**
* Resolve any ".." ("dotdots" or double periods) in a given path.
*
* This is especially useful for avoiding the confusing behavior `file_exists()`
* shows with symbolic links.
*
* #param string $path
*
* #return string
*/
function resolve_dotdots( string $path ) {
if (empty($path)) {
return $path;
}
$source = array_reverse(explode(DIRECTORY_SEPARATOR, $path));
$balance = 0;
$parts = array();
// going backwards through the path, keep track of the dotdots and "work
// them off" by skipping a part. Only take over the respective part if the
// balance is at zero.
foreach ($source as $part) {
if ($part === '..') {
$balance++;
} else if ($balance > 0) {
$balance--;
} else {
array_push($parts, $part);
}
}
// special case: path begins with too many dotdots, references "outside
// knowledge".
if ($balance > 0) {
for ($i = 0; $i < $balance; $i++) {
array_push($parts, '..');
}
}
$parts = array_reverse($parts);
return implode(DIRECTORY_SEPARATOR, $parts);
}
I just encountered this same problem and I solved it in a mysterious way. After inserting a a filepath I copied from Windows File explorer. file_exists() keeps returning false continuously, but if I copy same path from VSCode editor it works perfectly.
After dumping variables with var_dump($path); I noticed something mysterious.
For path I copied from file explorer it shows length 94.
For path I copied from VSCode Editor it shows length 88.
Both path look same length on my code Editor.
My suggestion: if string contain hidden characters, it may fail and not work.

Access dir from remote server in php?

Is it possible to list all the files from a remote server.I am running this code in serverOne.com , its a php server .I want to access serverTwo.com/dirOne its aTomcat server.
$path = "http://www.serverTwo.com/dirOne";
if ($handle = opendir($widget_path)) {
while (false !== ($widgetfile = readdir($handle)))
{
if ($widgetfile != "." && $widgetfile != "..")
{
echo $widgetfile;
}
}
closedir($handle);
}
The short answer is No. Definitely not like that because that would be a serious security problem, don't you think?!
There are ways you could establish a link between two servers but just allowing pretty much anyone to list files and read files off of one server from another would be quite bad.
If the other server has directory browsing enabled and there's no default document in the directory, then generally you get an HTML page containing a file listing. But if it's disabled and/or default-documented, then no, you can't. Not directly.
You can probably connect to your second server using FTP

PHP : Finding Files on Directory

Is it possible to find a file on C:/ (windows) using php script? If yes, is there any manual of sample code/workaround.
Edit : The webserver are on same PC as C:/ Directory in.
Thank you
If you're looking for a recursive search you might be interested in the spl's RecursiveDirectoryIterator.
<?php
$path = 'C:/';
$file = 'issetup.exe';
$rdi = new RecursiveDirectoryIterator($path);
$rit = new RecursiveIteratorIterator($rdi);
foreach( $rit as $path=>$info ) {
if ( $file===$info->getFilename() ) {
echo $path, "\n";
break;
}
}
As long as you only want to look in one directory, then yes, coding it using the PHP functions is quicker. But if you want to search recursively through the tree for a particular filename then it'll probably be a lot quicker to shell out:
$cmd="dir $fname /s"
chdir("C:/");
$found=explode("\n",`$cmd`);
But I believe that these days NT has file indexing built in to the OS - so there must be hooks exposed somewhere for an even faster search.
C.
I use scandir for this purpose, like so:
$path = $_SERVER['DOCUMENT_ROOT'];
$files = scandir($path);
echo '<pre>';
if (count($files) > 2) {
// first 2 entries are '.' and '..'
$files = array_slice($files, 2);
print_r($files);
}
echo '</pre>';
Go read up on http://php.net/manual/en/function.scandir.php
And for help on manululating the resulting array: http://php.net/manual/en/ref.array.php
If you are talking about the server on whcih PHP is installed, it should be infinitely possible with the PHP file command, as long as you are accessing areas of the HDD that share permissions with the webserver. The first example on PHP.net says as much ...
http://php.net/manual/en/function.file.php
If you are talking about your user's machine, they can select a file to upload using a <input id="uploader" name="uploader" type="file"> form element, but you cannot browse it using any server side language, because it is exactly that.
Unless you're talking about the C: drive on the server, or a command-line version of PHP running on your Windows machine, PHP as a server side language, doesn't have access to your C: drive.
If you are referring to the C: drive on the server, then the readdir function (as haim evgi suggested) should work for you.
Remember to read the warning on the readdir reference page, and remember to open the directory first. The function reference provides sample code.
I assume you want to run from the actual PHP interpreter (ie as a local script), you can use SPL(php 5)
see here and here for just 2 examples. More examples if you read the PHP manual and lots of others on the web if you search hard enough.

How do I make sure a file path is within a given subdirectory?

I want to make sure a file path set via query string does not go outside of the desired subdirectory. Right now, I am checking that:
The path does not start with "/", to prevent the user from giving an absolute path.
The path does not contain "..", to prevent the user from giving a path that is outside of the desired subdirectory.
The path does not contain ":", to prevent the use of a url (i.e. "http://", "ftp://", etc.). Should I ever run this script on a Windows server (not likely), this will also prevent absolute paths beginning with a drive specifier (i.e. "C:\"). Note: I'm aware that a colon is a valid character in a Unix filenames, but I will never be using it in a filename.
The path does not start with "\". Just in case I change my mind about running on a Windows server, this prevents Windows network paths from being specified (i.e. "\\someserver\someshare"). Again, I'm aware that a backslash is a valid Unix filename character, but I also won't be using it in any filenames.
Are these checks sufficient?
Background
I have a PHP script that takes (via query string) the path to a sample source file to be shown to a user. So I might give them a link like "view_sample.php?path=accounting_app/report_view.php" or "view_sample.php?path=ajax_demo/get_info.js".
The script looks basically like this:
$path = $_GET['path'];
if(path_is_valid($path) && is_file("sample/$path"))
{
header('Content-Type: text/plain');
readfile("sample/$path");
}
My concern is that a malicious user would see the url and try to do something like "view_sample.php?path=../../database/connection_info.php" and gain access to a file which is not in the "sample" directory.
Are the four checks I defined above (which would be implemented in the path_is_valid() function) sufficient to lock out a malicious user? (Also, I think checks 1, 3, and 4 are basically irrelevant since I am prepending a relative path, but if I didn't do this would the checks be sufficient?)
Call
$path = realpath("sample/$path");
Then check that the resulting path starts with the directory you're expecting.
<?php
// Current path information
$path = $_GET['path'];
$vroot = "sample";
// Validate that the $path is a subfolder of $vroot
$vroot = realpath($vroot);
if(substr(realpath($path), 0, strlen($vroot)) != $vroot or !is_dir($path)) {lid!
exit("Invalid path");
} else {
echo "Ah, everything is alright!";
}
?>
The use of realpath should not change the path, so I use it in the following way:
function checkPath($pathToCheck) {
global $basepath;
$fullpath = $basepath.'/'.$pathToCheck;
if ($fullpath==realpath($fullpath) && is_dir($fullpath)) {
return $fullpath;
} else {
error_die('path not allowed: '.htmlentities($pathToCheck));
}
}

Categories