Как получить доступ к php файлу

Обновлено: 07.07.2024

В PHP скриптах, вызывая include() , require() , fopen() или их производные, такие как include_once , require_once или даже move_uploaded_file() , часто появляются ошибки или предупреждения:

Не удалось открыть поток: нет такого файла или каталога.

Как быстро найти первопричину проблемы?

Ответ 1

Есть много причин, по которым можно столкнуться с этой ошибкой, и поэтому я дам контрольный список того, что необходимо проверить в первую очередь для решения этой ситуации.

Предположим, у нас есть следующая строка:

require "/path/to/file"

Контрольный список

1. Проверьте путь к файлу на предмет опечаток

  • проверьте вручную (визуально проверив путь) ;

  • переместите все, что вызывается с помощью require* или include* в переменную, скопируйте ее и попробуйте получить к ней доступ с терминала:

2. Убедитесь, что путь к файлу правильный с точки зрения относительного и абсолютного пути

  • если он начинается с косой черты "/", то это относится не к корню папки вашего веб-сайта (корень документа), а к корню вашего сервер :

    • например, каталог вашего веб-сайта может быть /users/tony/htdocs ;

    • не относительно пути к корню вашего веб-сайта или файла ;

    • или всегда используйте абсолютные пути к файлам .

    1. используйте require __DIR__."/relative/path/from/current/file" , который возвращает каталог текущего файла ;

    2. определите SITE_ROOT константу самостоятельно:

      • в корне каталога вашего веб-сайта создайте файл, например , config.php

      • в config.php напишите :

    • в каждом файле, в котором вы хотите сослаться на корневую папку сайта, включите config.php и затем используйте SITE_ROOT константу везде, где хотите:

    3. Проверьте свои пути включения

    Другой способ включения файлов, ни относительный, ни абсолютный, - это полагаться на путь включения . Это часто бывает с библиотеками или фреймворками, такими как, например, Zend framework.

    Подобное включение будет выглядеть так:

    include "Zend/Mail/Protocol/Imap.php"

    В этом случае вы должны убедиться, что папка, в которой находится «Zend», является частью пути включения.

    Это можно проверить с помощью:

    echo get_include_path();

    Вы можете добавить в него папку с помощью:

    set_include_path(get_include_path().":"."/path/to/new/folder");

    4. Убедитесь, что у вашего сервера есть доступ к этому файлу

    Может случиться так, что у пользователя, запускающего серверный процесс (Apache или PHP), просто нет разрешения на чтение или запись в этот файл.

    Чтобы проверить, под каким пользователем запущен сервер, можно использовать posix_getpwuid :

    $user = posix_getpwuid(posix_geteuid());

    var_dump($user);

    Чтобы узнать права доступа к файлу, введите в терминале следующую команду:

    ls -l <path/to/file>

    5. Проверьте настройки PHP

      • Если установлено, PHP не сможет получить доступ к любому файлу за пределами указанного каталога (даже через символическую ссылку).

      • По умолчанию не устанавливается, и в этом случае ограничений нет.

      • Можно проверить, вызвав phpinfo() или используя ini_get("open_basedir") .

      • Вы можете изменить настройку, отредактировав файл php.ini или файл httpd.conf.

      • Е сли включено, могут быть ограничения. Однако данный режим был удален в PHP 5.4. Если вы все еще используете версию, которая поддерживает безопасный режим, обновитесь до версии PHP, которая это еще поддерживает .

      • О тносится только к включению или открытию файлов через сетевой процесс, такой как http://, но не работает для локальной файловой системы.

      • Э ти опции можно проверить, используя ini_get("allow_url_include") или установи в с помощью ini_set("allow_url_include", "1") .

    Другие случаи

    Если ничего из вышеперечисленного не помогло диагностировать проблему, могут возникнуть следующие особые ситуации:

    1. Включение библиотеки на основе пути включения

    Может случиться так, что вы подключаете библиотеку, например, платформу Zend, используя относительный или абсолютный путь. Например:

    require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"

    Но по-прежнему получаете такую же ошибку.

    Это могло произойти из-за того, что файл, который вы (успешно) включили, сам имеет оператор include для другого файла, и этот второй оператор include предполагает, что вы добавили путь этой библиотеки к пути включения.

    Например, упомянутый ранее файл фреймворка Zend может включать следующее:

    include "Zend/Mail/Protocol/Exception.php"

    что не является включением ни по относительному пути, ни по абсолютному пути. Предполагается, что каталог фреймворка Zend был добавлен в путь включения.

    В таком случае единственное практическое решение - добавить каталог в ваш путь включения.

    2. SELinux

    3. Symfony

    Если вы используете Symfony и получаете эту ошибку при загрузке на сервер, возможно, к э ш приложения не был сброшен, либо потому, что app/cache был загружен, либо этот к э ш не был очищен.

    Для этого надо выполнить следующую консольную команду:

    cache:clear

    4. Внутри Zip-файла символы, отличные от A SC II

    По-видимому, эта ошибка может произойти также при вызове zip->close(), когда некоторые файлы внутри zip имеют в своем имени не-ASCII символы, такие как, например, «é».

    Потенциальное решение - обернуть имя файла, используя utf8_decode(), перед созданием целевого файла.

    Ответ 2

    В дополнение к предыдущему ответу:

    Программное обеспечение для виртуального хостинга

    Права доступа к файлам

    1. Этот пользователь владеет файлом и, возможно, родительским каталогом (особенно родительским каталогом, если вы хотите записывать файлы). В большинстве сред общего хостинга это не будет проблемой, потому что ваш пользователь должен владеть всеми файлами под вашим корневым каталогом.

    2. В Linux хорошей практикой будет использова ние chmod 600 (только владелец может читать и писать) или chmod 644 (владелец может писать, но все могут читать) .

    Ответ 3

    Samba Shares

    Если у вас есть тестовый сервер Linux и вы работаете из клиента Windows, общий ресурс Samba мешает команде chmod . Даже если вы используете:

    chmod -R 777 myfolder

    со стороны Linux вполне возможно, что Unix Group\www-data все еще не будет иметь доступ на запись. Есть рабочее решение : если ваш общий ресурс настроен так, что администраторы Windows сопоставлены с корневым каталогом – в Windows откройте разрешения, отключите наследование для вашей папки с копией, а затем предоставьте полный доступ для www-данных.

    Мы будем очень благодарны

    если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

    На самом деле, чем открыть php файл, не является большой проблемой. Бывает труднее открыть бутылку пива, когда находишься посреди леса. Но так думают лишь заядлые программисты. А для новичков поведаем обо всех возможностях php для работы с файлами:

    Файлы php

    Файлы с расширением php содержат в себе код написанный, на одноименном языке программирования. В отличие от других языков, php является серверным языком программирования. То есть он выполняется на стороне сервера. Поэтому для отладки его кода на клиентской машине должен быть установлен локальный сервер.

    Для работы с файлами php используются специальные приложения – программные редакторы. Наиболее распространенными из них являются:

    • Dreamweaver.
    • PHPEdit.
    • Eclipse PHP Development.

    Файлы php

    При создании сайтов на основе php может потребоваться многократное использование программного кода. В таких ситуациях удобно подключать уже готовые решения, находящиеся в другом файле. Для этого используется конструкция include . Ее синтаксис:

    Файлы php - 2



    Открытие и закрытие файлов

    В php все операции с файлами осуществляются в несколько этапов:

    • Открытие файла;
    • Редактирование содержимого;
    • Закрытие файла.

    Для открытия файла используется функция fopen() . Ее синтаксис:

    Открытие и закрытие файлов

    Для закрытия доступа к файлу служит функция fclose () . Синтаксис:

    int fclose (int file) , где int file – дескриптор сайта, который нужно закрыть.

    После каждого чтения или записи файл нужно закрывать этой функцией. Иначе остается открытым поток, созданный для файла. А это ведет к лишнему расходу серверных мощностей.

    Чтение и запись файлов

    Для простого отображения всего содержимого файла идеально подходит функция readfile () . Ее синтаксис:

    readfile (string filename) , где string filename – строковое имя фала ( не дескриптор ).

    Чтение и запись файлов

    Тот же самый файл можно прочитать с помощью функции fpassthru () . Она считывает данные от конечной позиции указателя и до конца файла. Ее синтаксис:

    Для работы с функцией требуется открытие и закрытие файла. Пример:

    Результат аналогичен предыдущему.

    Функции для работы с файлами в php позволяют считывать содержимое построчно и посимвольно:

    • string fgets ( int file, int length) – функция считывает строку длиною length . Пример:

    Чтение и запись файлов - 2

    • string fread (int file, int length) – по действию идентична предыдущей.

    Для записи текстовых данных в файл существует две идентичные функции:

    • int fputs ( int file, string string [, int length ])
    • int fwrite ( int file, string string [, int length ])

    Функции записывают в файл int file строку string string указанной длины int length ( необязательный аргумент ). Пример:


    Создание и удаление файлов

    Чтобы создать файл php , можно использовать функцию fopen() в режиме доступа « w » или « w+ ». Или функцию touch () . Она устанавливает время изменения файла. При отсутствии элемента с искомым именем он будет создан. Ее синтаксис:

    Для создания копии файла используется функция copy() . В качестве аргументов она принимает имя оригинала и файла, куда нужно скопировать содержимое. Если он не существует, то будет создан. Синтаксис функции:

    Создание и удаление файлов

    Удалить файл можно с помощью функции unlink() . Ее синтаксис:

    Получение информации о файле

    Для получения информации о файлах в php используется целый ряд функций:

    • bool fileexists (string filename) – проверяет, существует ли элемент;
    • int fileatime (string filename) – возвращает время последнего открытия;
    • int filesize (string filename) – возвращает байтовый размер файла;
    • string filetype (string filename) – тип файла.

    Получение информации о файле

    Это еще не все возможности для работы с файлами, реализованные в php . Многие из методов и функций остались за кадром. Так что простор для самостоятельного познания еще велик.

    Для большинства хостов Unix типично следующее, но вы можете узнать у своего хоста, можно ли использовать более строгие разрешения, позволяющие PHP выполнять запись в файлы (666) и папки (777) . На серверах Windows следующее не будет применяться, но вам необходимо убедиться, что файлы и папки доступны для записи ExpressionEngine. Возможно, вам придется связаться с вашим хостом для этого.

    Не уверен, что это значит. Я могу изменить определенные файлы и папки на 666 и 777 соответственно, где я - chown'er, но вышеупомянутое звучит так, как будто мне нужно разрешить PHP делать это тоже?

    ОРИГИНАЛЬНЫЙ ВОПРОС:

    Мне нужно убедиться, что PHP может писать в определенные файлы (666) и папки (777).

    Как мне это сделать?

    Я не уверен, какую проблему вы пытаетесь решить? Если вы можете получить доступ к каталогу, в котором находится файл, и у вас есть разрешение на выполнение, вы можете записывать в файлы и каталоги с этими разрешениями. Для большинства хостов Unix следующее типично, но вы можете узнать у своего хоста, можно ли использовать более ограничивающие разрешения, позволяющие PHP выполнять запись в файлы (666) и папки (777). Отсутствует ли кома? в противном случае эта фраза не имеет никакого смысла. Если каталог верхнего уровня не ограничен, у вас нет проблем с записью в доступные для записи файлы или каталоги. Я просто сделал копию и вставил из документации. Плюс, это причина, по которой я разместил вопрос, так как не понимаю, что означает эта цитата . Если вы видите документацию, в которой говорится, что вы используете 666 или 777 в отношении веб-файлов, вам, вероятно, следует игнорировать их, если для этого нет веских причин. Обычно это что-то, написанное кем-то, кто не мог понять, как установить правильные права доступа, и сдался и дал всем доступ для чтения или записи к файлам.

    Я дополню ответы Рахму и М.В. техническим решением. Все, что следует, действительно только для UNIX-подобных систем.

    Прокрутите раздел chmod / chown для примера, используя ACL - более мощный инструмент, чем режимы файлов UNIX.

    Поиск имени пользователя вашего веб-сервера

    Чтобы проверить это, попробуйте:

    Убедитесь, что имя пользователя, которое возвращает эта команда, является логичным (например, я использую nginx 99% времени, но эта команда возвращает tomcat7 , веб-сервер Java, который я установил один раз) .

    Предоставление разрешений веб-серверу: использование chmod и chown

    Выполнение chmod 666 или 777 (решение для такого рода проблем в плохих документациях / руководствах) может волшебным образом заставить вещи работать, но небезопасно. Предоставление разрешений 666 или 777 даст доступ к «другим». Так что не только Apache, но также grandmother и nsa (при условии, что эти учетные записи пользователей существуют на вашем компьютере - но на самом деле нет, пожалуйста, избегайте этого, если это не только для тестирования / устранения неполадок).

    Лучше быть более конкретным и дать разрешения только вам и Apache. Измените группу ваших файлов, чтобы предоставить полный контроль над вашими файлами веб-серверу. Для этого рекурсивно измените владельца:

    Но, скорее всего, вы можете сохранить полный доступ к своим файлам, изменив только группу:

    Затем сделайте все возможное, chmod чтобы дать группе www-data те же права, что и у вас. Например, если текущий режим равен 640 (6 для вас, 4 для www-данных, 0 для других, переводя на -rw-r -----) , установите его на 660 (6 для вас, 6 для www- данные, 0 для других, перевод на -rw-rw ----) . Посмотрите ответ Рахму, чтобы узнать больше о файловых режимах, это старый, но элегантный механизм.

    Чтобы избежать манипуляции с загадочными числами chmod , вы также можете использовать этот синтаксис:

    Это означает, что «для группы ( g ), добавить + ( rw ) разрешения на чтение и запись ( ) для папки your/folder/ , рекурсивно ( -R )».

    В 90% случаев этого должно быть достаточно.

    Мой предпочтительный метод: использование ACL (Access Control List)

    Иногда первого решения недостаточно. Я возьму пример Symfony Framework, который регистрирует и кэширует много данных. Так что для этого нужен доступ на запись в соответствующую папку.

    И метод chmod / chown может оказаться недостаточным, если вы параллельно используете консоль Symfony в CLI (под моей учетной записью пользователя) и в Интернете (пользователь веб-сервера). Это вызывает много проблем, потому что Symfony постоянно изменяет разрешения.

    В этом случае мы будем использовать ACL (Access Control List), который является более продвинутым способом управления разрешениями во многих системах UNIX.

    Вот команды, приведенные в официальной документации Symfony ( пожалуйста, измените app/cache и app/logs под свои нужды ):

    В системе, которая поддерживает chmod +a (т.е. не Debian / Ubuntu)

    В системе, которая не поддерживает chmod +a (чаще всего)

    Вам понадобится setfacl инструмент; возможно, он установлен в вашей системе по умолчанию, поэтому попробуйте setfacl -v проверить, доступна ли команда.

    Если команда недоступна и вы используете Ubuntu 14.04+, вам просто нужно установить инструмент:

    В противном случае следуйте документации по вашей ОС, потому что вам может потребоваться изменить способ монтирования вашего раздела ( документация по Ubuntu здесь ).

    У меня никогда не было проблем с этим методом, доволен или ваши деньги обратно.

    Рассмотрим следующий пример, в котором пользователь создал скрипт, удаляющий файл из его домашней директории. Предполагается ситуация, когда веб-интерфейс, написанный на PHP , регулярно используется для работы с файлами, и настройки безопасности позволяют удалять файлы в домашнем каталоге.

    <?php
    // Удаление файла из домашней директории пользователя
    $username = $_POST [ 'user_submitted_name' ];
    $userfile = $_POST [ 'user_submitted_filename' ];
    $homedir = "/home/ $username " ;

    unlink ( " $homedir / $userfile " );

    echo "Файл был удалён!" ;
    ?>

    Поскольку переменные вводятся в пользовательской форме, существует возможность удалить файлы, принадлежащие кому-либо другому, введя соответствующие значения. В этом случае может понадобиться авторизация. Посмотрим, что произойдёт, если будут отправлены значения "../etc/" и "passwd". Скрипт выполнит следующие действия:

    <?php
    // Удаление любого файла, доступного из 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
    // Удаление любого файла, к которому имеет доступ пользователь,
    // под которым запущен 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/" и система опять окажется уязвимой. Исходя из этого, вам может понадобиться более строгая проверка:

    <?php
    $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), и так далее. Исходя из этого, как правило, легче реализовать такую политику безопасности, в которой запрещено все, исключая то, что явно разрешено.

    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)
    <?php
    $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.

    Читайте также: