Веб-разработчик
0,0
рейтинг
9 февраля 2009 в 13:49

Разработка → Загрузка файлов и open_basedir: почему надо пользоваться стандартными функциями

PHP*
Казалось бы вопрос загрузки файлов на сервер обсосан до косточек, но одно недавнее событие заставило меня в этом усомниться.

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

По ссылке много букв (которые всё-таки рекомендуется прочитать), здесь же напишу кратко:
  • open_basedir ограничивает список файлов, к которым может обращаться PHP, указанным деревом директорий.
  • open_basedir может применяться независимо от того, используется защищенный режим или нет.

После включения этой настройки на наших серверах, скрипты оказались «заперты» внутри директории своего сайта (виртуального хоста). Файлы же продолжали загружаться в директорию для временных файлов, которая располагалась на другом разделе и не входила в дерево директорий сайта. Соответственно все скрипты, пытавшиеся обратиться к загруженным файлам через элемент tmp_name переменной $_FILES, терпели неудачу.

Конечно же язык PHP разрабатывают неглупые люди, поэтому действие open_basedir не распространяется на функции is_uploaded_file и move_uploaded_file, которые, собственно, и предназначены для работы с загруженными файлами.

Так в чём же тогда проблема? А проблема вот в чём: многие (действительно многие!) обращаются к загруженным файлам именно напрямую, в обход стандартных функций.

Обычно это делается в тех случаях, когда загруженный файл не предполагается хранить на сайте. Как правило это импорт прайс-листов (csv, xls), картинки, которые конвертируются перед сохранением в дереве файлов сайта. Часто $_FILES используется для проверки загруженной картинки (getimagesize) перед вызовом move_uploded_file.

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

