Comments 120
Самое смешное, что «знакомые расширения» апач тоже «откусывает».
phpfaq.ru/apache/blah.php.jpg — дефолтные настройки.
Поэтому рекомендуется заключать подключение PHP в контейнер
phpfaq.ru/apache/blah.php.jpg — дефолтные настройки.
Поэтому рекомендуется заключать подключение PHP в контейнер
+4
Упс, тег съелся.
В контейнер FilesMatch
<FilesMatch \.php$>
AddType application/x-httpd-php .php
</FilesMatch>
Это отобьёт Апачу охоту умничать при определении MIME-типа:
phpfaq.ru/good/blah.php.jpg
phpfaq.ru/good/blah.php
В контейнер FilesMatch
<FilesMatch \.php$>
AddType application/x-httpd-php .php
</FilesMatch>
Это отобьёт Апачу охоту умничать при определении MIME-типа:
phpfaq.ru/good/blah.php.jpg
phpfaq.ru/good/blah.php
+9
Мне понравилась формулировка «отобьёт Апачу охоту умничать...»
+3
Лучше всё же так
Чтобы уж не бояться случайного пропуска FilesMatch, без которого AddType превращается в способ выполнения каких угодно файлов как PHP скриптов, содержащих ".php" в любом месте имени.
<FilesMatch "\.php$"> SetHandler application/x-httpd-php </FilesMatch>
Чтобы уж не бояться случайного пропуска FilesMatch, без которого AddType превращается в способ выполнения каких угодно файлов как PHP скриптов, содержащих ".php" в любом месте имени.
0
Я проверяю MIME вот так.
/**
* Метод определяет MIME-тип файла.
* @todo move to class_mime
* link www.iana.org/assignments/media-types/index.html
* return
* bool false в случае, если файл не существует.
* str MIME-тип файла.
*/
static public function get_mime($filename){
if( is_file($filename) == true ){
$finfo = finfo_open(FILEINFO_MIME_TYPE, '/usr/share/file/magic.mgc');
$mimetype = finfo_file($finfo, $filename);
if( $mimetype === false )
return false;
finfo_close($finfo);
return $mimetype;
}else{
return false;
}
}
/**
* Метод определяет MIME-тип файла.
* @todo move to class_mime
* link www.iana.org/assignments/media-types/index.html
* return
* bool false в случае, если файл не существует.
* str MIME-тип файла.
*/
static public function get_mime($filename){
if( is_file($filename) == true ){
$finfo = finfo_open(FILEINFO_MIME_TYPE, '/usr/share/file/magic.mgc');
$mimetype = finfo_file($finfo, $filename);
if( $mimetype === false )
return false;
finfo_close($finfo);
return $mimetype;
}else{
return false;
}
}
-8
Есть тег source на Хабре…
+3
И как это поможет против картинки с приписанным PHP-кодом в конце файла или в метаданных?
+1
if( is_file($filename) == true )
— мощно сказано+10
Вот так же надо!
if ( (is_file($filename) == true) == true)
+31
Вообще-то is_file — это проверка аналогичная file_exists.
$filename — это абсолютный путь к файлу. Мало ли как называется переменная $filename или $path_to_file.
is_file — Возвращает TRUE, если файл существует и является обычным файлом, иначе возвращает FALSE.
$filename — это абсолютный путь к файлу. Мало ли как называется переменная $filename или $path_to_file.
is_file — Возвращает TRUE, если файл существует и является обычным файлом, иначе возвращает FALSE.
-6
спасибо кэп, только зачем bool сравнивать с bool?)
0
еще маленькая поправка — функция is_file проверяет существование файла и возможность выполнения с ним операций чтения/записи. Так же результат кешируется. Функция file_exists — просто проверяет наличие файла и, по-моему, директории.
А что значит «и является обычным файлом»? какие файлы еще бывают?
А что значит «и является обычным файлом»? какие файлы еще бывают?
0
какие файлы еще бывают?
директории, блочные и символьные устройства, возможно еще какие-то варианты есть.
0
«is_file — Возвращает TRUE, если файл существует и является обычным файлом, иначе возвращает FALSE.» — это из официальной русской документации с php.net.
Есть ещё is_link и is_dir — ссылка и директория, это ведь тоже файлы, исходя из этого контекста используется словосочетание «обычным файлом».
SILENTNUKE — причём тут моя стилистика написания кода, хочу и указываю явно сравнение с bool. Или ты типичный ХАБРАТРОЛЛЬ? Здесь идёт обсуждение конкретной темы, а мой рецепт дополнение к этой конкретной теме, к определению MIME. Или у тебя туалета дома нет и ты тут решил сходить.
Есть ещё is_link и is_dir — ссылка и директория, это ведь тоже файлы, исходя из этого контекста используется словосочетание «обычным файлом».
SILENTNUKE — причём тут моя стилистика написания кода, хочу и указываю явно сравнение с bool. Или ты типичный ХАБРАТРОЛЛЬ? Здесь идёт обсуждение конкретной темы, а мой рецепт дополнение к этой конкретной теме, к определению MIME. Или у тебя туалета дома нет и ты тут решил сходить.
-2
Не стоит так ругаться. Стилистика тут не при чём. Оператор if работает с булевыми выражениями, а is_file возвращает именно его, и поэтому дополнительное сравнение является избыточным.
Если тебе указали на ошибку, то лучше попросить объяснить, чем отругиваться.
Если тебе указали на ошибку, то лучше попросить объяснить, чем отругиваться.
0
Это не ошибка! Ну насмешил «Если тебе указали на ошибку». У меня стилистика явно указывать сравнение с boolean!
Когда ты столкнёшься с большим проектом и с «неуловимой» проблемой в коде, что я опишу ниже, ты начнёшь делать также, как и я, то есть явно сравнивать.
И если вы, никогда не работали с проектом, в котором 1 000 000 строк исполняемого PHP кода, то вам не понять мой подход явного указания сравнения.
В моём рецепте функция finfo_file($finfo, $filename) может вернуть mixed значение: строку или boolean. И в этом случае понятно, что всё что не false будет восприниматься как true,
поэтому можно записать if( !$mimetype ).
Но бывают такие функции, которые возвращают значения: true (строка, число, массив), false или null.
True, строка, число, массив — может означать, что функция отработала успешно и вернула какой-то результат.
False — будет означать то, что произошла ошибка.
Null — будет означать, что функция отработала верно, но вернула пустоту.
И с таким раскладом True/False/Null в PHP есть ряд функций, да и в собственных тоже такое бывает. И чтобы мне не заморачиваться, я выбрал именно правильный для меня подход, писать всегда явно определение true, false и null.
if( !my_function() ){
// Код, который нужно выполнить только в случае ошибки.
// Но, если функция отработала корректно и
// вернула пустой результат Null, то мы также окажемся здесь. А мне этого не нужно!
}
// Поэтому местным троллям в случае описываемой ситуации, также придётся писать явное сравнение.
if( !my_function() ){
// Код, который нужно выполнить только в случае ошибки.
}else if( my_function() == null ){
// Код, который нужно выполнить только при пустом значении.
}
// Но так как, у меня своя стилистика, богатый опыт и профессиональный подход, я пишу всегда явно.
// Теперь вы понимаете тролли? И тут тролли закричали в один голос: «Прости нас идиотов...»
if( my_function() == false ){
// Код, который нужно выполнить только в случае ошибки.
}else if( my_function() == null ){
// Код, который нужно выполнить только при пустом значении.
}
Я очень рад за местных многоуважаемых троллей и за то, что любимый PHP позволяет опускать boolean сравнение в if.
Но мне нравится, так как я пишу, потому что застрахован от таких нелепых ошибок! И не нужно отнимать моё время на пустой трёп, чтобы доказывать троллям, что они тролли.
Вместо того, чтобы обсирать мой код, лучше бы дополнили статью полезными материалами, давая какие-то решения.
Когда ты столкнёшься с большим проектом и с «неуловимой» проблемой в коде, что я опишу ниже, ты начнёшь делать также, как и я, то есть явно сравнивать.
И если вы, никогда не работали с проектом, в котором 1 000 000 строк исполняемого PHP кода, то вам не понять мой подход явного указания сравнения.
В моём рецепте функция finfo_file($finfo, $filename) может вернуть mixed значение: строку или boolean. И в этом случае понятно, что всё что не false будет восприниматься как true,
поэтому можно записать if( !$mimetype ).
Но бывают такие функции, которые возвращают значения: true (строка, число, массив), false или null.
True, строка, число, массив — может означать, что функция отработала успешно и вернула какой-то результат.
False — будет означать то, что произошла ошибка.
Null — будет означать, что функция отработала верно, но вернула пустоту.
И с таким раскладом True/False/Null в PHP есть ряд функций, да и в собственных тоже такое бывает. И чтобы мне не заморачиваться, я выбрал именно правильный для меня подход, писать всегда явно определение true, false и null.
if( !my_function() ){
// Код, который нужно выполнить только в случае ошибки.
// Но, если функция отработала корректно и
// вернула пустой результат Null, то мы также окажемся здесь. А мне этого не нужно!
}
// Поэтому местным троллям в случае описываемой ситуации, также придётся писать явное сравнение.
if( !my_function() ){
// Код, который нужно выполнить только в случае ошибки.
}else if( my_function() == null ){
// Код, который нужно выполнить только при пустом значении.
}
// Но так как, у меня своя стилистика, богатый опыт и профессиональный подход, я пишу всегда явно.
// Теперь вы понимаете тролли? И тут тролли закричали в один голос: «Прости нас идиотов...»
if( my_function() == false ){
// Код, который нужно выполнить только в случае ошибки.
}else if( my_function() == null ){
// Код, который нужно выполнить только при пустом значении.
}
Я очень рад за местных многоуважаемых троллей и за то, что любимый PHP позволяет опускать boolean сравнение в if.
Но мне нравится, так как я пишу, потому что застрахован от таких нелепых ошибок! И не нужно отнимать моё время на пустой трёп, чтобы доказывать троллям, что они тролли.
Вместо того, чтобы обсирать мой код, лучше бы дополнили статью полезными материалами, давая какие-то решения.
-3
Я очень рад за местных многоуважаемых троллей и за то, что любимый PHP позволяет опускать boolean сравнение в if.
Дело не в вашем любимом PHP. Это программирование и концепция типов данных (см. Никлаус Вирт «Алгоритмы и структуры данных»)
Но мне нравится, так как я пишу, потому что застрахован от таких нелепых ошибок! И не нужно отнимать моё время на пустой трёп, чтобы доказывать троллям, что они тролли.
Не застрахованы. Сравните смысл равенства == и эквиваленции === в вашем любимом языке. И заодно про приведение типов.
// Но так как, у меня своя стилистика, богатый опыт и профессиональный подход, я пишу всегда явно.
// Теперь вы понимаете тролли? И тут тролли закричали в один голос: «Прости нас идиотов...»
Мне вас жаль. И вашу учительницу информатики.
Не шучу. И не троллю.
Дело не в вашем любимом PHP. Это программирование и концепция типов данных (см. Никлаус Вирт «Алгоритмы и структуры данных»)
Но мне нравится, так как я пишу, потому что застрахован от таких нелепых ошибок! И не нужно отнимать моё время на пустой трёп, чтобы доказывать троллям, что они тролли.
Не застрахованы. Сравните смысл равенства == и эквиваленции === в вашем любимом языке. И заодно про приведение типов.
// Но так как, у меня своя стилистика, богатый опыт и профессиональный подход, я пишу всегда явно.
// Теперь вы понимаете тролли? И тут тролли закричали в один голос: «Прости нас идиотов...»
Мне вас жаль. И вашу учительницу информатики.
Не шучу. И не троллю.
0
Поправлюсь, пока тролли спят.
if( my_function() === false ){
// Код, который нужно выполнить только в случае ошибки.
}else if( my_function() === null ){
// Код, который нужно выполнить только при пустом значении.
}
Буду краток и откровенен.
Мне нелегко об этом писать, но правда заключается в том, что таких гениальных и талантливых людей, как Я — единицы. Нас всегда ущемляют в правах, пытаются высмеять и вытеснить, серая масса люмпенов программистов, да и просто бездарные люди. Вот и на Хабре, тот самый случай, я могу постить комментарии 1 раз в час. Ах, какое не справедливое сообщество. Ладно, пошёл себе арбуз рубану.
if( my_function() === false ){
// Код, который нужно выполнить только в случае ошибки.
}else if( my_function() === null ){
// Код, который нужно выполнить только при пустом значении.
}
Буду краток и откровенен.
Мне нелегко об этом писать, но правда заключается в том, что таких гениальных и талантливых людей, как Я — единицы. Нас всегда ущемляют в правах, пытаются высмеять и вытеснить, серая масса люмпенов программистов, да и просто бездарные люди. Вот и на Хабре, тот самый случай, я могу постить комментарии 1 раз в час. Ах, какое не справедливое сообщество. Ладно, пошёл себе арбуз рубану.
-4
британские ученые отдыхают. неделя юного кодоиспытателя на хабре.
+21
И как раз на том же Stackoverflow дали нормальный ответ — прогонять все фотографии через GD или Imagemagick.
+2
Вас, возможно, шокирует, что PHP-код можно вставить и в данные самого изображения, и тогда этот код выживет пересохранение в тот же формат?
0
Пересохранение.
-4
Обработка с помощью GD убьёт любые посторонние данные по умолчанию, а Imagemagick-у надо при конвертации об этом специально сказать. Впрочем, я не возьмусь назвать конкретные ключи, которые в этом случае надо применить — кроме EXIF-а наверняка есть ещё лазейки.
+4
UFO just landed and posted this here
UFO just landed and posted this here
php — injection
PS. Или в паре с некоторыми другими типами узвимостей.
PS. Или в паре с некоторыми другими типами узвимостей.
0
UFO just landed and posted this here
Конкретно этой ошибки у Вас может не быть, но может быть неправильная настройка сервисов администратором, может быть ошибка в стороннем ПО.
Количество различных вариаций уязвимостей ограничивается лишь фантазией злоумышленника, и то что он смог загрузить вредоносный код, пусть пока и без возможности запустить его, явно не достижение.
PS. Лучше сбить свой самолет, чем пропустить вражеский.
Количество различных вариаций уязвимостей ограничивается лишь фантазией злоумышленника, и то что он смог загрузить вредоносный код, пусть пока и без возможности запустить его, явно не достижение.
PS. Лучше сбить свой самолет, чем пропустить вражеский.
+2
Например, habrahabr.ru/post/100961/
0
ИМХО бороться таки нужно с сыростью, а не плесенью. А сырость в том, что Apache неадекватно реагирует на определенные имена файлов.
Вообще, apache — достаточно слабый способ отдавать статику, lighttpd или nginx делают это гораздо лучше. Таким образом, если отдавать статику через nginx (без настроенных обработчиков CGI), то заливка любого файла оставит систему в целости и сохранности, будь у вас там многоэтажные проверки или нет.
Хотя все же даже с nginx-ом следует проверить файл, но уже просто для удобства пользователя. Чтобы другие ваши посетители видели целую и валидную картинку. При этом можно держать градус паранойи на низком уровне, т.к. система в любом случае в безопасна.
Вообще, apache — достаточно слабый способ отдавать статику, lighttpd или nginx делают это гораздо лучше. Таким образом, если отдавать статику через nginx (без настроенных обработчиков CGI), то заливка любого файла оставит систему в целости и сохранности, будь у вас там многоэтажные проверки или нет.
Хотя все же даже с nginx-ом следует проверить файл, но уже просто для удобства пользователя. Чтобы другие ваши посетители видели целую и валидную картинку. При этом можно держать градус паранойи на низком уровне, т.к. система в любом случае в безопасна.
+9
По большой счёту решение сводится к:
Непонятно только, причём здесь описанные в посте уязвимости.
- не использовать голый AddType для задания обработчика скриптов;
- никогда не доверять user input;
- явно отключать выполнение скриптов для директорий со статикой.
Вообще, apache — достаточно слабый способ отдавать статику, lighttpd или nginx делают это гораздо лучше
Непонятно только, причём здесь описанные в посте уязвимости.
0
При том, что 99% статьи является workaround-ом против фундаментального недостатка: в папке со статикой тем или иным способом может быть выполнен PHP скрипт. Далее, основываясь на всего лишь этом одном недостатке перечислел 101 способ его проэксплуатировать и описано 202 проверки, противоборствующие этому 101 способу.
Устраните всего лишь один этот фундаментальный недостаток при помощи того же nginx — и вся статья теряет смысл.
Устраните всего лишь один этот фундаментальный недостаток при помощи того же nginx — и вся статья теряет смысл.
+1
Храню файлы с именем в виде хэша а всю информацию (имя файла, mime etc) отдельно, очень удобно.
+2
Что такое самоуверенный проект? Почему это словосочетание встречается в статье несколько раз? Где названия и адреса репозиториев этих самоуверенных проектов?
-8
UFO just landed and posted this here
промахнулся комментарием
habrahabr.ru/post/148999/#comment_5034779
habrahabr.ru/post/148999/#comment_5034779
0
если злоумышленник получил доступ на уровне системы, он и так может все сделать
Например, случаются уязвимости, дающие возможность удалять (но не создавать или изменять) произвольные файлы. (Предположим, эта уязвимость в каком-нибудь совсем другом углу сервера, не относящемся к уязвимому веб-сайту.)
Без загрузки image.php.jpg это лишь бессмысленный и беспощадный DoS, а с ним — выполнение кода.
0
А не проще ли вообще сделать доступ к картинкам через отдельный скрипт и закрыть прямой доступ к папке с ними? Тогда никто и не сможет выполнить их.
0
UFO just landed and posted this here
Ну да. Не может:
Черным по белому сказано, что при большей везучести можно выполнить все. Инъекция так делается: в изображение вставляется код и его отследить становится сложнее.
А нагрузка на сервер мизерная получается по-сравнению с пользой от такого метода.
Но не надо забывать, что по умолчанию интерпретатор PHP вызывается ещё и для расширений .phtml и .php3, а некоторые хостеры включают его и для других расширений — порой даже для .html, .js, .jpg и так далее, чтобы вставлять в статические ресурсы какой-нибудь SEO-код, или отслеживать статистику хитов.
Черным по белому сказано, что при большей везучести можно выполнить все. Инъекция так делается: в изображение вставляется код и его отследить становится сложнее.
А нагрузка на сервер мизерная получается по-сравнению с пользой от такого метода.
0
При проблемах с нагрузкой вероятнее всего вы захотите загружать картинки на отдельный сервер, где стоит nginx, отдающий только статику, без возможности выполнения скриптов. Если отдельного сервера нет-то нет и проблем с нагрузкой ;).
+1
Этот отдельный скрипт тоже частенько бывает решетом без basename().
pic.php?img=../../../etc/passwd
pic.php?img=../../../etc/passwd
0
Ну само собой, прямые руки и мысли головой никто не отменял :)
К тому же можно так:
и удалять из имени файла парные точки
К тому же можно так:
file.php?name=image&ext=jpg
и удалять из имени файла парные точки
0
Вот проблема ( ваша и OnYourLips ) как раз в том, что вы отказываетесь действовать по принципу белого списка (запрещено всё, что не разрешено) и предпочитаете действовать по принципу списка чёрного — разрешено всё, что не запрешено.
Но чёрный список заведомо дырявее белого. Всё предусмотреть невозможно. И, скажем, добраться до какого-нибудь файла с паролями можно будет и безо всяких точек.
Но чёрный список заведомо дырявее белого. Всё предусмотреть невозможно. И, скажем, добраться до какого-нибудь файла с паролями можно будет и безо всяких точек.
+3
UFO just landed and posted this here
Безопасность во многом зависит от администраторов, а не разработчиков. В вашем коде нет места php-include, но настройки сервера позволяют запустить файл в upload, включая чтение файлов движка или его конфигов. Ваш код будет идеален, но злоумышленник получит возможность, например, доступа к БД с правами вашего кода. Кстати, отчасти поэтому я советую заказчикам взять shared хостинг или нанимать админа, а не берусь настроить им vds. Разве что сильно настаивают когда занимаюсь администрированием.
0
При сохранении всегда использую ID изображения в базе и при открытии по ID делаю intval.
0
Ну, как минимум следует учитывать возможность инклюда с локального диска.
Понятно, что инклюды надо защищать отдельно, но программисты обычно не слишком заботятся о безопасности внутренних инклюдов. А проверку на open_basedir картинка пройдёт спокойно.
Опять же, sun.php.jpg оказывается куда более разрушительным. Так что не все рекомендации в статье одинаково бесполезны.
Понятно, что инклюды надо защищать отдельно, но программисты обычно не слишком заботятся о безопасности внутренних инклюдов. А проверку на open_basedir картинка пройдёт спокойно.
Опять же, sun.php.jpg оказывается куда более разрушительным. Так что не все рекомендации в статье одинаково бесполезны.
0
UFO just landed and posted this here
Я же пример привел, работающий. В самом первом комментарии к топику.
Собственно, практически любой фреймфорк запускает PHP файлы в зависимости от пользовательского ввода. Очень часто части запрошенного урла совпадают с названиями файлов/методов имеющихся классов.
А фильтрация всего этого дела остаётся на совести программиста.
Собственно, практически любой фреймфорк запускает PHP файлы в зависимости от пользовательского ввода. Очень часто части запрошенного урла совпадают с названиями файлов/методов имеющихся классов.
А фильтрация всего этого дела остаётся на совести программиста.
0
Многие из описанных вами методов уже давно обходятся при наличии интеллекта и желания.
+1
Поведайте, будем рады!
+4
это альтернативные способы, есть еще и приватные, но о них мало кто говорит. Я бы хотел дополнить, что приведенные вами примеры эффективны только при использовании их в качестве целого элемента системы, т.е. если использовать их не в комплексе, то толку от них мало.
-1
Добавлю:
в пакетах libapache2-mod-php5 и mime-support для Debian (возможно, и для Ubuntu) по умолчанию используется потенциально небезопасная конфигурация.
В /etc/mime.types для application/x-httpd-php прописаны расширения .php .phtml .pht (!!!)
При этом в /etc/apache2/mods-available/php5.conf есть строчка
беда которой в том, что она создает чувство ложной защищенности, т.к. с такими mime.types все работает и без нее.
И, вероятно, не совсем так, как вы ожидаете — как насчет файла с замечательным именем «hello.pht.en»?
Эта «черная магия» отключается дописыванием строки
все в тот же php5.conf.
в пакетах libapache2-mod-php5 и mime-support для Debian (возможно, и для Ubuntu) по умолчанию используется потенциально небезопасная конфигурация.
В /etc/mime.types для application/x-httpd-php прописаны расширения .php .phtml .pht (!!!)
При этом в /etc/apache2/mods-available/php5.conf есть строчка
<FilesMatch "\.ph(p3?|tml)$">
беда которой в том, что она создает чувство ложной защищенности, т.к. с такими mime.types все работает и без нее.
И, вероятно, не совсем так, как вы ожидаете — как насчет файла с замечательным именем «hello.pht.en»?
Эта «черная магия» отключается дописыванием строки
RemoveType .php .pht .phtml .php3 .php4 .php5
все в тот же php5.conf.
+2
Кстати в фабричных настройках Debian эта уязвимость появилась почти 10 лет назад.
archive.debian.org/debian/pool/main/m/mime-support/
mime-support_3.9-1.3.tar.gz 30-Apr-2003
archive.debian.org/debian/pool/main/a/apache/
apache_1.3.26-0woody6.diff.gz 17-Nov-2004
«Don't Add Security, Remove Insecurity»
archive.debian.org/debian/pool/main/m/mime-support/
mime-support_3.9-1.3.tar.gz 30-Apr-2003
archive.debian.org/debian/pool/main/a/apache/
apache_1.3.26-0woody6.diff.gz 17-Nov-2004
«Don't Add Security, Remove Insecurity»
0
>> В последней версии PHP, судя по моим экспериментам, $_FILES[«file»][«name»] и так возвращает только basename от переданного в HTTP-запросе значения filename; но осторожность тут лишней не будет.
Про лишнюю осторожность бред конечно, а вот до какой версии оно возвращало не basename?
Про лишнюю осторожность бред конечно, а вот до какой версии оно возвращало не basename?
0
можно ещё анализировать содержимое файла, например так:
$content = file_get_contents ( 'загруженный файл' );
if ( stristr( $content, '<?' ) OR stristr ( $content, '<%' ))
{
die();
}
-7
Отлично подходит для ситуаций, когда пару десятков пользователей в параллели будут загружать большие картинки. )
0
пример накидал самый простейший, можно оптимизировать
-2
Два правила начинающему комментатору:
1. Если эта идея прямо сейчас пришла вам в голову, то надо сначала проверить — насколько она применима в реальной жизни.
2. Если вы к этой идее не имеете вообще никакого отношения, а просто повторяете за кем-то — тем более надо сначала проверить — насколько она применима в реальной жизни. Чтобы не быть одним из миллионов разносчиков мусора.
В качестве домашнего задания попробуйте поискать эти сочетания в любой мало-мальски объемной коллекции заведомо безопасных картинок.
1. Если эта идея прямо сейчас пришла вам в голову, то надо сначала проверить — насколько она применима в реальной жизни.
2. Если вы к этой идее не имеете вообще никакого отношения, а просто повторяете за кем-то — тем более надо сначала проверить — насколько она применима в реальной жизни. Чтобы не быть одним из миллионов разносчиков мусора.
В качестве домашнего задания попробуйте поискать эти сочетания в любой мало-мальски объемной коллекции заведомо безопасных картинок.
+6
UFO just landed and posted this here
Чужие или не чужие, обязаны или не обязаны — зависит лишь от TOS.
0
Не понял, как именно поступать?
Он же никак эти данные не портит, а просто предлагает не принимать.
Сайт и не обязан принимать всё подряд.
Смысла я в такой проверке не вижу, но и никаких проблем с пользовательскими данными — тоже
Он же никак эти данные не портит, а просто предлагает не принимать.
Сайт и не обязан принимать всё подряд.
Смысла я в такой проверке не вижу, но и никаких проблем с пользовательскими данными — тоже
0
UFO just landed and posted this here
У вас все в кучу перемешалось.
Я не предлагаю делать эту тупую проверку на "<?".
Эта проверка сама по себе дурацкая и не имеет смысла.
Однако, если сайт вообще делает какую-то проверку, и отвергает какие-то пользовательские данные, то это только его, сайта, дело, и никакого «поступания с чужими данными» здесь нет.
Скажем, есть ограничение на минимальный размер заливаемых картинок. Если я не принимаю картинку размером 32х32, то никакого надругательства над пользовательскими данными я не совершаю.
А чтобы заказчики не звонили, надо просто выдавать внятные сообщения об ошибках и собирать их в отчет, выдаваемый по запросу.
А чтобы на кофейной гуще не гадать — нужно обязательно логировать весь процесс.
Я не предлагаю делать эту тупую проверку на "<?".
Эта проверка сама по себе дурацкая и не имеет смысла.
Однако, если сайт вообще делает какую-то проверку, и отвергает какие-то пользовательские данные, то это только его, сайта, дело, и никакого «поступания с чужими данными» здесь нет.
Скажем, есть ограничение на минимальный размер заливаемых картинок. Если я не принимаю картинку размером 32х32, то никакого надругательства над пользовательскими данными я не совершаю.
А чтобы заказчики не звонили, надо просто выдавать внятные сообщения об ошибках и собирать их в отчет, выдаваемый по запросу.
А чтобы на кофейной гуще не гадать — нужно обязательно логировать весь процесс.
0
Кому я что обязан на своём сайте?
0
Как раз проверял написаное в статье на своем хомяке — открыл jpg-шку с подсветкой синтаксиса php (Notepad++) и штуки три <? нашлось.
0
была уже тема на хабре.
1) отключить выполнение php в папке с хранением картинок.
2) рандомные имена и пути + расширение присваивается сервером.
1) отключить выполнение php в папке с хранением картинок.
2) рандомные имена и пути + расширение присваивается сервером.
0
UFO just landed and posted this here
UFO just landed and posted this here
рандомные пути… наверное не точно выразился… не скрипт запрета нахождения файла физически.ДОстатчно будет просто рандомного имени + расширение от сервера + запрет выполнения php в папке и достаточно.
0
>Придется отдавать скриптом, чтобы подставлять правильные имена.
Необязательно, в большинстве CMS в БД хранится этот рандомный адрес и указывается сразу в ссылке на файл.
Необязательно, в большинстве CMS в БД хранится этот рандомный адрес и указывается сразу в ссылке на файл.
0
Очень часто при загрузке картинок нужен их ресайз. Так что если он не удался по понятным причинам, то трём файл.
0
UFO just landed and posted this here
Вообще не вижу проблемы — вынести все в отдельную папку. В идеале — раздавать с отдельного домена (пусть даже поддомена) с помоью nginx.
Если хостинг совсем плохой и есть только апач то отрегистрировать все расширения, убрать возможности запуска любых скриптов и SSI для файлов в этой папке.
Если хостинг совсем плохой и есть только апач то отрегистрировать все расширения, убрать возможности запуска любых скриптов и SSI для файлов в этой папке.
+1
if (preg_match('#\<\?.*\?\>#si',file_get_contents($_FILES['bablabla']))) die('oops');
А вот уж потом move_uploaded_file. У вас же там не гигабайтные файлы загружаются?
-5
Куда грустнее, когда есть CMS (или блог, или еще какой _готовый_ софт), к нему понаустанавливали модулей — и это все надо защитить. Аудит кода устраивать не самый лучший вариант. Аудит настроек сервера — хорошо, если сервер наш, но ведь бывает и shared-хостинг, где сегодня вот так все настроено, а завтра что-то тихо ка-а-а-а-ак поменяется…
Я к тому, что порой проще (и надежнее) вспомнить про тот же cloudflare.com, чем грызть себе ногти, ругаясь на чужой код на своем сервере.
Я к тому, что порой проще (и надежнее) вспомнить про тот же cloudflare.com, чем грызть себе ногти, ругаясь на чужой код на своем сервере.
+1
Можно убрать «недопустимые» символы в имени файла. То есть сразу убираем точки (кроме одной) и слэши из имени, а потом уже проверяем расширение. Обязательное пересохрание это изврат какой то. А если ворд документы пойдут или пдф, тоже пересохранять? :)
0
Достаточно часто встречаются ситуации когда люди пользуются какой либо функцией в фреймворке для описанных вами и совсем уж очевидных проверок, а сохраняют файл собственными силами и тогда оказывается, что при проверке делается trim (к примеру) а при сохранении вы его не делаете, что позволяет загрузить изображение с именем «file.jpg » и провернуть XSS для пользователей IE.
И совсем забыли об одной еще достаточно хитрой особенности nginx — нельзя допускать загрузки картинок без имени, только с расширением (например ".jpg"), т.к.:
Имхо, считаю статью из серии К.О.
Куда более интересней вопрос — правильная загрузка/отдача любых произвольных файлов, т.к. помимо изображений все чаще есть необходимость в загрузке тех же аудио/видео/офисный и иных файлов.
И совсем забыли об одной еще достаточно хитрой особенности nginx — нельзя допускать загрузки картинок без имени, только с расширением (например ".jpg"), т.к.:
anri@AKrasichkov:~$ curl -I http://localhost/test.gif | grep Content-Type
Content-Type: image/gif
anri@AKrasichkov:~$ curl -I http://localhost/.gif | grep Content-Type
Content-Type: application/octet-stream
Имхо, считаю статью из серии К.О.
Куда более интересней вопрос — правильная загрузка/отдача любых произвольных файлов, т.к. помимо изображений все чаще есть необходимость в загрузке тех же аудио/видео/офисный и иных файлов.
+1
К слову сказать, файлов «без имени» не существует. В данном случае вы продемонстрировали файл с
именем ".jpg".
А «хитрая» особенность nginx заключается в том, что в отличии от апача заголовок «Content-Type» устанавливается по расширению и абсолютно ни на что не влияет с точки зрения обработки запроса. И при отсутствии расширения берется из директивы «default_type» с безобидным по-умолчанию значением.
именем ".jpg".
А «хитрая» особенность nginx заключается в том, что в отличии от апача заголовок «Content-Type» устанавливается по расширению и абсолютно ни на что не влияет с точки зрения обработки запроса. И при отсутствии расширения берется из директивы «default_type» с безобидным по-умолчанию значением.
0
Да, вы правы фактически имя у файла ".jpg" просто как иначе «обозвать» подобные файлы я увы не придумал, посему счел уместным употребить именно такое обозначение. Возможно, говорить «файлы без названия» было бы более корректным.
application/octet-stream безобидное? С чего бы вдруг? А как же mime-сниффинг в IE, включенный у абсолютного большинства его пользователей? Как раз по этой причине у меня обычно «default_type» и выставлен в force-download.
application/octet-stream безобидное? С чего бы вдруг? А как же mime-сниффинг в IE, включенный у абсолютного большинства его пользователей? Как раз по этой причине у меня обычно «default_type» и выставлен в force-download.
0
«default_type» не может быть выставлен в «force-download» — это делается другим заголовком.
Что касается mime-сниффинга в IE то, если мне не изменяет память, он работает только если пользователь открывает файл прямой ссылкой, а не браузер загружает по тегу на странице, и когда он работает, то какой бы «Content-Type» вы не выставили — это не поможет.
В общем же случае, если вы допускаете загрузку скриптов на ваш сервер — у вас уже проблемы, и рано или поздно кто-нибудь найдет способ это поэксплуатировать.
Что касается mime-сниффинга в IE то, если мне не изменяет память, он работает только если пользователь открывает файл прямой ссылкой, а не браузер загружает по тегу на странице, и когда он работает, то какой бы «Content-Type» вы не выставили — это не поможет.
В общем же случае, если вы допускаете загрузку скриптов на ваш сервер — у вас уже проблемы, и рано или поздно кто-нибудь найдет способ это поэксплуатировать.
0
Хм, перепроверил — а вы правы, черт побери! Видимо я последние тесты проводил или со странной сборкой IE или еще что, в любой случае склоняю шляпу, век живи — век учисью.
А с этим никто и не спорит, вопрос в другом — как максимально обезопасить свой аплоад разработчикам которые не знают на какой конкретной конфигурации будет работать их код (разработчики CMS/CMF, модулей и т.д.). Вот и приходится искать все возможные «странности» и подстраиваться под них, как в моем примере с nginx + файл только с расширением. Люди ведь извращенцы, некоторые работают и на связке IIS+PHP. С позиции разработки проекта все прозрачно — используем CDN, другой домен для статики и т.д.
В общем же случае, если вы допускаете загрузку скриптов на ваш сервер — у вас уже проблемы, и рано или поздно кто-нибудь найдет способ это поэксплуатировать.
А с этим никто и не спорит, вопрос в другом — как максимально обезопасить свой аплоад разработчикам которые не знают на какой конкретной конфигурации будет работать их код (разработчики CMS/CMF, модулей и т.д.). Вот и приходится искать все возможные «странности» и подстраиваться под них, как в моем примере с nginx + файл только с расширением. Люди ведь извращенцы, некоторые работают и на связке IIS+PHP. С позиции разработки проекта все прозрачно — используем CDN, другой домен для статики и т.д.
0
Моё предложение по защите: http://bolknote.ru/2012/08/05/~3704.
-3
Точнее, это была реализация, а идея вот: http://bolknote.ru/2012/08/02/~3703.
-2
В ISPManager не так уж просто отключить PHP для image.php.jpg
Но решение есть. Может пригодится:
1. Создаем скрипт для вставки нужных инструкций в /etc/apache2/apache2.conf:
disable-apache-php-vuln.pl
2. Делаем копию /etc/apache2/apache2.conf и запускаем
3. Перезапускаем апач.
4. Теперь добавим нужные инструкции для новых сайтов создав /usr/local/ispmgr/etc/virtualhost.templ с таким содержимым:
5. Перезапускаем ispmgr:
killall ispmgr
Почему так сложно?
Просто ispmanager не умеет по другому включать php для сайта. Только через
И я не знаю как изменить это.
Но решение есть. Может пригодится:
1. Создаем скрипт для вставки нужных инструкций в /etc/apache2/apache2.conf:
disable-apache-php-vuln.pl
#!/usr/bin/perl
use strict;
my $fn = "/etc/apache2/apache2.conf";
open(FILE, '<', $fn);
my $data = join("", <FILE>);
close(FILE);
$data =~ s|DocumentRoot\s+([^\s]+)|DocumentRoot \1
<Directory \1>
RemoveHandler .php .pht .phtml .php3 .php4 .php5
RemoveType .php .pht .phtml .php3 .php4 .php5
<FilesMatch "\\.ph(p3?\|tml)\$">
SetHandler application/x-httpd-php
</FilesMatch>
</Directory>|g;
open(FILE, '>', $fn);
print FILE $data;
close(FILE);
2. Делаем копию /etc/apache2/apache2.conf и запускаем
perl disable-apache-php-vuln.pl
3. Перезапускаем апач.
4. Теперь добавим нужные инструкции для новых сайтов создав /usr/local/ispmgr/etc/virtualhost.templ с таким содержимым:
DocumentRoot __DocumentRoot__
<Directory __DocumentRoot__>
RemoveHandler .php .pht .phtml .php3 .php4 .php5
RemoveType .php .pht .phtml .php3 .php4 .php5
<FilesMatch "\.ph(p3?|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
</Directory>
5. Перезапускаем ispmgr:
killall ispmgr
Почему так сложно?
Просто ispmanager не умеет по другому включать php для сайта. Только через
AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
И я не знаю как изменить это.
0
Прочитал статью, прочитал комменты, почесал репу. Не совсем понятно, что делает злоумышленник дальше, после того как загрузил файл с php кодом? Ведь этот файл еще надо как то выполнить.
У меня допустим аплоадятся картинки и складываются в не-www директорию, и единственное, что с ними делается это file_get_contents и echo. Есть ли в этом случае возможность выполнять код загруженной картинки?
И самое главное, статья с учетом комментариев так и не раскрыла тему защиты.
У меня допустим аплоадятся картинки и складываются в не-www директорию, и единственное, что с ними делается это file_get_contents и echo. Есть ли в этом случае возможность выполнять код загруженной картинки?
И самое главное, статья с учетом комментариев так и не раскрыла тему защиты.
0
Sign up to leave a comment.
Articles
Change theme settings
Ваш сайт тоже позволяет заливать всё подряд?