Как подняться к корню каталога с помощью php

Войны между программистами php и perl кажется давно уже позади. Даже я стал программировать на php, напрочь забыв perl. Но это не значит, что меня всё устраивает в php. Например то, что скрипты на php могут не только легко содержать куски html-разметки, но и запускаться из любой папки на сервере, я до сих пор считаю серьёзной уязвимостью, накладывающей дополнительные обязательства на программиста, пишущего код. Наверняка, можно озадачится и серверными средствами ограничить запуск php-скриптов из всех директорий, кроме выбранной, (или, по крайней мере, прописать в правах доступа к папкам запрет на исполнение с наследованием этого свойства файлами), но я пока не встречал кода, который показал бы, что этим кто-то озадачивался. Как использовать эту особенность php, я для себя решил. А в этой статье рассмотрим, как подняться по всему дереву каталогов в корневую директорию с помощью php-скрипта, который, как увидим, может спокойно лазить по всему серверу и что-то там себе в делать тихим сапом (в зависимости от развитости и извращённости фантазии программиста, его написавшего).



Основные переменные и функции php для определения папки, в которой находится программа

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

Итак, скрипт с названием delete.php (потому что после написания статьи будет удалён) лежит в папке \www\mb4.ru\templates\protostar\html\layouts\joomla\html\batch\, если рассматривать его путь от домашней директории пользователя.

В php версиях: PHP 4 >= 4.1.0, PHP 5, PHP 7 есть переменная $_SERVER, содержащая в себе массив с заголовками, путями и местоположениями скриптов. Записи в этом массиве создаются веб-сервером. Нет гарантии, что каждый веб-сервер предоставит любую информацию, но по умолчанию, рассматриваемые ниже два пути, хранящиеся в этом массиве, отдаются сервером «на ура».

  • $_SERVER['DOCUMENT_ROOT']
    • в этой переменной содержится директория корня документов, в которой выполняется текущий скрипт, в точности та, которая указана в конфигурационном файле сервера.
  • $_SERVER['SCRIPT_FILENAME']
    • в этой переменной содержится абсолютный путь к исполняемому скрипту.

Для проверки, как это работает, достаточно запустить php-скрипт, который выдаст на экран содержимое этих переменных:

<?php
echo "$_SERVER['DOCUMENT_ROOT'] . "<br>";
echo "$_SERVER['SCRIPT_FILENAME']";
?>

В результате получим нечто подобное:

/var/www/mb4/data/www/mb4.ru
/var/www/mb4/data/www/mb4.ru/templates/protostar/html/layouts/joomla/html/batch/delete.php

То есть корневую папку пользователя, под которым запущен на выполнение скрипт и ВНИМАНИЕ (!) — полный путь к исполняемому скрипту от корня дерева каталогов сервера (!). Красота ;)

В php есть ещё одна полезная функция, которой мы воспользуемся ниже для подъёма к корню файловой системы сервера, которая получает имя текущего рабочего каталога. Это функция getcwd(), работающая во всех версиях php (PHP 4, PHP 5, PHP 7).

То есть, запустив код:

<?php
echo "getcwd()";
?>

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

/var/www/mb4/data/www/mb4.ru/templates/protostar/html/layouts/joomla/html/batch

Всё тот же путь, по которому можно подняться до корня файловой системы.

Как получить список папок ветки дерева каталога, в котором лежит php-скрипт

Самый простой способ получить список папок ветки дерева каталога, в котором лежит php-скрипт, это воспользоваться  стандартной функций php preg_split(), работающей во всех версиях этого языка (PHP 4, PHP 5, PHP 7). Эта функция разбивает строку по регулярному выражению и помещает результаты разбиения в массив. В нашем случае, в качестве разделителей папок однозначно используется /, так что и думать особо не нужно, используя для вывода функцию print_r() так, подробно описано в → этой статье:

<?php
echo '<pre>';
print_r( preg_split ( '/\//', getcwd() ) );
echo '</pre>';
?>

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

Array
(
    [0] => 
    [1] => var
    [2] => www
    [3] => mb4
    [4] => data
    [5] => www
    [6] => mb4.ru
    [7] => templates
    [8] => protostar
    [9] => html
    [10] => layouts
    [11] => joomla
    [12] => html
    [13] => batch
)

Если в этот массив нужно включить и имя файла, то вместо getcwd() нужно использовать глобальную переменную $_SERVER['SCRIPT_FILENAME'].

Как подняться к корню каталога с помощью php, заходя в каждую папку

Вот тут мы и добрались до ответа на основой вопрос: «Как подняться к корню каталога с помощью php?» Для этого достаточно знать, что в операционных системах типа *nix ссылкой на предыдущую папку служит .., а в php есть функция, позволяющая менять каталог chdir(). То есть, для перехода на каталог выше, нужно указать скрипту: chdir ( '..' ). В итоге получим такой скрипт, который поднимается к корню каталога файловой системы, последовательно заходя во все встречные родительские папки:

<?php
while ( getcwd() != '/' ) {
	echo getcwd() . "<br/>";
	chdir ( '..' );
}
?>

Для того, чтобы программа не пыталась выйти за пределы операционной системы в открытый космос (всё равно не получится), в цикле while нужно указать ограничение, что дальше корня / даже не пытаться заходить: getcwd() != '/'. Иначе будет бесконечный цикл и программа будет тупо биться в конечную папку, пытаясь выйти за её пределы.

В результате наш скрипт бодро откроет все папки (и даже сможет по ним полазить, если нужно) и выдаст список того, в каких директориях он побывал:

/var/www/mb4/data/www/mb4.ru/templates/protostar/html/layouts/joomla/html/batch
/var/www/mb4/data/www/mb4.ru/templates/protostar/html/layouts/joomla/html
/var/www/mb4/data/www/mb4.ru/templates/protostar/html/layouts/joomla
/var/www/mb4/data/www/mb4.ru/templates/protostar/html/layouts
/var/www/mb4/data/www/mb4.ru/templates/protostar/html
/var/www/mb4/data/www/mb4.ru/templates/protostar
/var/www/mb4/data/www/mb4.ru/templates
/var/www/mb4/data/www/mb4.ru
/var/www/mb4/data/www
/var/www/mb4/data
/var/www/mb4
/var/www
/var

Резюме

Таким образом, разместив короткую программу на php в любое место на сервере, можно попасть в любую родительскую директорию. Что с этим делать и как можно использовать, как-нибудь в другой раз.

Напоследок полный работающий код для тестирования и дописывания этого php-скрипта. Скрипт безобидный: ничего не дописывает и не меняет на сервере, так что его можно использовать в качестве заготовки для написания более осмысленной программы, выполняющей определённые действия. ;)

<?php
echo "Текущая папка: <b>" . getcwd() . "</b><br/><br/>";
echo '<pre>';
print_r( preg_split ( '/\//', getcwd() ) );
echo '</pre>';

while ( getcwd() != '/' ) {
	echo getcwd() . "<br/>";
	chdir ( '..' );
}

echo "<br>\$_SERVER['DOCUMENT_ROOT'] = <b>" . $_SERVER['DOCUMENT_ROOT'] . "</b><br>";
echo "\$_SERVER['SCRIPT_FILENAME'] = <b>" . $_SERVER['SCRIPT_FILENAME'] . "</b>";
?>

Заберите ссылку на статью к себе, чтобы потом легко её найти!
Раз уж досюда дочитали, то может может есть желание рассказать об этом месте своим друзьям, знакомым и просто мимо проходящим?
Не надо себя сдерживать! ;)

Старт! Горячий старт на просторы интернета
Старт! Горячий старт на просторы интернета
Старт! Меню