P. S. Кто-то может сказать «нефиг так конфигурировать сервера, что скрипты перестают работать». Однако я считаю, что если настройка есть, то кто-нибудь её обязательно использует. И если ваша программа после этого перестанет работать, то камни полетят в вас. Оно вам (нам) надо?
Михаил Красильников @Mekras
карма
18,9
рейтинг 0,0
Веб-разработчик
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (33)

  • +1
    Спасибо за статью. Сталкивался с такой проблемой.
  • +1
    Спасибо за объяснения.
  • +1
    И не поспоришь. Все правильно.
  • 0
    С такой проблемой не сталкивался, но за статью спасибо. Будем знать.
  • +1
    Сталкивался с подобным, но пошли более простым путем. Сделали симлинк на нужную директорию.
    • 0
      Симлинк — это костыль для неграмотно написанной программы. Если бы разработчик использовал стандартные функции, то вам не пришлось бы делать симлинки.
  • +2
    Тема и обсосана хостинг-провайдерами, которые дают в эту директиву так же /tmp (к сессиям не относится).
    • +1
      Ответственные хостинг-провайдеры также tmp директорию делают для каждого сайта отдельно.
      • 0
        Это очень правильный подход, тогда и tmp сидит под квотами пользователя, и сессии можно туда же пихать.
        • 0
          Я считаю так: на админа надейся, но сам не плошай. В том смысле, что грамотная настройка сервера — это задача админа, которая ни в коей мере не снимает с программиста ответственности за грамотность его кода.
          • 0
            «Грамотные» программисты делают всё по книжке «PHP для чайников». Я одну такую купил года 3 назад — до сих пор волосы шевелятся, если вспоминаю тамошние примеры.

            Основная суть поста — что неправильно работают с файлами.
            • 0
              Чайникам тут, как раз, проще :)
              С загрузкой файлов на сервер я сталкиваюсь очень редко, поэтому код загрузки файлов всегда копировал из примера[^] на php.net или из своего старого кода, который копировал из примера на php.net :)
              • 0
                в сорсах проскакивало и while feof :)
  • 0
    Хорошая статья.
    Сам видел copy у товарищей. Так что будте бдительны и не делайте ошибок!
  • 0
    Учтем-учтем =)
    Спасибо
  • 0
    Познавательно. Действительно, обращался напрямую. Учту эти две функции в будущем.
  • 0
    предлагаете сначала переместить временный файл куда то себе, а потом проверить его на валидность? в корне не согласен с таким подходом ибо это налагет на скрипт еще ответственность за удаление файла.

    Имхо гораздо лучше бы прописать в спецификации к приложению пункт о том, что ему должно быть доступна такая то директория. И если потом кто-то чего то изменит, то уж простите — там сказаны требования.

    Тестов конечно никто не отменял — это ответ на вопрос вроде «А как узнать что не работает?»
    • 0
      Если программист не хочет брать на себя ответственность за то что он делает, то конечно трудно что-то Вам возразить. Это вопрос подхода и целей. Тогда можете считать, что моя заметка адресована к тем, кто принимает на себя ответственность за свои творения и, самое главное, хочет сделать свои программы лучше, надежнее, кроссплатформенней. Если это не про Вас, смело забейте на написанное и пишите список требований к среде. Я не в коей мере Вас не осуждаю, сколько людей, столько и мнений.
      • +1
        тогда Вы как программист должны отвечать за то что на сервере отключены функции для работы с залитыми файлами, отключены функции конвертирования кодировок и тд и тп — за все что можно сделать с сервером…

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

        хотите сказать что если приложение написанное под виндовс не запускается на линуксе, то это вина программиста написашего его? он ведь не предусмотрел то, что его приложение может быть запущено на линуксе
        • 0
          Сказать я хочу то, что программа, непривередливая к окружению, всегда вызывает у пользователя больше симпатий, чем программа привередливая. Ещё я хочу сказать, что есть достаточно простые пути сделать программу чуть более надёжной и отказоустойчивой. И я буду этими путями следовать, что и остальным советую.
  • –2
    спасибо, капитан.
  • 0
    Тоже в корне не согласен:

    Вариант 1: Почему не внести /tmp в open_basedir? — Ну может быть в чем-то не секурно.
    Вариант 2: Почему не задать upload_tmp_dir? внутрь папок виртуального хоста, если уж вы запираете пользователей внутри?

    Вы «проклинаете» тех, кто обращается напрямую и призываете использовать стандартные функции — то есть ваша логика такая: у нас секурный хостинг, а вы там еб… сь программируйте, как хотите. Может все же как-то лицом к пользователям стоит, или нет?
    • +1
      Попробуйте дочитать заметку до конца, она не такая уж и большая. Там есть постскриптум, где и про логику, и про лицом к пользователю.

      Собственно, использование стандартных функций для загрузки — это и есть встать лицом к пользователю. Потому что программист получает дополнительные гарантии работоспособности его программы в разных окружениях. А пользователь получает надёжную программу, которая работает везде, где её не запустить.
      • 0
        Извиняюсь перед Вами, честно говоря написал немного на эмоции. Заметку я до конца дочитал сразу, просто первым впечатлением было: «О! Кто-то прочитал про новые директивы и решил применить… :( „
        Не думаю что стоит разводить баттл из-за этого, вижу человек вы знающий то с чем имеете дело.
        Но один момент я так и не понял — почему мне нельзя дать права на временную папку, тем более что права только на чтение, тем более что права туда буду иметь только я, так как это будет внутри папок моего виртуального хостинга?
        • 0
          Права дать можно. Если Ваша разработка будет работать на сервере под Вашим контролем, то у Вас полная свобода действий. Чего нельзя сказать если речь идёт о разработке, которая будет работать неизвестно где (например о библиотеке, или просто продукте, который предназначен для широкого круга пользователей). В этом случае хрен его знает, как будет настроен сервер. Не используя прямой доступ, Вы можете гарантировать работу программы независимо от расположения директории для загрузки файлов и установки open_basedir.
      • –1
        какая она надежная простите ?:)

        я допустим как админ просто возьму и закрою вам доступ ВЕЗДЕ на запись — и попробуйте вы написать софт который будет загружать файлы. он должен быть в разных окружениях ведь…

        каждый софт требует соблюдения каких либо условий для его работы
        • 0
          Она надёжнее программы, написанной без учёта того, как работает PHP.

          Совершенство недостижимо, но это не значит, что к нему не надо стремиться.
  • 0
    отоно как :), а я просто включал временную директорию в open_basedir :)
  • 0
    move_uploaded_file хороша тем, что убирает мусор из темповой папки
  • 0
    Я, обычно, при конфигурации сервера, делаю у полльзователя еще и tmp директорию (как раз для таких случаев)
    • 0
      Если Вы дочитали до конца (включая постскриптум), то должны понимать, что речь идёт не о настройке сервера, а написании программ. Ведь только в очень малом количестве случаев программист имеет возможность влиять на настройку сервера, где работает написанная им программа.
      • 0
        Я то дочитал, но высказал свое мнение со стороны администратора сервера. То есть писать программы которые будут работать на большем количестве железа — конечно надо, но и от администратора требуется чтоб на его «машине» работало как можно больше программ (скриптов) не жертвуя безопасностью.
        • 0
          Это бесспорно, это очень хорошо, что Вы так конфигурируете сервера. Просто в контексте заметки это можно воспринять как альтернативное решение проблемы, что с моей точки зрения неверно. :-)

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