Here’s an idea. I’m trying to create file from PHP script. File may be created in any public place on server (in public root or in its subdirectories). Bottom of line, I want to write function like this (it must work on both unix and windows servers).
function create_file($path, $filename, $content, $overwrite=false) {
# body
...
}
Parameters:
- $path – file-path (empty or ends with
/) - $filename – any valid file-name (requires dot+extension)
- $content – file-content (anything)
- $overwrite – if set true, existing file will be overwritten (default. false).
Result:
Function returns TRUE and creates file with content, or FALSE if file-creation was not possible for any reason.
Description of problem:
I expect this function to return true and create file $filename on path $path, or false if it wasn’t possible for any reason. Also if file was successfully opened for writing, need to put $content in it.
Argument $path is relative path to public directory, and $filename is any valid filename. Of course, I want to avoid creating files if path points outside of public directory. Function may be called from subdirectory-scripts like this example
# php script: /scripts/test.php
create_file('../data/', 'test.info', 'some contents');
# result file: /data/test.info
What have I tried so far?
I’ve tried doing this with fopen() and fwrite() functions and that works on some servers, and doesn’t work on some. I guess there’s problem with writing privileges and chmod() but to be honest I’m not very familiar with chmod attributes. Also I couldn’t check if $path points outside of server’s public directory.
In short, I want this function to create file and return TRUE if file doesn’t exist, or file exists and $owerwrite=true. Otherwise, nothing happens and function returns FALSE.
Additionally, I would like to know reason why file can’t be created on some path (just in theory). Incorrect path/filename is only thing I have on my mind and I’m sure there’s more about this problem.
Thanks in advance for any sample/example/suggestion.
update code
So far I have this code…
function create_file($path, $filename, $content, $overwrite=false) {
$reldir = explode('/', trim(str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])), '/'));
$dirdepth = sizeof($reldir);
$rpadd = $dirdepth > 0 ? '(\.\./){0,' . $dirdepth . '}' : '';
$ptpath = '#^/?' . $rpadd . '([a-z0-9]\w*/)*$#i';
$ptname = '/^[a-z]\w*\.[a-z0-9]+$/i';
if ($res = preg_match($ptpath, $path) && preg_match($ptname, $filename)) {
$res = false;
if ($overwrite === true || !file_exists($path.$filename)) {
if ($f = @fopen($path.$filename, 'w')) {
fwrite($f, $content);
fclose($f);
$res = true;
}
}
}
return $res;
}
Some suggestions:
Basename php function can help you identifying this kind of malignous paths. Look this post: php directory traversal issue