Php изменить права на файл
Осуществляет попытку изменения режима доступа указанного файла на режим, переданный в параметре mode .
Список параметров
Обратите внимание, что значение параметра mode не переводится автоматически в восьмеричную систему счисления, поэтому, чтобы удостовериться в том, что режим был установлен верно, предваряйте нулем (0) значение передаваемое в параметре mode . Строки, такие как "g+w", не будут работать должным образом.
chmod ( "/somedir/somefile" , 755 ); // десятичное, скорее всего, указано неверно
chmod ( "/somedir/somefile" , "u+rwx,go+rx" ); // строка, неверный способ
chmod ( "/somedir/somefile" , 0755 ); // восьмеричное, верный способ
?>?php
Значение параметра mode состоит из трех восьмеричных чисел, определяющих уровень доступа для владельца файла, для группы, в которую входит владелец, и для других пользователей, соответственно. Число, определяющее уровень пользователя, может быть вычислено путем суммирования значений, определяющих права: 1 - доступ на выполнение, 2 - доступ на запись, 4 - доступ на чтение. Сложите эти числа для указания нужного права доступа. Более подробно о системе прав в системах Unix вы можете узнать с помощью команд 'man 1 chmod' и 'man 2 chmod'.
// Доступ на запись и чтение для владельца, нет доступа для других
chmod ( "/somedir/somefile" , 0600 );
// Доступ на запись и чтение для владельца, доступ на чтение для других
chmod ( "/somedir/somefile" , 0644 );
// Полный доступ для владельца, доступ на чтение и выполнение для других
chmod ( "/somedir/somefile" , 0755 );
// Полный доступ для владельца, доступ на чтение и выполнение для группы владельца
chmod ( "/somedir/somefile" , 0750 );
?>
Примечания
Замечание:
Текущим пользователем является пользователь, от имени которого выполняется PHP. Возможно, что это будет не тот пользователь, под именем которого вы получаете доступ к командной оболочке или учетной записи FTP. На большинстве систем режим доступа к файлу может быть изменен только его владельцем.
Замечание: Эта функция неприменима для работы с удаленными файлами, поскольку файл должен быть доступен через файловую систему сервера.
Замечание:
При включенном безопасный режим PHP проверяет имеет ли файл или директория, с которой вы работаете, такой же UID (id владельца), как и выполняемый скрипт. Кроме того, вы не можете устанавливать SUID, SGID и "липкие" (sticky) биты.
Возвращает права доступа на указанный файл в числовом виде. Младшие биты этого значения такие же, как и биты прав доступа для использования в функции chmod() , однако, на большинстве платформ, возвращаемое значение будет также включать информацию о типе файла, который передан в качестве параметра filename . Примеры ниже демонстрируют как проверить возвращаемое значение на наличие определённых прав и типа файла на POSIX-системах, включая Linux и macOS.
Для локальных файлов, возвращаемое значение является частью структуры st_mode , которая возвращается функцией С-библиотеки stat() . Какие в точности биты установлены может варьироваться от платформы к платформе. Рекомендуется поискать документацию к вашей платформе, если требуется обработка битов возвращаемого значения, не относящихся к правам доступа.
Возвращает false в случае возникновения ошибки.
Список параметров
Обратите внимание, что значение параметра mode не переводится автоматически в восьмеричную систему счисления, поэтому, чтобы удостовериться в том, что режим был установлен верно, предваряйте нулем (0) значение передаваемое в параметре mode . Строки, такие как "g+w", не будут работать должным образом.
chmod ( "/somedir/somefile" , 755 ); // десятичное, скорее всего, указано неверно
chmod ( "/somedir/somefile" , "u+rwx,go+rx" ); // строка, неверный способ
chmod ( "/somedir/somefile" , 0755 ); // восьмеричное, верный способ
?>?php
Значение параметра mode состоит из трех восьмеричных чисел, определяющих уровень доступа для владельца файла, для группы, в которую входит владелец, и для других пользователей, соответственно. Число, определяющее уровень пользователя, может быть вычислено путем суммирования значений, определяющих права: 1 - доступ на выполнение, 2 - доступ на запись, 4 - доступ на чтение. Сложите эти числа для указания нужного права доступа. Более подробно о системе прав в системах Unix вы можете узнать с помощью команд 'man 1 chmod' и 'man 2 chmod'.
// Доступ на запись и чтение для владельца, нет доступа для других
chmod ( "/somedir/somefile" , 0600 );
// Доступ на запись и чтение для владельца, доступ на чтение для других
chmod ( "/somedir/somefile" , 0644 );
// Полный доступ для владельца, доступ на чтение и выполнение для других
chmod ( "/somedir/somefile" , 0755 );
// Полный доступ для владельца, доступ на чтение и выполнение для группы владельца
chmod ( "/somedir/somefile" , 0750 );
?>
User Contributed Notes 7 notes
(A) Better not to create files or folders with user-supplied names. If you do not validate enough, you can have trouble. Instead create files and folders with randomly generated names like fg3754jk3h and store the username and this file or folder name in a table named, say, user_objects. This will ensure that whatever the user may type, the command going to the shell will contain values from a specific set only and no mischief can be done.
(B) The same applies to commands executed based on an operation that the user chooses. Better not to allow any part of the user's input to go to the command that you will execute. Instead, keep a fixed set of commands and based on what the user has input, and run those only.
For example,
(A) Keep a table named, say, user_objects with values like:
username|chosen_name |actual_name|file_or_dir
--------|--------------|-----------|-----------
jdoe |trekphotos |m5fg767h67 |D
jdoe |notes.txt |nm4b6jh756 |F
tim1997 |_imp_ folder |45jkh64j56 |D
and always use the actual_name in the filesystem operations rather than the user supplied names.
(B)
$op = $_POST [ 'op' ]; //after a lot of validations
$dir = $_POST [ 'dirname' ]; //after a lot of validations or maybe you can use technique (A)
switch( $op ) case "cd" :
chdir ( $dir );
break;
case "rd" :
rmdir ( $dir );
break;
.
default:
mail ( "webmaster@example.com" , "Mischief" , $_SERVER [ 'REMOTE_ADDR' ]. " is probably attempting an attack." );
>
All of the fixes here assume that it is necessary to allow the user to enter system sensitive information to begin with. The proper way to handle this would be to provide something like a numbered list of files to perform an unlink action on and then the chooses the matching number. There is no way for the user to specify a clever attack circumventing whatever pattern matching filename exclusion syntax that you may have.
Anytime you have a security issue, the proper behaviour is to deny all then allow specific instances, not allow all and restrict. For the simple reason that you may not think of every possible restriction.
Well, the fact that all users run under the same UID is a big problem. Userspace security hacks (ala safe_mode) should not be substitution for proper kernel level security checks/accounting.
Good news: Apache 2 allows you to assign UIDs for different vhosts.
devik
A basic filename/directory/symlink checking may be done (and I personally do) via realpath() .
if (isset( $_GET [ 'file' ])) <
$base = '/home/polizei/public_html/' ; // it seems this one is good to be realpath too.. meaning not a symlinked path..
if ( strpos ( $file = realpath ( $base . $_GET [ 'file' ]), $base ) === 0 && is_file ( $file )) <
unlink ( $file );
> else <
die( 'blah!' );
>
>
?>
when using Apache you might consider a apache_lookup_uri on the path, to discover the real path, regardless of any directory trickery.
then, look at the prefix, and compare with a list of allowed prefixes.
for example, my source.php for my website includes:
if(isset($doc)) $apacheres = apache_lookup_uri($doc);
$really = realpath($apacheres->filename);
if(substr($really, 0, strlen($DOCUMENT_ROOT)) == $DOCUMENT_ROOT) if(is_file($really)) show_source($really);
>
>
>
hope this helps
regards,
KAT44
I don't think the filename validation solution from Jones at partykel is complete. It certainly helps, but it doesn't address the case where the user is able to create a symlink pointing from his home directory to the root. He might then ask to unlink "foo/etc/passwd" which would be in his home directory, except that foo is a symlink pointing to /.
Personally I wouldn't feel confident that any solution to this problem would keep my system secure. Running PHP as root (or some equivalent which can unlink files in all users' home directories) is asking for trouble.
If you have a multi-user system and you are afraid that users may install scripts like this, try security-enhanced Linux. It won't give total protection, but it at least makes sure that an insecure user script can only affect files which the web server is meant to have access to. Whatever script someone installs, outsiders are not going to be able to read your password file---or remove it.
I think the lesson is clear:
(1) Forbit path separators in usernames.
(2) map username to a physical home directory - /home/username is fine
(3) read the home directory
(4) present only results of (3) as an option for deletion.
I have discovered a marvelous method of doing the above in php but this submission box is too small to contain it.
Осуществляет попытку изменения режима доступа указанного файла на режим, переданный в параметре permissions .
Ошибки
В случае неудачного завершения работы генерируется ошибка уровня E_WARNING .
User Contributed Notes 17 notes
BEWARE, a couple of the examples in the comments suggest doing something like this:
chmod(file_or_dir_name, intval($mode, 8));
However, if $mode is an integer then intval( ) won't modify it. So, this code.
$mode = 644;
chmod('/tmp/test', intval($mode, 8));
. produces permissions that look like this:
Instead, use octdec( ), like this:
BEWARE using quotes around the second parameter.
If you use quotes eg
chmod (file, "0644");
php will not complain but will do an implicit conversion to an int before running chmod. Unfortunately the implicit conversion doesn't take into account the octal string so you end up with an integer version 644, which is 1204 octal
Value Permission Level
400 Owner Read
200 Owner Write
100 Owner Execute
40 Group Read
20 Group Write
10 Group Execute
4 Global Read
2 Global Write
1 Global Execute
In the previous post, stickybit avenger writes:
Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value.
Note that in order to set the sticky bit on a file one must use '01777' (oct) and not '1777' (dec) as the parameter to chmod:
chmod ( "file" , 01777 ); // correct
chmod ( "file" , 1777 ); // incorrect, same as chmod("file",01023), causing no owner permissions!
?>
Rule of thumb: always prefix octal mode values with a zero.
use a stored string for the mask is a pain
ex: $mask contains a string 0755
int($mask) not work (return 755)
the only way i found is use octdec($mask)
Changes file mode recursive in $pathname to $filemode
$iterator = new RecursiveIteratorIterator (new RecursiveDirectoryIterator ( $pathname ));
foreach( $iterator as $item ) chmod ( $item , $filemode );
>
Note that info at rvgate dot nl's chmodnum function produces INCORRECT results. The resutls are base-10 numbers that only LOOK like they are octal numbers. The function also ignores setuid, setgid and sticky bits, and will produce incorrect numbers if such a file is encountered. Instead, this brute-force code works. Maybe there is something more slick, but this isn't too CPU-intensive (note that it assumes you've error-checked that you indeed have a 10-character string!):
$permissions = 'drwxr-xr-x' ; // or whatever
$mode = 0 ;
if ( $permissions [ 1 ] == 'r' ) $mode += 0400 ;
if ( $permissions [ 2 ] == 'w' ) $mode += 0200 ;
if ( $permissions [ 3 ] == 'x' ) $mode += 0100 ;
else if ( $permissions [ 3 ] == 's' ) $mode += 04100 ;
else if ( $permissions [ 3 ] == 'S' ) $mode += 04000 ;
if ( $permissions [ 4 ] == 'r' ) $mode += 040 ;
if ( $permissions [ 5 ] == 'w' ) $mode += 020 ;
if ( $permissions [ 6 ] == 'x' ) $mode += 010 ;
else if ( $permissions [ 6 ] == 's' ) $mode += 02010 ;
else if ( $permissions [ 6 ] == 'S' ) $mode += 02000 ;
if ( $permissions [ 7 ] == 'r' ) $mode += 04 ;
if ( $permissions [ 8 ] == 'w' ) $mode += 02 ;
if ( $permissions [ 9 ] == 'x' ) $mode += 01 ;
else if ( $permissions [ 9 ] == 't' ) $mode += 01001 ;
else if ( $permissions [ 9 ] == 'T' ) $mode += 01000 ;
printf ( 'Mode is %d decimal and %o octal' , $mode , $mode );
?>
Windows has a very different file permission model to Unix and integrates them only minimally.
On Windows, all this function can do is to change the "read only" flag, which is turned on if $mode & 0200 does not pass.
i.e. it only checks if u+w is missing from the bitmask, and if it is, it sets the read only flag.
The executable flag cannot be set as Windows determines it based on file extension.
The write flag cannot be set as Windows determines write access based on ACLs, which are not integrated here.
If you cannot chmod files/directories with PHP because of safe_mode restrictions, but you can use FTP to chmod them, simply use PHP's FTP-functions (eg. ftp_chmod or ftp_site) instead. Not as efficient, but works.
Just an update of the solution with octdec. You have to give octdec the string as a parameter.
$mode = '644';
chmod(file_or_dir_name, octdec($mode));
an update to 'neil at 11 out of 10's code for changing mode using FTP.
changes: proper array added within the function (better for those of us who only need to connect to one ftp server) so only the mode and directory name need to be passed.
the octal added, for completeness and predictable stability.
$path = "public" ;
$mod = intval ( $xcite , 8 );
// extract ftp details (array keys as variable names)
extract ( $ftp_details );
// set up basic connection
$conn_id = ftp_connect ( $ftp_server );
// login with username and password
$login_result = ftp_login ( $conn_id , $ftp_user_name , $ftp_user_pass );
// try to chmod $path directory
if ( ftp_site ( $conn_id , 'CHMOD ' . $mod . ' ' . $ftp_root . $path ) !== false ) <
$success = TRUE ;
>
else <
$success = FALSE ;
>
// close the connection
ftp_close ( $conn_id );
return $success ;
>
?>
for those of you, like me, who were looking for a way to make an 'un-hackable' uploader, here's the closest i got, now for a field test, good luck!
I was trying to change permissions of a folder with chmod command with FTP connection. (I needed a writable folder to upload pictures with php)
I got the following respond:
"SITE CHMOD 777 uploads: command not understood"
The reason: Server is running under Windows system that does not allow to set file permissions via FTP. Conversely, the UNIX-running servers allow that.
1. If your web hosting provider has a web-based control panel that lets you set file permissions, then you need to login there and make changes.
2. It is possible to contact the hosting provider and ask them about this issue; maybe they can make the changes.
3. It is possible to change the hosting provider that has servers run on UNIX, and keep the site there.
error_reporting ( E_ERROR | E_PARSE );
/* Makes is so Directories are not browseable to the public,
removing only the Public = Read permission, while leaving
the other chmod permissions for the file in tact.
If you have exectue already on, and read off, public viewers will only
be able to view files through links, but not browse
around to see what's inside of directories and see what
you've got laying around. */
//-------------------------------------------------------
// Get file mode
// Get file permissions supported by chmod
function getmod ( $filename ) <
$val = 0 ;
$perms = fileperms ( $filename );
// Owner; User
$val += (( $perms & 0x0100 ) ? 0x0100 : 0x0000 ); //Read
$val += (( $perms & 0x0080 ) ? 0x0080 : 0x0000 ); //Write
$val += (( $perms & 0x0040 ) ? 0x0040 : 0x0000 ); //Execute
// Misc
$val += (( $perms & 0x40000 ) ? 0x40000 : 0x0000 ); //temporary file (01000000)
$val += (( $perms & 0x80000 ) ? 0x80000 : 0x0000 ); //compressed file (02000000)
$val += (( $perms & 0x100000 ) ? 0x100000 : 0x0000 ); //sparse file (04000000)
$val += (( $perms & 0x0800 ) ? 0x0800 : 0x0000 ); //Hidden file (setuid bit) (04000)
$val += (( $perms & 0x0400 ) ? 0x0400 : 0x0000 ); //System file (setgid bit) (02000)
$val += (( $perms & 0x0200 ) ? 0x0200 : 0x0000 ); //Archive bit (sticky bit) (01000)
//-------------------------------------------------------
// Take the read option off of all the subdirectories of the included path
function pathlock ( $dir , $listall = false , $testrun = true ) <
echo "START @ " . date ( "F j, Y, h:i:s A" ) . "
" ;
echo ( $testrun ? '**Test Run Activated (no changes will be made).**
' : '**Live Run Activated.**
' );
echo $dir . " is our directory.
\n" ;
echo "[. IN PROGRESS. ]
" ;
$file_list = '' ;
$stack [] = $dir ;
while ( $stack ) <
$current_dir = array_pop ( $stack );
if ( $dh = opendir ( $current_dir )) <
while (( $file = readdir ( $dh )) !== false ) <
if ( $file !== '.' AND $file !== '..' ) <
$current_file = " < $current_dir >/ < $file >" ;
if ( is_dir ( $current_file )) <
// BEG ADD PATH
$mode = getmod ( $current_file ); //Get the mode
$HasPubRead = hasmod ( $mode , 4 );
if ( $HasPubRead || $listall ) < // Can the public read this dir?
//======================================
$ch = true ;
$take = 0 ;
// Change the mode:
if ( $HasPubRead ) <
$take = 4 ; // Value for Public Read. 4 is the same in octal and decimal.
if (! $testrun ) <
$ch = chmod ( $current_file , $mode - $take );
>
>
echo $current_file . ",current keyword">. decoct ( $mode ) .
(( $mode !== $mode - $take ) ? ",new keyword">. decoct ( $mode - $take ) : '' ) .
( $ch ? '' : ',FAILED' ) . "
\n" ;
> // end if hasmod
// END ADD PATH
$stack [] = $current_file ;
> // if if_dir
> //if ($file !== '.' AND $file !== '..')
> //while (($file = readdir($dh)) !== false)
> //if ($dh = opendir($current_dir))
> // while ($stack)
echo "
COMPLETE @ " . date ( "F j, Y, h:i:s A" ) . "
\n" ;
return;
//return $path_list;
> // end function
//-------------------------------------------------------
//listall Show all folders, even one's we're not going to process?
//testrun Do a test run without making any changes
pathlock ( $_SERVER [ "DOCUMENT_ROOT" ], false , true ); // listall?=false, testrun?=true
В прошлой статье я достаточно подробно рассказал о правах доступа к файлам. Разумеется, это только теория, которую необходимо знать, чтобы правильно использовать функции для работы с правами доступа к файлам через PHP. Эту тему мы разберём в данной статье.
Я уже говорил, что у файла всегда есть владелец, и у каждого файла имеется информация о его владельце. Каждый пользователь имеет свой UID (уникальный идентификатор), и именно этот идентификатор хранится в каждом файле. Чтобы узнать его, используется функция fileowner():
После этого будет получен UID владельца файла "myfile.txt". Чтобы сменить владельца файла, надо воспользоваться функцией chown():
В данном примере мы передали права владельца "myfile.txt" пользователю myuser. Также вместо имени пользователя можно указывать его UID.
Следующая пара PHP-функций - это filegroup() и chgrp(), которые работают аналогично функциям fileowner() и chown(), но отвечают за группу пользователей:
echo filegroup("myfile.txt");
chgrp("mygroup", "myfile.txt");
?>
И, наконец, последние, но самые важные функции для работы с правами доступа к файлам через PHP - это fileperms() и chmod():
Как Вы уже догадались, функция fileperms() возвращает права доступа к файлу. А функция chmod() устанавливает новые права доступа к файлу. Также заметьте, что права задаются с обязательным указанием ведущего нуля!
Это самые основные и самые важные функции PHP для работы с правами доступа. Я бы даже сказал, что реально используются только последние две, поэтому с ними потренируйтесь в работе. И ещё раз напоминаю, что права доступа имеются только в Unix-системах, а в Windows их вообще нет, поэтому и данные функции там так же будут работать некорректно.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Она выглядит вот так:
Комментарии ( 8 ):
А можно это как-то сделать чтобы это не видели пользователи? То есть, если они смотрят исходный код страницы и чтобы они в нем не увидели этого PHP-кода?
Они его и не увидят. Этот код выполняется на сервере ещё до того, как пользователи увидят конечную HTML-страницу.
Здравствуйте! Извините за возможно глупый вопрос, но когда добавляешь файлы через Админ-панель в папку с правами, например 744, нужно сначала поменять права на 777, добавить файл и обратно поменять права.
По fileowner и filegroup выдаёт нули, а по fileperms выдаёт 33206. Такие дела.
Дочитал и понял, в Windows не работает, можешь не замарачиваться
Эта статья рассчитана на работу с хостингом (на Linux) через фтп-клиент к примеру. В Windows не много по-другому все устроено.
Ошибки
В случае возникновения ошибки выдаётся ошибка уровня E_WARNING .
Смотрите также
- chown() - Изменяет владельца файла
- chgrp() - Изменяет группу файла
- fileperms() - Возвращает информацию о правах на файл
- stat() - Возвращает информацию о файле
Список параметров
Обратите внимание, что значение параметра permissions не переводится автоматически в восьмеричную систему счисления, поэтому, чтобы удостовериться в том, что режим был установлен верно, предваряйте нулём (0) значение передаваемое в параметре permissions . Строки, такие как "g+w", не будут работать должным образом.
chmod ( "/somedir/somefile" , 755 ); // десятичное, скорее всего, указано неверно
chmod ( "/somedir/somefile" , "u+rwx,go+rx" ); // строка, неверный способ
chmod ( "/somedir/somefile" , 0755 ); // восьмеричное, верный способ
?>?php
Значение параметра permissions состоит из трёх восьмеричных чисел, определяющих уровень доступа для владельца файла, для группы, в которую входит владелец, и для других пользователей, соответственно. Число, определяющее уровень пользователя, может быть вычислено путём суммирования значений, определяющих права: 1 - доступ на выполнение, 2 - доступ на запись, 4 - доступ на чтение. Сложите эти числа для указания нужного права доступа. Более подробно о системе прав в системах Unix вы можете узнать с помощью команд 'man 1 chmod' и 'man 2 chmod'.
// Доступ на запись и чтение для владельца, нет доступа для других
chmod ( "/somedir/somefile" , 0600 );
// Доступ на запись и чтение для владельца, доступ на чтение для других
chmod ( "/somedir/somefile" , 0644 );
// Полный доступ для владельца, доступ на чтение и выполнение для других
chmod ( "/somedir/somefile" , 0755 );
// Полный доступ для владельца, доступ на чтение и выполнение для группы владельца
chmod ( "/somedir/somefile" , 0750 );
?>
Возвращаемые значения
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
User Contributed Notes 9 notes
Don't use substr, use bit operator
decoct ( fileperms ( $file ) & 0777 ); // return "755" for example
?>
If you want to compare permission
0755 === ( fileperms ( $file ) & 0777 );
?>
This may not be immediately apparent to some, but you can use octdec( $octal_value ) to match the permissions retrieved by file perms
//assumes file has 2770 permissions
$perm = fileperms ( __FILE__ );
$bit = "102770" ;
printf ( "%s\n" , octdec ( $bit ) );
printf ( "%s\n" , $perm );
When ever you make a:
You have to call:
before you can call:
An easy way to calculate fileperms to chmod is this:
Displays 666 or 777 (depends on chmod set).
Displays 0666 or 0777 and refers immediately to the number set with chmod();
Windows has a very different file permission model to Unix and integrates them only minimally.
Here's how Windows calculates the bitmask.
u+w/g+w/o+w is set based on whether the file has the read only flag.
u+r/g+w/o+w is always set.
u+x/g+x/o+x is set based on whether $filename is an inherently executable file (e.g. bat) or a directory.
Windows isn't integrating its ACLs at all.
mixed mkperms( string $perms [, bool return_as_string = false [, string $filename ] ] )
Returns permissions given a string in literal format and a filename.
If the file name is omitted, the permissions that the function will return are based on 000-permissions.
If return_as_string is set to true, the result will be output as a 644 format string. Otherwise it will return a string converted to base-10 for chmod.
echo mkperms ( 'u+r' , true ), "\n" ; // 400
echo mkperms ( 'u+rwx,g+rw,o+x' , true ), "\n" ; // 761
touch ( 'myfile.txt' ); // Create a file with any permissions
chmod ( 'myfile.txt' , mkperms ( 'u=rwx,g=x,o=rw' )); // myfile.txt is now at -rwx--xrw-
// Make a file and give it full permissions
touch ( 'somefile.txt' );
chmod ( 'somefile.txt' , 0777 );
echo mkperms ( 'g-w,o-rw' , true , 'somefile.txt' ); // 751
echo mkperms ( 'u=rwx,g-r,o=-' , true , 'somefile.txt' ); // 730
// This way you can apply permissions to files
chmod ( 'somefile.txt' , mkperms ( 'u=rwx,g-r,o=-' , false , 'somefile.txt' )); // somefile.txt is now at -rwx-wx---
?>
PS : sorry I had to put it on pastebin, or else it just made the note way too long.
A small function for the last 3 digits (777/755 ect.)
function getFilePermission ( $file ) $length = strlen ( decoct ( fileperms ( $file )))- 3 ;
return substr ( decoct ( fileperms ( $file )), $length );
>
?>
Since the output of decoct( fileperms('.') ) is of the form: 40644
It seems the previous example is wrong, instead you should understand:
To get permissions formatted as "644":
echo substr ( decoct ( fileperms ( '.' ) ), 2 );
?>
To get permissions formatted as "0644":
echo substr ( decoct ( fileperms ( '.' ) ), 1 );
?>
On Linux (not tested on Windows), if you want a chmod-like permissions, you can use this function:
function file_perms ( $file , $octal = false )
if(! file_exists ( $file )) return false ;
$perms = fileperms ( $file );
$cut = $octal ? 2 : 3 ;
return substr ( decoct ( $perms ), $cut );
>
?>
Using it:
$ touch foo.bar
$ chmod 0754 foo.bar
echo file_perms ( 'foo.bar' ); // prints: 754
echo file_perms ( 'foo.bar' , true ); // prints 0754
?>
Рассмотрим следующий пример, в котором пользователь создал скрипт, удаляющий файл из его домашней директории. Предполагается ситуация, когда веб-интерфейс, написанный на PHP , регулярно используется для работы с файлами, и настройки безопасности позволяют удалять файлы в домашнем каталоге.
// Удаление файла из домашней директории пользователя
$username = $_POST [ 'user_submitted_name' ];
$userfile = $_POST [ 'user_submitted_filename' ];
$homedir = "/home/ $username " ;
unlink ( " $homedir / $userfile " );
echo "Файл был удалён!" ;
?>
Поскольку переменные вводятся в пользовательской форме, существует возможность удалить файлы, принадлежащие кому-либо другому, введя соответствующие значения. В этом случае может понадобиться авторизация. Посмотрим, что произойдёт, если будут отправлены значения "../etc/" и "passwd". Скрипт выполнит следующие действия:
// Удаление любого файла, доступного из PHP-скрипта.
// В случае, если PHP работает с правами пользователя root:
$username = $_POST [ 'user_submitted_name' ]; // "../etc"
$userfile = $_POST [ 'user_submitted_filename' ]; // "passwd"
$homedir = "/home/ $username " ; // "/home/../etc"
unlink ( " $homedir / $userfile " ); // "/home/../etc/passwd"
echo "Файл был удалён!" ;
?>
- Ограничить доступ пользователя, с правами которого работает веб-сервер с PHP .
- Проверять все данные, вводимые пользователем.
// Удаление любого файла, к которому имеет доступ пользователь,
// под которым запущен PHP.
$username = $_SERVER [ 'REMOTE_USER' ]; // использование авторизации
$userfile = basename ( $_POST [ 'user_submitted_filename' ]);
$homedir = "/home/ $username " ;
$filepath = " $homedir / $userfile " ;
if ( file_exists ( $filepath ) && unlink ( $filepath )) $logstring = " $filepath удалён\n" ;
> else $logstring = "Не удалось удалить $filepath \n" ;
>
$fp = fopen ( "/home/logging/filedelete.log" , "a" );
fwrite ( $fp , $logstring );
fclose ( $fp );
echo htmlentities ( $logstring , ENT_QUOTES );
Однако и такая проверка не учитывает все возможные ситуации. Если система авторизации позволяет пользователям выбирать произвольные логины, взломщик может создать учётную запись вида "../etc/" и система опять окажется уязвимой. Исходя из этого, вам может понадобиться более строгая проверка:
$username = $_SERVER [ 'REMOTE_USER' ]; // использование авторизации
$userfile = $_POST [ 'user_submitted_filename' ];
$homedir = "/home/ $username " ;
$filepath = " $homedir / $userfile " ;
if (! ctype_alnum ( $username ) || ! preg_match ( '/^(?:[a-z0-9_-]|\.(?!\.))+$/iD' , $userfile )) die( "Неправильное имя пользователя или файл" );
>
В зависимости от используемой вами операционной системы необходимо предусматривать возможность атаки на разнообразные файлы, включая системные файлы устройств (/dev/ или COM1), конфигурационные файлы (например /etc/ или файлы с расширением .ini), хорошо известные области хранения данных (/home/, My Documents), и так далее. Исходя из этого, как правило, легче реализовать такую политику безопасности, в которой запрещено все, исключая то, что явно разрешено.
Смотрите также
- chmod() - Изменяет режим доступа к файлу
- is_readable() - Определяет существование файла и доступен ли он для чтения
- stat() - Возвращает информацию о файле
Примечания
Замечание:
Текущим пользователем является пользователь, от имени которого выполняется PHP. Возможно, что это будет не тот пользователь, под именем которого вы получаете доступ к командной оболочке или учётной записи FTP. На большинстве систем режим доступа к файлу может быть изменён только его владельцем.
Замечание: Эта функция неприменима для работы с удалёнными файлами, поскольку файл должен быть доступен через файловую систему сервера.
Возвращаемые значения
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Примеры
echo substr ( sprintf ( '%o' , fileperms ( '/tmp' )), - 4 );
echo substr ( sprintf ( '%o' , fileperms ( '/etc/passwd' )), - 4 );
?>?php
Результат выполнения данного примера:
switch ( $perms & 0xF000 ) case 0xC000 : // сокет
$info = 's' ;
break;
case 0xA000 : // символическая ссылка
$info = 'l' ;
break;
case 0x8000 : // обычный
$info = 'r' ;
break;
case 0x6000 : // файл блочного устройства
$info = 'b' ;
break;
case 0x4000 : // каталог
$info = 'd' ;
break;
case 0x2000 : // файл символьного устройства
$info = 'c' ;
break;
case 0x1000 : // FIFO канал
$info = 'p' ;
break;
default: // неизвестный
$info = 'u' ;
>
Результат выполнения данного примера:
Примечания
Замечание: Результаты этой функции кешируются. Более подробную информацию смотрите в разделе clearstatcache() .
Начиная с PHP 5.0.0, эта функция также может быть использована с некоторыми обёртками url. Список обёрток, поддерживаемых семейством функций stat() , смотрите в разделе Поддерживаемые протоколы и обёртки.
Читайте также: