Комментарии 101
это бред какой-то, сначала сохранять файл, а потом проводить его валидацию, и удалять в случаи неуспеха
что это за движок такой?
что это за движок такой?
+19
Бред здесь не в сохранении файла — это необходимость из-за safe mode и open base dir, а в других деталях:
1. Сохранение файла в папку temp, которая почему-то доступна извне.
2. Проверка файла на mime-type — нигде не видела, чтобы так делали.
3. Сохранение под начальным названием файла, отсутствие проверки на расширение и возможность запуска под этим именем.
Но автору все равно респект, все дружно проверяем свои движки!
Помню приходилось делать register shutdown при загрузке mp3.
1. Сохранение файла в папку temp, которая почему-то доступна извне.
2. Проверка файла на mime-type — нигде не видела, чтобы так делали.
3. Сохранение под начальным названием файла, отсутствие проверки на расширение и возможность запуска под этим именем.
Но автору все равно респект, все дружно проверяем свои движки!
Помню приходилось делать register shutdown при загрузке mp3.
+9
Бред здесь не в сохранении файла — это необходимость из-за safe mode и open base dir
можно в деталях, пожалуйста?
0
При загрузке файла PHP помещает его во временную папку со случайным названием файла. Если в настройках PHP задан параметр open_base_dir и временная директория не входит в предел видимости open_base_dir, то манипуляции с загруженным файлом будут запрещены.
Для работы с ним существует функция move_uploaded_file, которая сохраняет только загруженные файлы в другое место.
Название временного файла будет храниться в ключе tmp_name массива $_FILES['название_параметра_для_файла'].
При попытке, например, обратиться к нему getimagesite($_FILES['file']['tmp_name']) получим ошибку
Соответственно, файл нам сохранить все же придется.
Для работы с ним существует функция move_uploaded_file, которая сохраняет только загруженные файлы в другое место.
Название временного файла будет храниться в ключе tmp_name массива $_FILES['название_параметра_для_файла'].
При попытке, например, обратиться к нему getimagesite($_FILES['file']['tmp_name']) получим ошибку
Warning: getimagesize(): open_basedir restriction in effect. File(/tmp/phpncFYlY) is not within the allowed path(s):
Соответственно, файл нам сохранить все же придется.
0
Только сохранять его нужно вне DocumentRoot или как в вашем вебсервере это называется. Ну или хотя бы в директории, доступ к которой через веб закрыт. В худшем случае — в которой не выполняются скрипты.
+4
Вообще-то манипуляции с загруженным файлом напрямую во временной директории — это уже звоночек, что вы делаете что-то не так. Вне зависимости от значения open_base_dir, с загруженными файлами лучше работать через move_uploaded_file, эта функция для этого и создавалась.
+1
Я отвечала на комментарий beat о том, что сохранить как раз таки нужно. Только это пришло в голову, когда он написал:
Показалось, что он напрямую обращается к загруженному файлу (а может оно так и есть, знает только автор).
это бред какой-то, сначала сохранять файл, а потом проводить его валидацию, и удалять в случаи неуспеха
Показалось, что он напрямую обращается к загруженному файлу (а может оно так и есть, знает только автор).
+2
НЛО прилетело и опубликовало эту надпись здесь
Потому что для работы с загружеными файлами специально есть функция move_uploaded_file, которая делает это безопасно и является общепринятым способом. Не нужно самому копаться во временной директории, когда в языке есть функционал для нормальной работы в этом случае.
+1
если нужно проанализировать содержимое файла ДО того, как он будет помещён в окончательную директорию, этот анализ лучше делать во временной
ну или придётся перемещать его в «другую временную», а потом опять, уже на окончательное место (ну или удалять)
ну или придётся перемещать его в «другую временную», а потом опять, уже на окончательное место (ну или удалять)
+2
Не вижу проблемы в том, что у приложения есть своя временная папка или в том чтобы удалить файл, если он не прошел проверку.
-1
Не вижу проблемы в том, что у приложения есть своя временная папка или в том чтобы удалить файл, если он не прошел проверку.
Вы видно и статью-то по диагонали прочитали. Там именно происходит так: перемещают в свою папку, а потом проверяют, и если не прошёл проверку — удаляют. Точно так, как вы сказали.
Только вот в функции, которая делает проверку, нашли баг, и скрипт на этом этапе вылетает, не успев удалить файл. Упс…
А если бы мы проверяли в /tmp, а потом если надо перемещали — проблемы бы не возникло.
Ваш подход аналогичен «разрешено всё, что не запрещено». Мой — «запрещено всё, что не разрешено». Второе правильнее.
+7
Is_uploaded_file() вам в помощь.
+1
НЛО прилетело и опубликовало эту надпись здесь
На самом деле настоящая причина как раз таки в безопасности. А конкретно в инкапсуляции.
Есть система, в ней есть системные папки (например, временная), которые доступны всем. Если дать к ней доступ PHP-скриптам — это огромная дыра в безопасности (можно подменить любые чужие временные файлы).
Дальше, если в PHP настраиваем upload_tmp_dir, то это «межпроектовая» дыра (то же самое, только не на уровне всей системы, а на уровне PHP-процессов.
Есть система, в ней есть системные папки (например, временная), которые доступны всем. Если дать к ней доступ PHP-скриптам — это огромная дыра в безопасности (можно подменить любые чужие временные файлы).
Дальше, если в PHP настраиваем upload_tmp_dir, то это «межпроектовая» дыра (то же самое, только не на уровне всей системы, а на уровне PHP-процессов.
0
по-моему временна директория как раз и предназначена для хранения всякого мусора, временных файлов, или что там можно найти интересного? даже не знаю, часть пользовательских сессий, пока за ними не пришел garbage collection?
+1
Вы представляете, что будет при возможности изменения файлов сессий? Мусор, как вы говорите, на данный момент считается самой ценной целью взлома любой системы.
И еще раз, временная папка (если речь о ней) — она на всю систему, не только на PHP.
И еще раз, временная папка (если речь о ней) — она на всю систему, не только на PHP.
0
Так для чего вообще нужна системная временная директория, по-вашему?
-2
Нужна для хранения временных файлов, но это не значит, что любому процессу можно ее отдавать.
Если вы говорите об этом примере, то это всего лишь пример.
И с open_base_dir без системной временной папки — это не прокатит.
Если вам так нужна временная папка — ничего не мешает сделать ее самому на уровне конкретного web-ресурса.
Если вы говорите об этом примере, то это всего лишь пример.
И с open_base_dir без системной временной папки — это не прокатит.
Warning: tempnam(): open_basedir restriction in effect. File(/tmp) is not within the allowed path(s):
Если вам так нужна временная папка — ничего не мешает сделать ее самому на уровне конкретного web-ресурса.
-1
Но зачем? У общесистемной есть отдельные плюсы, например:
* Устаревшие сессии PHP будет подчищать сам
* Файлы, не перемещённые оттуда с помощью move_uploaded_file, он будет подчищать сам
Кстати, последнее полностью нивелирует проблему, изложенную в статье (скрипт упал до того, как удалил файл).
То есть, если бы мы с самого начала не стали тянуть каку в рот (забирать оттуда непроверенный файл), даже после падения проверки он сам удалился бы. Так что надёжнее и безопаснее — проверить в /tmp и если не нужен — не брать (т.е. «брать только то, что нужно»), чем забрать к себе, проверять и если не нужен — удалить («брать всё и потом выбрасывать»).
* Устаревшие сессии PHP будет подчищать сам
* Файлы, не перемещённые оттуда с помощью move_uploaded_file, он будет подчищать сам
Кстати, последнее полностью нивелирует проблему, изложенную в статье (скрипт упал до того, как удалил файл).
То есть, если бы мы с самого начала не стали тянуть каку в рот (забирать оттуда непроверенный файл), даже после падения проверки он сам удалился бы. Так что надёжнее и безопаснее — проверить в /tmp и если не нужен — не брать (т.е. «брать только то, что нужно»), чем забрать к себе, проверять и если не нужен — удалить («брать всё и потом выбрасывать»).
-1
Не понимаю причем тут сессии? Я не предлагаю для сессий создавать свою временную папку для каждого проекта.
Я предлагаю не давать к ней доступ из скриптов!
session_start и $_SESSION при этом будет работать.
Я предлагаю не давать к ней доступ из скриптов!
session_start и $_SESSION при этом будет работать.
-1
Так скриптам тоже бывают нужны временные файлы. Например, только что загруженные и про которые ещё неизвестно, нужны ли они и хотим ли мы их хранить.
-2
Вот скриптам и создайте временную ограниченную open_base_dir директорию.
-1
А зачем, зачем создавать ещё одну, если такая уже есть? Пусть /tmp будет в open_basedir и всё. Зачем мне отдельная временная директория?
-2
Расскажите, пожалуйста, в чем по вашему смысл директивы open_basedir, если она захватывает системные папки?
-1
Вообще, по большому счёту, никакого смысла в open_basedir нет. Это костыль, как и safe mode.
Вон, в соседней ветке обсуждают Django — там нет никакого safe mode, нет никакого open_basedir, и никто не жалуется. Тем не менее, проблем безопасности типа RCE у них прилично так меньше, поскольку исполняемый скрипт недоступен через веб и указан в конфиге сервера приложений, а не как с PHP, любой файл с подходящей маской имени и находящийся внутри дерева документов является исполняемым скриптом.
Однако, а что такого священного в системных ресурсах? Куда важнее защитить данные, а не системные директории.
Вон, в соседней ветке обсуждают Django — там нет никакого safe mode, нет никакого open_basedir, и никто не жалуется. Тем не менее, проблем безопасности типа RCE у них прилично так меньше, поскольку исполняемый скрипт недоступен через веб и указан в конфиге сервера приложений, а не как с PHP, любой файл с подходящей маской имени и находящийся внутри дерева документов является исполняемым скриптом.
Однако, а что такого священного в системных ресурсах? Куда важнее защитить данные, а не системные директории.
-2
Вообще, по большому счёту, никакого смысла в open_basedir нет. Это костыль, как и safe mode.
Вот это и стоило обсуждать. Потому что весь диалог и шел в контексте open_basedir и ваше аргументы неверны в таком случае.
А про open_basedir, как и про любую другую особенность языка смысла спорить не вижу. Она есть потому, что разработчиков на PHP в тысячи раз больше и их уровень сильно отличается от разработчиков на других языках.
Но не соглашусь, что это какой-то костыль — это обычная фишка, коих хватает в каждом языке.
Тем не менее, проблем безопасности типа RCE у них прилично так меньше, поскольку исполняемый скрипт недоступен через веб и указан в конфиге сервера приложений, а не как с PHP, любой файл с подходящей маской имени и находящийся внутри дерева документов является исполняемым скриптом.
Спорить о достоинствах этого тоже считаю глупым холиваром.
Однако, а что такого священного в системных ресурсах? Куда важнее защитить данные, а не системные директории.
Священного ничего нет, как и в данных, мы же не о религии говорим вроде? А важного много чего может быть. Не хотите — не защищайте, лично я стараюсь ограничить исполняемые скрипты только необходимыми для их работы возможностями, а не гадать — есть ли что-то важное на жестком диске сервера.
0
по-моему взломщик уже получил доступ к файлам, от он и так уже получит и всю базу, и файлы, и скрипты
0
можно подменить любые чужие временные файлы
не знаю как у вас, а я создаю там временные файлы с правами 600
давайте, подмените
0
Я вроде не говорила, что нельзя защититься от этого? Я отвечала на вопрос — почему, по-умолчанию, рекомендуется этого не делать.
Предполагается, что люди, способные осознать всю глубину проблемы — не нуждаются в советах для широкой аудитории.
По поводу ваших прав на 600, а создаете их вы средствами чего? 600 — это права доступа владельца на чтение и запись.
Дайте угадаю, кто будет владельцем при, например, запуске apache+php в обоих случаях?
Предполагается, что люди, способные осознать всю глубину проблемы — не нуждаются в советах для широкой аудитории.
По поводу ваших прав на 600, а создаете их вы средствами чего? 600 — это права доступа владельца на чтение и запись.
Дайте угадаю, кто будет владельцем при, например, запуске apache+php в обоих случаях?
0
Я знал, что последует этот вопрос.
Если apache+mod_php, то mpm_itk и скрипты каждого виртуалхоста выполняются от отдельной учётной записи. Так что не угадаете.
Кроме того, если бы на шареде все PHP исполнялись от одного пользователя, я мог бы всё равно залезть в чужие сессии.
Если apache+mod_php, то mpm_itk и скрипты каждого виртуалхоста выполняются от отдельной учётной записи. Так что не угадаете.
Кроме того, если бы на шареде все PHP исполнялись от одного пользователя, я мог бы всё равно залезть в чужие сессии.
0
Т.е. возвращаемся к первоначальному ответу — если мы осознаем проблему, мы способны от нее защититься?
0
Я понял, что вы поняли. Я хотел подчеркнуть, что если «дай угадаю» и все PHP-скрипты всех пользователей сервера выполняются от одного и того же имени, просто перемещением сессий или чего угодно вовне /tmp вы проблему не решаете никак. Потому, что всё равно это всё будет доступно интерпретатору, и соответственно, любому пользователю.
То есть, без разницы, работать ли в /tmp или где-то ещё: если сервер настроен безопасно, и в /tmp будет безопасно; если он настроен криво, куда не положи — дыра будет. А поскольку /tmp специально предназначен именно для работы с временными файлами, для этого лучше его и использовать, не изобретая велосипеды и костыли.
Кстати, сам PHP по умолчанию сессии создаёт в /tmp и с правами 600, специально проверил.
То есть, без разницы, работать ли в /tmp или где-то ещё: если сервер настроен безопасно, и в /tmp будет безопасно; если он настроен криво, куда не положи — дыра будет. А поскольку /tmp специально предназначен именно для работы с временными файлами, для этого лучше его и использовать, не изобретая велосипеды и костыли.
Кстати, сам PHP по умолчанию сессии создаёт в /tmp и с правами 600, специально проверил.
-1
Подождите, мы говорим о загруженных файлах и директиве open_base_dir так?
Никаких прав на доступ к /tmp с ней у нас нет. Если мы даем такой доступ, то нам приходится уже защищаться от другой проблемы — доступа к системной папке.
Далее, мы говорим о PHP, а не об остальных возможностях защитить наш сервер. PHP не знает, кто его запустит. Может быть разные пользователи, может быть один. Может быть безопасный http-сервер, а может быть и не очень.
PHP инкапсулированно в себе предлагает не создавать дыру в безопасности. Что тут нелогичного?
Никаких прав на доступ к /tmp с ней у нас нет. Если мы даем такой доступ, то нам приходится уже защищаться от другой проблемы — доступа к системной папке.
Далее, мы говорим о PHP, а не об остальных возможностях защитить наш сервер. PHP не знает, кто его запустит. Может быть разные пользователи, может быть один. Может быть безопасный http-сервер, а может быть и не очень.
PHP инкапсулированно в себе предлагает не создавать дыру в безопасности. Что тут нелогичного?
0
То, что подход, который вы предлагаете для «не создавания дыры в безопасности» не работает на небезопасном сервере, а на безопасном он просто не нужен.
/tmp — системная папка специально для временных файлов, в чём проблема с доступом к ней, если она специально задумана так, чтобы доступ был?
/tmp — системная папка специально для временных файлов, в чём проблема с доступом к ней, если она специально задумана так, чтобы доступ был?
0
То, что подход, который вы предлагаете для «не создавания дыры в безопасности» не работает на небезопасном сервере, а на безопасном он просто не нужен.
Во-первых, я конкретный подход не предлагала, а описывала рекомендации и возможности PHP.
Во-вторых, почему это не работает? Вы так и не объяснили вашу позицию. Вот задан у нас open_base_dir и файлы грузятся через move_uploaded_file. При выполнении скриптов от одного пользователя — какие проблемы безопасности? Может быть, я что-то упускаю, конечно?
/tmp — системная папка специально для временных файлов, в чём проблема с доступом к ней, если она специально задумана так, чтобы доступ был?
Потому что есть разные уровни доступа. Например PHP был задуман чтобы автоматизировать часть процессов, но это не значит, что пользователю web-ресурса можно запускать произвольные скрипты (например, запустить на хабре php-скрипт-фильтр, который автоматом уберет из ленты комментарии с рейтингом -500). Точно так же есть уровни доступа и на сервере: для системных процессов — одни, для разработчиков — другие, для скриптов, выполнящихся http-серверов — третие, для скриптов из crontab — четвертые.
-2
Откуда рекомендации? На php.net ничего такого нет. Я как раз пытаюсь показать, что подобные рекомендации лишены смысла, а то и вредны.
Напомню, в статье описан случай: перемещаем к себе, проверяем, если не нужен — удаляем. Но проверка падает, файл не удаляется. Если бы мы проверили до перемещения (да, доступ к /tmp должен быть разрешён, и я не понимаю, зачем его запрещать), даже при падении проверки файл был бы удалён. То есть, ваша рекомендация в данном случае принесла бы больше вреда, чем пользы.
Про уровни доступа не понял, вообще это к чему здесь? Есть некий системный ресурс, который задуман как «можно всем» (вне зависимости от уровня доступа). К чему возникла речь про выполнение произвольных скриптов и так далее — не улавливаю, это как-то за рамками темы.
Напомню, в статье описан случай: перемещаем к себе, проверяем, если не нужен — удаляем. Но проверка падает, файл не удаляется. Если бы мы проверили до перемещения (да, доступ к /tmp должен быть разрешён, и я не понимаю, зачем его запрещать), даже при падении проверки файл был бы удалён. То есть, ваша рекомендация в данном случае принесла бы больше вреда, чем пользы.
Про уровни доступа не понял, вообще это к чему здесь? Есть некий системный ресурс, который задуман как «можно всем» (вне зависимости от уровня доступа). К чему возникла речь про выполнение произвольных скриптов и так далее — не улавливаю, это как-то за рамками темы.
0
Откуда рекомендации? На php.net ничего такого нет. Я как раз пытаюсь показать, что подобные рекомендации лишены смысла, а то и вредны.
www.php.net/manual/ru/function.move-uploaded-file.php
Эта функция проверяет, является ли файл filename загруженным на сервер (переданным по протоколу HTTP POST). Если файл действительно загружен на сервер, он будет перемещён в место, указанное в аргументе destination.
Такая проверка особенно важна в том случае, если существует шанс того, что какие-либо действия, производимые над загруженным файлом, могут открыть его содержимое пользователю или даже другим пользователям системы.
Это по поводу вообще проверки — наш ли это файл загружен. Вы скажете, что есть is_uploaded_file, но это возвращает нас к обсуждению смысла open_base_dir, которое вы избегаете.
Если бы мы проверили до перемещения (да, доступ к /tmp должен быть разрешён, и я не понимаю, зачем его запрещать), даже при падении проверки файл был бы удалён.
Возможно, вы удивитесь, но загружаемый файл удаляется
www.php.net/manual/ru/features.file-upload.post-method.php
По окончанию работы скрипта, в случае, если принятый файл не был переименован или перемещен, он будет автоматически удален из временной папки.
Так что, я не понимаю о каких вредных рекомендациях вы говорите, с учетом того что open_base_dir ни в коем случае не дал бы нам доступ из web-морды к upload_tmp_dir, в отличии от вашего примера.
«можно всем»
Ну это ваше личное видение.
-2
Это по поводу вообще проверки — наш ли это файл загружен. Вы скажете, что есть is_uploaded_file
Ммм, то есть, по-вашему PHP настолько говно, что в моём массиве $_FILES может быть не мой загруженный файл?
Зачем ЭТО проверять? Всё, что в $_FILES — моё, файлы, переданные моему скрипту через POST. В is_uploaded_file тоже, таким образом, мало смысла.
Возможно, вы удивитесь, но загружаемый файл удаляется
www.php.net/manual/ru/features.file-upload.post-method.php
По окончанию работы скрипта, в случае, если принятый файл не был переименован или перемещен, он будет автоматически удален из временной папки.
Перечитайте, пожалуста, то, на что отвечали. ОБ ЭТОМ Я И ГОВОРЮ. Повторю: если я переместил файл (как вы предлагаете), а потом упала проверка, до удаления дело не дойдёт — я переместил его, и в лучшем случае он там останется лежать бесполезным мусором, а в худшем — будет ситуация как в статье. Поэтому нельзя пользоваться этим советом, совет — вредный.
Если бы я проверял файл там, куда его мне положили во временной директории, и проверка упала бы, то файл был бы автоматически удалён PHP после падения скрипта — т.к. я его не перемещал. Никакой проблемы с мусором нет. Поэтому верный совет — проверить, нужен ли нам вообще этот файл, и забирать его к себе move_uploded_file только если был нужен. И игнорировать, если не был нужен — удалится само.
Ну это ваше личное видение.
режим 0777, видно, один я вижу
0
Перечитайте, пожалуста, то, на что отвечали. ОБ ЭТОМ Я И ГОВОРЮ. Повторю: если я переместил файл (как вы предлагаете), а потом упала проверка, до удаления дело не дойдёт — я переместил его, и в лучшем случае он там останется лежать бесполезным мусором, а в худшем — будет ситуация как в статье. Поэтому нельзя пользоваться этим советом, совет — вредный.
Вы просто подгоняете ситуацию конкретно под этот пост. А мы говорим о совершенном разных вещах.
Я говорю о глобальной защите скриптов через open_basedir и, как следствие, необходимости переместить файл в место, где я смогу с ним работать (проверять и т.д.). Вы считаете, что open_basedir не нужно — это ваше право, но тема совершенно другая.
Я не предлагала переместить файл в папку доступную извне? Вроде, нет.
То, что у вас случайно получится избежать именно этой атаки ни о чем не говорит, да и получится ли?
Если бы я проверял файл там, куда его мне положили во временной директории, и проверка упала бы, то файл был бы автоматически удалён PHP после падения скрипта
Это если будет кому его еще удалять (живой GC), ведь так?
0
Вы просто подгоняете ситуацию конкретно под этот пост. А мы говорим о совершенном разных вещах.
Здрасте, я вроде бы пишу в комментарияк конкретно к этому посту. Не уходите в оффтопик ;)
Даже если файл перемещается в «другую временную директорию», недоступную через веб, он может там так и остаться (ну, опять же, при падении во время проверки). То есть, будет хотя бы занимать место, а может быть и зацеплен через уязвимость типа file inclusion. Не хотелось бы иметь в системе непонятных файлов, где угодно. Либо полученные от пользователя файлы должны быть проверены и нужны, либо они не должны оставаться в системе вообще. И да, open_basedir не поможет в данном случае никак.
Это если будет кому его еще удалять (живой GC), ведь так?
Да. Надо понимать, что он выживает чаще, чем скрипт. Упавший GC в случае с mod_php примерно равносилен упавшему процессу вебсервера, в котором выполняется интерпретатор. А скрипт обычно и убивается самим интерпретатором при различных условиях, то есть, слишком много памяти запросил, слишком долго выполняется и так далее. GC интерпретатор
Поэтому на встроенный GC рассчитывать надёжнее, чем на то, что скрипт доработает до конца.
0
(… не дописал...) GC интерпретатор не будет убивать, убивая скрипт, а наоборот, вызовет, чтобы подчистить за ним мусор.
0
Здрасте, я вроде бы пишу в комментарияк конкретно к этому посту. Не уходите в оффтопик ;)
Да. Надо понимать, что он выживает чаще, чем скрипт. Упавший GC в случае с mod_php примерно равносилен упавшему процессу вебсервера, в котором выполняется интерпретатор.
Вы пишите про вредность совета для всех случаев или конкретно как обойти эту уязвимость?
В этом посте не упадет, а в следующем может и упадет. Мы говорим об уязвимостях. Именно поэтому вы подгоняете ситуацию под этот пост. Конкретно, эту уязвимость ваш способ решит (оставим открытым кучу дыр, но ладно), а вот остальные нет.
Но слава богу у вас GC жив. Тогда можете указать upload_tmp_dir в директорию с open_basedir и будем вам счастье. Помогу, с конфигом для apache
php_admin_value open_basedir /var/www/sites/site.ru
php_admin_value upload_tmp_dir /var/www/sites/site.ru/upload
0
Если некий совет претендует на общность и хотя бы в одном случае он вредный, то — он вредный в целом, потому, что не определены границы применимости и условия. То есть, кто-нибудь непременно последует ему бездумно как раз в той ситуации, где надо было делать по-другому. Не надо таких советов.
Впрочем, если вы находите open_basedir полезным, то вариант с переназначением upload_tmp_dir действительно лучше, чем поход «скопировать и потом по результатам анализа удалять». То есть, я допустил бы такое решение, но потребовал бы аргументировать, чем именно не устраивает стандартная директория /tmp и разделение прав средствами unix. Мало ли, какие дополнительно ограничения у меня есть на /tmp, типа nodev nosuid noexec и мандатного контроля прав, которым я как администратор доверяю больше, чем php open_basedir.
Впрочем, если вы находите open_basedir полезным, то вариант с переназначением upload_tmp_dir действительно лучше, чем поход «скопировать и потом по результатам анализа удалять». То есть, я допустил бы такое решение, но потребовал бы аргументировать, чем именно не устраивает стандартная директория /tmp и разделение прав средствами unix. Мало ли, какие дополнительно ограничения у меня есть на /tmp, типа nodev nosuid noexec и мандатного контроля прав, которым я как администратор доверяю больше, чем php open_basedir.
0
1. С какой целью мне создавать себе дополнительную кучу забот, проверяя нет ли у меня дыр во всем серваке, везде ли правильные права и т.д. Это я бы попросила вас аргументировать бессмысленное увеличение прав скрипта. И про недоверие туда же — зачем мне одна степень безопасности вместо двух, если я ничего не теряю при этом.
2. Расскажите подробнее как вы откроете доступ к /tmp при помощи open_basedir и где при этом у вас лежат файлы проекта.
2. Расскажите подробнее как вы откроете доступ к /tmp при помощи open_basedir и где при этом у вас лежат файлы проекта.
-1
его запрещают для того чтоб не могли сделать LFI в tmp. Вкратце о реализации, отправляют на phpinfo evil файл с заранее увеличенным размером пока сервак ждёт файл до конца, получают имя файла в tmp, юзают LFI баг, исполняют код.
-1
Манипуляции можно проводить там же — во временной папке, но после move_uploaded_file. После чего уже класть в рабочее место чистенький и обработанный файлик (само собой удаляя его из /tmp).
0
Ну а чем это безопаснее манипуляций ДО move_uploaded_file?
0
Потому что, ДО move_uploaded_file манипуляции сделать невозможно, нет? При правильно настроенном сервере.
Более того (могу ошибаться, но мне всегда казалочь, что это так) move_uploaded_file может выполнить только тот же процесс apache/php, кто его принял и положил на диск
Более того (могу ошибаться, но мне всегда казалочь, что это так) move_uploaded_file может выполнить только тот же процесс apache/php, кто его принял и положил на диск
-1
А почему это невозможно? Возможно. При правильно настроенном сервере.
Лень проверять, но если память не изменяет, к этому файлу доступ может получить кто угодно, но на нём режимы 0600 и он существует до перемещения move_uploaded_file или до завершения скрипта (удаляется по завершении, если не был перемещён).
Лень проверять, но если память не изменяет, к этому файлу доступ может получить кто угодно, но на нём режимы 0600 и он существует до перемещения move_uploaded_file или до завершения скрипта (удаляется по завершении, если не был перемещён).
+1
Смотря какие манипуляции :-) Удалить можно. А вот изменить размер по-моему нельзя
0
Ах. Если файл нужен не весь, а будет подвергаться обработке на лету, то я не стал бы это делать in place. Вынул бы всё, что мне из него нужно, а сам он пусть удаляется.
0
1. Apache/PHP кладет файл в /tmp (понятно что она не должна быть доступна web-серверу, который может что-то запускать)
2. Делаете move_uploaded_file опять же в /tmp с каким-то именем (алгоритм которого знаете только вы — повышаем безопасность)
3. Обрабатываете как надо файл.
4. Shutdown function на всякий случай для удаления (GC по сути)
5. Перемещаете в нужное место (как вариант доступное из web-сервера, хотя в настоящее время для картинок обычно это уже не apache/php — что тоже повышает безопасность)
2. Делаете move_uploaded_file опять же в /tmp с каким-то именем (алгоритм которого знаете только вы — повышаем безопасность)
3. Обрабатываете как надо файл.
4. Shutdown function на всякий случай для удаления (GC по сути)
5. Перемещаете в нужное место (как вариант доступное из web-сервера, хотя в настоящее время для картинок обычно это уже не apache/php — что тоже повышает безопасность)
-1
честно говоря, у меня файлы даже не загружаются, если /tmp не прописан в open_basedir, сейчас вот при загрузке получаю [error] => 6 (что есть UPLOAD_ERR_NO_TMP_DIR), честно говоря никогда не задавался вопросом совместной работы директив open_basedir и upload_tmp_dir, потестирую на досуге.
Доверять MIME не стоит, но все же если хочется проверить, то он приходит в массиве $_FILES, и необходимости в getimagesize() нет
P.S. Но все же, сохранения файла, и последующая его валидация (в данном случаи самая простая, на тип файла), не должна быть реализованная так как в испытуемому движке
Доверять MIME не стоит, но все же если хочется проверить, то он приходит в массиве $_FILES, и необходимости в getimagesize() нет
P.S. Но все же, сохранения файла, и последующая его валидация (в данном случаи самая простая, на тип файла), не должна быть реализованная так как в испытуемому движке
+2
У вас проблема не в open_base_dir, а в правах записи на папку tmp.
-1
на винде? )
+2
если /tmp не прописан в open_basedir
Подумалось, что это вряд ли «винда». А по вашему «на винде» нет прав доступа записи на папку? Или production у вас тоже на «винде» (код то работать везде должен)? Тогда, извиняюсь, не знаю нюансов работы upload_file php в windows, но подозреваю, что что-то тут не чисто.
-1
в win с правами как-то попроще, да и все работало, пока не прописал только одну open_basedir
при чем здесь production?
при чем здесь production?
0
В никсах также, если папка не входит в open_basedir то ни временные файлы ни сессии php сохранять в нее не будет.
«Chroot» процесса php происходит перед запуском сессий и всего прочего, так что доступа в недозволенные папки уже не оказывается к моменту старта сессии или сохранения временного файла. sferrka что-то путает.
«Chroot» процесса php происходит перед запуском сессий и всего прочего, так что доступа в недозволенные папки уже не оказывается к моменту старта сессии или сохранения временного файла. sferrka что-то путает.
0
В никсах также, если папка не входит в open_basedir то ни временные файлы ни сессии php сохранять в нее не будет.
Description: Ubuntu 12.04.4 LTS
PHP Version => 5.5.12-2+deb.sury.org~precise+1
Apache conf
php_admin_value open_basedir /var/www/sites/
session_start();
echo $_SESSION['ddas'];
var_dump($_SESSION);
$_SESSION['ddas']=1;
var_dump(session_save_path());
file_put_contents('/tmp/1.txt','sdfds');
1array(1) { [«ddas»]=> int(1) } string(13) "/var/lib/php5"
Warning: file_put_contents(): open_basedir restriction in effect. File(/tmp/1.txt) is not within the allowed path(s): (/var/www/sites/)
Не знаю, что у вас не сохраняет.
0
вы уверены что в данном случае
php_admin_value open_basedir /var/www/sites/
обрабатывается? Попытка открыть файл вне этой директории заканчивается неудачей? Хотя возможно, в 5.5 версии изменили это поведение и ваш пример действительно работает. 0
Я изменила комментарий, с примером про сохранение и нет, я думаю так это работало всегда. У вас есть доказательства обратного?
0
Да, действительно, поправили уже давно. Но такое поведение имело место даже в 5.3 версии
+1
А вот тут вы ошибаетесь, приходящий mime в массиве $_FILES содержит лишь заголовок, предоставленный браузером и не проверяется на корректность. С помощью данной уязвимости, в бородатые годы «куллхацкеры» натворили достаточно дел, если вы понимаете о чем я.
0
да, по этому я писал что доверять mime не стоит, но файлу можно можно и заголовок подделать
0
Что значит «заголовок подделать»?
-1
Браузер при загрузке передает Content-Type файла, который затем попадает в $_FILES.
0
Ясно. В общем, в $_FILES есть два значения, которым можно доверять, не опасаясь — размер файла и временное имя. Остальные (в том числе — имя контрола, в котором был загруженный файл) — прилетают из сети и к ним нужно относиться с подозрением.
0
Совершенно верно.
Вообще, первое правило защиты — не доверять ничему, что как-либо соприкасалось с данными извне. В Ruby есть очень интересная концепция tainted, когда виртуальная машина будет автоматически помечать все переменные, которые «взаимодействовали» с пользовательскими данными, как «ненадёжные» и в таких функциях, как
Вообще, первое правило защиты — не доверять ничему, что как-либо соприкасалось с данными извне. В Ruby есть очень интересная концепция tainted, когда виртуальная машина будет автоматически помечать все переменные, которые «взаимодействовали» с пользовательскими данными, как «ненадёжные» и в таких функциях, как
exec
, можно затем заблокировать выполнение, получив tainted-переменную. 0
del, и без меня разъяснили
0
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
А еще добавили примеси, пространства имен, генераторы, имена классов по статическому псевдо-свойству «class» и многое другое. Не знаю какие вы видите скриншоты, но по работе сталкиваюсь с разными версиями PHP.
0
Движок писался до того, как 5.3 стала мейнстримом, а safe mode выпилили только в 5.4, то есть спустя лет так 5-7.
0
Такое ощущение что функция загрузки специально придумана под уязвимость
Как мне кажется — уже каждый джуниор знает что проверять надо расширение, а не mime тип, и уж точно не сохранять файл куда либо до проверки…
Как мне кажется — уже каждый джуниор знает что проверять надо расширение, а не mime тип, и уж точно не сохранять файл куда либо до проверки…
-6
$info = getimagesize('temp/'.$filename.'.'.$ext);
$tmp_ext = str_replace('image/', '', $info['mime']);
if ($ext != $tmp_ext) {
...
}
здесь тоже гениально, для JPEG файлов mime type всегда будет image/jpeg, а расширение файлов обычно .jpg, соответственно jpg файлы всегда будут переименовываться в .jpeg, зачем?
0
*.jpeg эквивалентен *.jpg, nginx и другие сервера его отлично распознают. Другой вопрос — зачем проверять на 'jpg' в коде, если там всегда будет 'jpeg'? Авторы перестраховались.
+1
Основная дыра — в запуске php.
Если её закрыть, ничего не будет.
Закрывается, например, так:
Если её закрыть, ничего не будет.
Закрывается, например, так:
<Files ~ "\..+$"> Deny from all </Files> php_flag engine 0 RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml AddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp
+24
Согласен, оптимальный вариант — выносить все скрипты за DocumentRoot, а для корня сайта отключать их выполнение. Либо если так не получается — отключать выполнение скриптов для пользовательских папок. Но увы, до сих пор многие движки грешат наследием и позволяют запускать всё и отовсюду. В этой связи особенно интересны ошибки в настройке nginx+fcgi, когда запустить на выполнение можно любой скрипт вне зависимости от его расширения (ссылка есть в статье).
+1
Но как узнать хеш, в который переименовался файл?
0
Даже не пирожное
-5
> Публиковать ли ещё статьи об уязвимостях?
Конечно публиковать, вы ещё спрашивате?
Я правильно понимаю, что генератор «бомбы» просто внедряет phpinfo() в файл из сжатых нулей?
Конечно публиковать, вы ещё спрашивате?
Я правильно понимаю, что генератор «бомбы» просто внедряет phpinfo() в файл из сжатых нулей?
0
«Бомба» прерывает «естественный» ход событий и файл bomb.php остается в каталоге для временных файлов…
0
Да, как уже сказано в топике, надо сделать две вещи:
— залить файл,
— заставить сервер выполнить залитый файл.
Для выполнения второй задачи, есть промежуточная задача: нужно знать куда именно и под каким именем залился наш файл.
В топике указан способ решения первой и промежуточной задач.
Решение второй задачи здесь не приведено, так как это, как ни странно, совсем другая задача :)
— залить файл,
— заставить сервер выполнить залитый файл.
Для выполнения второй задачи, есть промежуточная задача: нужно знать куда именно и под каким именем залился наш файл.
В топике указан способ решения первой и промежуточной задач.
Решение второй задачи здесь не приведено, так как это, как ни странно, совсем другая задача :)
0
> Публиковать ли ещё статьи об уязвимостях?
Да, только избавьтесь от «ложили».
Да, только избавьтесь от «ложили».
+5
Просто напомню, что есть habrahabr.ru/conversations/
-1
этим способом ложили
Возможно это сленг, как у каменщиков.
-1
Лично мне статья понравилась, с удовольствием почитаю ещё.
Вспомнилось, как N лет назад прикалывались над друзьями и отправляли по почте файл в 1-2 Мб.
И называли файл «Фотки.rar» или «CS_1.6.zip».
А человек его распаковать не мог, потому что места на диске не хватало.
Кстати, может кому пригодится…
>> $ext = strtolower($ext[count($ext)-1]);
$ext = strtolower(end($ext))
Что касается проверки, то она какая-то странная…
Сначала происходят операции с файлом, а потом только проверяется у него расширение.
По логике, сначала должна происходить проверка входных данных, и только затем выполняться какие-то действия.
Вспомнилось, как N лет назад прикалывались над друзьями и отправляли по почте файл в 1-2 Мб.
И называли файл «Фотки.rar» или «CS_1.6.zip».
А человек его распаковать не мог, потому что места на диске не хватало.
Кстати, может кому пригодится…
>> $ext = strtolower($ext[count($ext)-1]);
$ext = strtolower(end($ext))
Что касается проверки, то она какая-то странная…
Сначала происходят операции с файлом, а потом только проверяется у него расширение.
По логике, сначала должна происходить проверка входных данных, и только затем выполняться какие-то действия.
+1
За шутку «640 петабайт хватит для всех» отдельное спасибо! ;)
0
Зарегистрируйтесь на Хабре , чтобы оставить комментарий
Опасный getimagesize() или Zip Bomb для PHP