Getting around PHP safe mode to write to server. Is it possible? - php

I have got the following problem since the server has safe mode turned on, and directories are being created under different users:
I upload my script to the server, it shows as belonging to 'user1'. All it is doing is making a new directory when a new user is created so it can store files in it.
New directory is created, but it belongs to 'apache' user.
'user1' and 'apache' are different users; and safe mode is turned on. So the php script cannot write to that newly created directory.
Now I have a problem!
One solution is to turn off safe mode. Also, a coworker suggested that there are settings that can be changed to ensure the directories are under the same user as the script. So I am looking to see if latter can be done.
But I have to ask. Is there a programatical solution for my problem?
I am leaning to a 'no', as safe mode was implemented to solve it at the php level. Also the actual problem may seem like the directory being created under a different user, so a programatic fix might just be a band-aid fix.

I've used this workaround:
instead of php mkdir you can create directories by FTP with proper rights.
function FtpMkdir($path, $newDir) {
$path = 'mainwebsite_html/'.$path;
$server='ftp.myserver.com'; // ftp server
$connection = ftp_connect($server); // connection
// login to ftp server
$user = "user#myserver.com";
$pass = "password";
$result = ftp_login($connection, $user, $pass);
// check if connection was made
if ((!$connection) || (!$result)) {
return false;
exit();
} else {
ftp_chdir($connection, $path); // go to destination dir
if(ftp_mkdir($connection, $newDir)) { // create directory
ftp_site($connection, "CHMOD 777 $newDir") or die("FTP SITE CMD failed.");
return $newDir;
} else {
return false;
}
ftp_close($connection); // close connection
}
}

You might be able to turn safe mode off for a specific directory via a .htaccess file (if on Apache).
php_value safe_mode = Off
You might need to get your hosting provider to make this change for you though in the httpd.conf.

I have had some success with setting the group bit of the upload directory to sticky.
PHP can then create directories inside it and write to it.
http://en.wikipedia.org/wiki/Setuid#setuid_and_setgid_on_directories
chmod g+s directory

Related

How to create a folder above the root directory using php

my root dir id
/var/www/html/
i want to create directory at /var/www/
ie /var/www/myfolder
i'm executing create_dir.php
from
/var/www/html/site/create_dir.php
when i execute this program it's unable to create folder.
in log i'm getting permission denide.
update
This is my code
<?php
$os_type=php_uname('s');
$cur_file_path=$_SERVER['PHP_SELF'];
echo "File path:$cur_file_path<br>";
$scount=substr_count($cur_file_path, '/');
echo "/ count:$scount<br>";
$doc_root= $_SERVER['DOCUMENT_ROOT'] ;
echo "doc root:$doc_root<br>";
if($os_type=='Linux')
{
$ds=substr_count("$cur_file_path","/");//directory seperator
echo "Count of /=$ds<br>";
}
if($os_type=='Windows')
{
$ds=substr_count("$cur_file_path","'\'");//directory seperator
}
$path="../";
for($i=1;$i<$scount;$i++)
{
$path.="../";
}
$dir="myfolder";
exec("mkdir ".$dir);
?>
how to solve this.
That is a security problem as it gives read and write access to the world. It may be that your apache user does not have read/write permissions on the directory.
Here's what you do if $os_type=='Linux':
1. Make sure all files are owned by the Apache group and user. In Linux it is the www-data group and user
exec('chown -R www-data:www-data /path/to/webserver/www',$ouput,$result);
2. Next enabled all members of the www-data group to read and write files
exec('chmod -R g+rw /path/to/webserver/www',$ouput,$result);
The php mkdir() function should now work without returning errors. You can also see the error output in $output in case of error.
There is the another way to create directory using ftp:
You can try mkdir with ftp, mkdir works with stream wrappers, so it's ok to write mkdir('ftp://user:pass#server/mydir');
OR
If you have problems with the SAFE MODE Restriction in effect i.e. if you try to create and access to subdirectorys recursive you can use ftp-lib like this.
<?php
DEFINE ('FTP_USER','yourUser');
DEFINE ('FTP_PASS','yourPassword');
/**
* Returns the created directory or false.
*
* #param Directory to create (String)
* #return Created directory or false;
*/
function mkDirFix ($path) {
$path = explode("/",$path);
$conn_id = #ftp_connect("localhost");
if(!$conn_id) {
return false;
}
if (#ftp_login($conn_id, FTP_USER, FTP_PASS)) {
foreach ($path as $dir) {
if(!$dir) {
continue;
}
$currPath.="/".trim($dir);
if(!#ftp_chdir($conn_id,$currPath)) {
if(!#ftp_mkdir($conn_id,$currPath)) {
#ftp_close($conn_id);
return false;
}
#ftp_chmod($conn_id,0777,$currPath);
}
}
}
#ftp_close($conn_id);
return $currPath;
}
?>
Maybe it helps.
The purpose of a "root" directory is to protect the hosting computer from malicious/buggy code that might damage information stored in other parts of the computer. It gives you an area in which you can safely do your thing while explicitly and deliberately preventing you from interfering with any data "above" your root directory. The root is as low as you can go, by design. Any host computer that has a vulnerability that would allow you to access data outside of your assigned space is a host computer begging to be hacked; you won't find many of those, hopefully.
It may be worthwhile to restructure the directories within your root directory to simulate a deeper root than what you are actually restricted to. Otherwise, it is a matter of convincing the system administrator for the host computer to allow you additional access.
In a properly designed and managed system, what you are asking for is intentionally not possible, and running into this particular roadblock is more a sign that you may need to reconsider what you want to do in light of your restrictions. Even if this is being hosted from your own computer and you are the system administrator, it would be wise to examine every possible way you can achieve the goals you hope to achieve without breaking that barrier. ANY means you implement to allow web-controlled code to break that barrier is a vulnerability in your system that someone, somewhere, is looking for an opportunity to exploit.

Error failed to open stream permission denied when trying to create page in public_html

I am trying to run a script which creates pages and saves them to the server
but am getting a permission error on one of the files that is in the public_html directory.
So 2 pages are created in the "pages" directory which is chmod to 0777 and they are created fine.
The 3rd page is created in the "public_html" directory which fails with you do not have permission.
The only way i have found to fix this is to chmod the "public_html" directory to 0770 which then
everything works but i have been strongly advised by the hosting company not to do this bevause of the security risk.
So my question is, Is there any otherway to achieve this goal?
Looking into it a bit it looks like i need to give the script "user" priviliges might work but
this is beyond my knowledge at the moment.
I`m not even sure what the script is running as at the moment, I would guess "group" as chmoding the public_html
to 0770 allows "group"
My setup is: vps server running centos CENTOS 6.7 x86_64
php 5, dso, Apache suEXEC on
simplified Code i am using is:
$page_path = "/home/username/public_html/";
$loop[Html_Name] = "test.html";
$new_page_file = "test.html";
$fp = fopen($page_path.$loop[Html_Name], "w");
fwrite($fp, $new_page_file);
fclose($fp);
chmod($page_path.$loop[Html_Name], 0666);
Many thanks in advance.
Typically, we use ftp in these situations. /public_html permissions may remain to 750 and run this code.
$server = 'localhost';
$ftp_user_name = 'username';
$ftp_user_pass = 'passw';
$dest = 'public_html/new.file';
$source = '/home/username/public_html/path/to/existing.file';
$connection = ftp_connect($server);
$login = ftp_login($connection, $ftp_user_name, $ftp_user_pass);
if (!$connection || !$login) { die('Ftp not connected.'); }
$copied = ftp_put($connection, $dest, $source, FTP_BINARY);
if ($copied) {
echo 'File copied';
} else {
echo 'Copy failed!';
}
ftp_close($connection);
The page with final destination in public_html can be created in the other directory and then this script will copy it in public_html. The old file will remain and if a file exists with the same destination name will be overwritten.
The $dest is relative path to user home directory. The $source is absolute path.
The connection will fail if the ftp is concurrently used by filezilla or something. A solution to that is to create a second ftp user account in cPanel.

How to update/replace php script on server

I am working on update feature for a CMS. But I stuck on this. The scenario is user will able to upload a zip file, the updater script will extract it and replace the old one.
I have a problem with replacing, I've done the following
<?php rename($old, $new);
I always get "Permission Denied"
using ftp_rename:
<?php
$conn = ftp_connect($host);
ftp_login($conn, 'user', 'pass');
ftp_rename($conn, $src, $dest);
I always get
Warning: ftp_rename(): Rename Failed. on....
Is there a proper way to do this ? thanks.
Depending on your linux distro, php actually executes command as a specific user. Check your apache (or whatever server you are using) settings and put the permission accordingly
For example in apache, it is set
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
You can then change that upload folder to be owned by www-data
For more information you can read this useful discussion
https://unix.stackexchange.com/questions/30879/what-user-should-apache-and-php-be-running-as-what-permissions-should-var-www

Cannot write create file using PHP file_put_contents

I'm new at the whole php thing, and I need to write a file in the server (my own computer where I am developing a web app) with some config info. Here is the code I'm using:
$filename = "config.conf";
$db_info = $db_user . "<-*->" . $db_passwd . "<-*->" . $db_name;
if (file_put_contents($filename,$db_info) === false){
$ret["error"] = "Can't create/write: $filename.";
mysqli_close($con);
echo json_encode($ret);
return;
}
When I test my web app I get the create/write error I wrote. I checked and the file is not created. My working directory is in /var/www/tests however I've checked tests and my user has read and write permissions and is owner of that folder. If I create a file with a ordinary file explorer I have no problems whatsoever. Since the function is so simple, I am at a loss. Please help!
does web server has read/write permissions (e.g. nginx uses www-data user)? try setting permissions to 777 for folder where you want to create that file.

PHP - Create directory on different server

I have Wamp (server called emerald) running and Mamp running on my Mac. People register on Mamp. Emerald is basically file hosting.
Emerald connects to Mamp's mysql database, to login users. However, I want to create a directories for new registrations on Emerald using PHP.
How can I do this? I have tried using this code:
$thisdir = "192.168.1.71";
$name = "Ryan-Hart";
if(mkdir($thisdir ."/documents/$name" , 0777))
{
echo "Directory has been created successfully...";
}
But had no luck. It basically needs to connect the other server and create a directory, in the name of the user.
I hope this is clear.
You can't create directories through http. You need a filesystem connection to the remote location (a local hard disk, or a network share for example).
The easiest way that doesn't require setting up FTP, SSH or a network share would be to put a PHP script on Emerald:
<?php
// Skipping sanitation because it's only going to be called
// from a friendly script. If "dir" is user input, you need to sanitize
$dirname = $_GET["dir"];
$secret_token = "10210343943202393403";
if ($_GET["token"] != $secret_token) die ("Access denied");
// Alternatively, you could restrict access to one IP
error_reporting(0); // Turn on to see mkdir's error messages
$success = mkdir("/home/www/htdocs/docs/".$dirname);
if ($success) echo "OK"; else echo "FAIL";
and call it from the other server:
$success = file_get_contents("http://192.168.1.71/create_script.php?token=10210343943202393403&dir=HelloWorld");
echo $success; // "OK" or "FAIL"
Create a script on another server that creates the dir and call it remotely.
Make sure you have security check (+a simple password at least)
There is no generic method to access remote server filesystems. You have to use a file transfer protocol and server software to do so. One option would be SSH, which however requires some setup.
$thisdir = "ssh2.sftp://user:pass#192.168.1.71/directory/";
On Windows you might get FTP working more easily, so using an ftp:// url as directory might work.
As last alternative you could enable WebDAV (the PUT method alone works for file transfers, not creating directories) on your WAMP webserver. (But then you probably can't use the raw PHP file functions, probably needs a wrapper class or curl to utilize it.)
I know this is old but i think this might me useful, in my experience:
if(mkdir($thisdir ."/documents/name" , 0777))
doesn't work, i need to do it:
mkdir($thisdir, 0777);
mkdir($thisdir ."/documents" , 0777);
mkdir($thisdir ."/documents/name" , 0777));
hope it helps :)

Categories