Comments 109
полезно, в избранное. Пошел править конфиги.
+4
ТС спасибо
0
особенное изображение, которое будет одновременно проходить валидацию размеров GD и исполняться php интерпретатором, будет иметь права на исполнение произвольного кода на сервере с правами php процесса.
А реально такое изображение создать? Ведь в начале каждого img идет бинарный header
0
UFO just landed and posted this here
зачем? Можно просто после конца gif вставить сколько надо и какой хочешь информации, вполне будет валидная картинка
0
А еще валиднее — EXIF! Очень семантично, валидаторастам на радость!
+2
А что? После тела идет нужный мусор. Я так, в сове время, делал гигабайтные прозрачные гифки 1x1 пиксель ;)
+1
если картинка обрабатывается с помощью функций PHP работы с изображениями, то вся EXIF-информация будет удалена
+1
google://rarjpeg
0
UFO just landed and posted this here
перфоманс у вас тоже не возникает, однако
-1
UFO just landed and posted this here
MVC хорошая, красивая архитектура. Но, например, тот же Шетухин (вы знаете кто это?) ругался на нее.
Далее, я не понимаю, зачем использовать index.php; php!; для отдачи просто статической картинки?
Далее, я не понимаю, зачем использовать index.php; php!; для отдачи просто статической картинки?
-9
Да хотя бы так: RewriteRule !\.(js|gzip|gz|css|ico|gif|jpe?g|png|zip|txt|xml|htm?l|rar|exe|php|tar|bin)$ index.php [L]
А в папках с графикой запрет на выполнение чего-либо интерпретатором.
А в папках с графикой запрет на выполнение чего-либо интерпретатором.
0
Это не проблема nginx; это проблема тех, кто читает howto и делает по ним, вместо того, что бы прочитать документацию, которая, в основном, на русском!
+10
проблема именно в cgi.fix_pathinfo — fpm тоже не при чём
0
по-мойму это проблема в недопонимание инструментов, что используют
0
Проблема как всегда в php. cgi.fix_pathinfo реально сложный инструмент. PATH_INFO изначально появился для SEO-шников, чтобы были красивые урлы (как бы статические, раньше поисковики так любили), если php запускается как CGI и веб сервер не поддерживает rewrite.
Понимаете для какого это года актуально? ;-)
Фича прижилась в php, как и множество других костылей из cgi_main.c.
Также, зачем-то cgi.fix_pathinfo по умолчанию выставили в «1» — спорное решение.
Получается, в случае её использования rewrite происходит непосредственно в php, и это происходит по-умолчанию.
Понятно, что если rewrite помимо этого происходит в веб сервере, то ничего хорошего не получится.
Потом в cgi sapi появилась поддержка fastcgi. это тоже было странно — надо было уже разносить на разные sapi — в cgi и fastcgi не сильно много общего с точки зрения кода. Для эры fastcgi опция уже давно потеряла свой старый смысл и актуальность, но уже не осталось людей, которые имели полную картину происходящего.
Потом fastcgi sapi начали повсеместно использовать с nginx (изначально fastcgi использовался с IIS/zeus и он был сильно специфичнее в использовании).
И вот, наконец, костылики с хрустом начали ломаться обнажая все проблемы что были скрыты все эти годы.
Понимаете для какого это года актуально? ;-)
Фича прижилась в php, как и множество других костылей из cgi_main.c.
Также, зачем-то cgi.fix_pathinfo по умолчанию выставили в «1» — спорное решение.
Получается, в случае её использования rewrite происходит непосредственно в php, и это происходит по-умолчанию.
Понятно, что если rewrite помимо этого происходит в веб сервере, то ничего хорошего не получится.
Потом в cgi sapi появилась поддержка fastcgi. это тоже было странно — надо было уже разносить на разные sapi — в cgi и fastcgi не сильно много общего с точки зрения кода. Для эры fastcgi опция уже давно потеряла свой старый смысл и актуальность, но уже не осталось людей, которые имели полную картину происходящего.
Потом fastcgi sapi начали повсеместно использовать с nginx (изначально fastcgi использовался с IIS/zeus и он был сильно специфичнее в использовании).
И вот, наконец, костылики с хрустом начали ломаться обнажая все проблемы что были скрыты все эти годы.
+6
да, забыл добавить.
сама реализация cgi.fix_pathinfo достаточно тормозная — на каждый запрос проверяется каждая компонента пути — не скрипт ли это.
так что её стоит выключать также и по соображениям производительности.
сама реализация cgi.fix_pathinfo достаточно тормозная — на каждый запрос проверяется каждая компонента пути — не скрипт ли это.
так что её стоит выключать также и по соображениям производительности.
+4
The WWW Common Gateway Interface Version 1.1 8 января 1996 года. PATH_INFO уже есть. Более древних упомининай не нашёл, но уже видно что дела давних дней. Очень давних.
0
Спасибо! Заэксплуатируем, пока не закрыли.
-9
Что использовать вы хотите? Что закрывать?
0
Не будут закрывать.
Конструкции вроде /wiki/index.php/Заглавная никто не отменял, да и переход на интерпретатор по *.php тоже.
Конструкции вроде /wiki/index.php/Заглавная никто не отменял, да и переход на интерпретатор по *.php тоже.
0
вы мне скажите, в чем ошибка-то?
0
Ошибки нет, это не баг, а фича (фичи), поэтому в самом коде nginx по этому поводу, скорее всего, ничего менять не будут. Ошибка если и есть, то в конфигах отдельных конфигураций. А фичи эти вполне часто используемые (те же самые /wiki/index.php/Заглавная).
«Не будут закрывать» == «Пальцем не пошевелят по этому поводу»
«Не будут закрывать» == «Пальцем не пошевелят по этому поводу»
0
Я правильно понимаю, что если за nginx стоит apache, он обработает либо запрос /scripts/1px.gif/test.php либо /scripts/1px.gif и в любом случае не станет выполнять картинку как php-скрипт?
0
Да. Поведение nginx ровно такое, как его просил автор конфига. Все что кончается на .php выполнять там. Я не пониманию, почему это ошибка.
+2
Как минимум по тому, что просят выполнить .../img/test.gif/.php, а он по факту выполняет .../img/test.gif как PHP.
-1
Покажите мне debug log
+1
Да, это действительн php меняет pathinfo, а не nginx.
0
тогда топикстартер просто провокатор! Который громко крикнул и убежал в кусты
+7
=)) Ну во-первых, не в кусты, а на обед.
Во-вторых я не писал, что это уязвимость nginx. Читайте внимательно.
Ну и в третьих проблема мне кажеться в том, что оказывается в переменной $fastcgi_script_name. У лайти такого например нету.
Во-вторых я не писал, что это уязвимость nginx. Читайте внимательно.
Ну и в третьих проблема мне кажеться в том, что оказывается в переменной $fastcgi_script_name. У лайти такого например нету.
0
Всетаки ошибка в том, что nginx по умолчанию делает то, что ему делать не следовало бы, правит pathinfo. Как он вообще догадывается, что нужно проверить существование файла? Там четко написано — если запрос заканчивается на php. Про файлы там вообще ничего нет.
-1
Статику вообще надо держать на отдельном server{}, где нет никаких средств исполнения. И будет счастье.
+12
Катап решил эпично всех завоевать в этом топике!
+9
Писал когда то по просьбе знакомого описание наиболее распространенных уязвимостей: recoilme.ru/blog/comments/237
-1
Как ни пытался не получается ошибку воспроизвести. Всё время пишет «No input file specified.»
0
Ах да, у меня используются unix socket'ы
0
У вас точно cgi.fix_pathinfo установлена в 1?
0
Она у меня вообще нигде не прописана, даже в php.ini
phpinfo() эту опцию вообще не отображает. Вот конфиг:
location ~ \.php$ {
fastcgi_pass unix:/home/vz/root/201/tmp/php.sock;
fastcgi_index index.php;
fastcgi_param script_FILENAME /home/username/htdocs$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param script_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}
Unix socket поднят в виртуальной среде
phpinfo() эту опцию вообще не отображает. Вот конфиг:
location ~ \.php$ {
fastcgi_pass unix:/home/vz/root/201/tmp/php.sock;
fastcgi_index index.php;
fastcgi_param script_FILENAME /home/username/htdocs$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param script_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}
Unix socket поднят в виртуальной среде
0
Т.е. unix:/home/vz/root/201/tmp/php.sock; относится к серверу, а
fastcgi_param script_FILENAME /home/username/htdocs$fastcgi_script_name; уже к виртуальной машине.
fastcgi_param script_FILENAME /home/username/htdocs$fastcgi_script_name; уже к виртуальной машине.
0
А какая версия пхп и с какими ключами собрана?
Судя по php.net/manual/en/ini.core.php:
Available since PHP 4.3.0. PHP_INI_ALL prior to PHP 5.2.1.
Судя по php.net/manual/en/ini.core.php:
Available since PHP 4.3.0. PHP_INI_ALL prior to PHP 5.2.1.
0
5.2.11
0
Вот ключи:
Configure Command => './configure' '--with-config-file-path=/etc/php5' '--mandir=/usr/share/man' '--enable-memory-limit' '--disable-debug' '--with-regex=php' '--disable-rpath' '--disable-static' '--with-pic' '--with-layout=GNU' '--with-pear=/usr/share/php' '--enable-calendar' '--enable-sysvsem' '--enable-sysvshm' '--enable-sysvmsg' '--enable-trans-sid' '--enable-bcmath' '--with-bz2=/usr/lib' '--enable-ctype' '--without-gdbm' '--with-iconv' '--enable-exif' '--with-gettext' '--enable-mbstring' '--with-pcre-regex=/usr' '--enable-shmop' '--enable-sockets' '--with-libxml-dir=/usr/lib' '--with-zlib' '--with-zlib-dir=/usr/lib' '--with-openssl=/usr' '--enable-soap' '--enable-zip' '--with-mime-magic=' '--with-exec-dir=/usr/lib/php5/libexec' '--with-system-tzdata' '--prefix=/usr' '--without-mm' '--without-sybase-ct' '--without-mssql' '--without-sqlite' '--sysconfdir=/etc/php5' '--with-gd' '--enable-gd-native-ttf' '--with-jpeg-dir=/usr/lib' '--with-png-dir=/usr/lib' '--with-freetype-dir=/usr/lib' '--with-mhash=shared,/usr/lib' '--with-mysql=/usr/lib/mysql/lib' '--enable-shared' '--enable-fastcgi' '--with-fpm' '--with-fpm-conf=/etc/php5/php-fpm.conf' '--with-fpm-log=/var/log/php-fpm.log' '--with-fpm-pid=/var/run/php-fpm.pid' '--with-curl=/usr/lib' '--with-mcrypt=/usr/lib' '--with-libevent=shared'
Configure Command => './configure' '--with-config-file-path=/etc/php5' '--mandir=/usr/share/man' '--enable-memory-limit' '--disable-debug' '--with-regex=php' '--disable-rpath' '--disable-static' '--with-pic' '--with-layout=GNU' '--with-pear=/usr/share/php' '--enable-calendar' '--enable-sysvsem' '--enable-sysvshm' '--enable-sysvmsg' '--enable-trans-sid' '--enable-bcmath' '--with-bz2=/usr/lib' '--enable-ctype' '--without-gdbm' '--with-iconv' '--enable-exif' '--with-gettext' '--enable-mbstring' '--with-pcre-regex=/usr' '--enable-shmop' '--enable-sockets' '--with-libxml-dir=/usr/lib' '--with-zlib' '--with-zlib-dir=/usr/lib' '--with-openssl=/usr' '--enable-soap' '--enable-zip' '--with-mime-magic=' '--with-exec-dir=/usr/lib/php5/libexec' '--with-system-tzdata' '--prefix=/usr' '--without-mm' '--without-sybase-ct' '--without-mssql' '--without-sqlite' '--sysconfdir=/etc/php5' '--with-gd' '--enable-gd-native-ttf' '--with-jpeg-dir=/usr/lib' '--with-png-dir=/usr/lib' '--with-freetype-dir=/usr/lib' '--with-mhash=shared,/usr/lib' '--with-mysql=/usr/lib/mysql/lib' '--enable-shared' '--enable-fastcgi' '--with-fpm' '--with-fpm-conf=/etc/php5/php-fpm.conf' '--with-fpm-log=/var/log/php-fpm.log' '--with-fpm-pid=/var/run/php-fpm.pid' '--with-curl=/usr/lib' '--with-mcrypt=/usr/lib' '--with-libevent=shared'
0
Ах да, у меня еще PHP 5.2.x
0
0
Бугога =) Капитан очевидность. Баге этой сто лет в обед.
-9
UFO just landed and posted this here
уязвимость связки? м… э…
![](https://habrastorage.org/getpro/habr/comment_images/ffa/625/f2a/ffa625f2a6a8414f9d732f4393c5e561.gif)
![](https://habrastorage.org/getpro/habr/comment_images/ffa/625/f2a/ffa625f2a6a8414f9d732f4393c5e561.gif)
+4
ещё есть аналогичный «нюанс» с путями вида httр://........./image.gif%00.php
+2
Можно просто проверить существует ли файл и вернуть, например, 404 Not Found:
location ~ \.php$ {
try_files $uri =404;
include «fastcgi_params»;
fastcgi_pass ...;
fastcgi_param ...;
}
location ~ \.php$ {
try_files $uri =404;
include «fastcgi_params»;
fastcgi_pass ...;
fastcgi_param ...;
}
0
вообще тут нужно с умом подойти. в nginx есть куча способов от этой вещи отмазаться, но если у вас генерятся картинки (sic!) или что-то другое на лету, тут надо думать
0
Я везде использую такую конструкцию, проверяющую наличие файла:
location ~ \.php$ { if ( -f $request_filename ) { fastcgi_pass unix:/tmp/php-fpm.sock; } fastcgi_index index.php; fastcgi_param script_FILENAME /nginx/html$fastcgi_script_name; include fastcgi_params; }
0
где-то в рассылке nginx пробегало, что конструкции с if лучше избегать.
0
Ого, я вижу, что кусок моего конфига ушел в пост. Мелочь, а приятно :))
+1
Что для меня всегда было загадкой, так это возможность upload'ить картинки в каталог "/scripts/".
+1
Спасибо! Закрыл. Правда говоря трюк с php.ini почему-то не прошел. Сделал через конфиги nginx'а.
0
хм… топик обновлен.
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}
а чем этого мало?
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}
а чем этого мало?
0
Желто.
0
Сорри, отправилось раньше.
Желто.
На нормальном конфиге php НИКОГДА не должен обрабатываться в пути, куда может заливать юзер.
Это реализуется, как было описано выше, редиректом всей динамики на index.php, как вариант — наличие php-скриптов в отдельном от статики месте или location ^~ для статики.
Желто.
На нормальном конфиге php НИКОГДА не должен обрабатываться в пути, куда может заливать юзер.
Это реализуется, как было описано выше, редиректом всей динамики на index.php, как вариант — наличие php-скриптов в отдельном от статики месте или location ^~ для статики.
0
UFO just landed and posted this here
С ужасом сейчас обнаружил, что в дефолтном php-правиле у cherokee таки есть эта уязвимость.
«Починил», добавив к выполнению *.php файлов условие File Exists :) Теперь нормально.
«Починил», добавив к выполнению *.php файлов условие File Exists :) Теперь нормально.
0
Немного апну тему :)
Не работает на свежей связке nginx + php-fpm, так как в конфиге php-fpm есть строчка
;security.limit_extensions = .php .php3 .php4 .php5
Которая не даст выполнить другие файлы.
Не работает на свежей связке nginx + php-fpm, так как в конфиге php-fpm есть строчка
;security.limit_extensions = .php .php3 .php4 .php5
Которая не даст выполнить другие файлы.
0
На всякий случай уточню, что не работает не из-за наличия вышеупомянутой строчки (";" в начале означает, что строка закомментирована), а из-за применения самого подхода с белым списком в конфиге — по умолчанию разрешено только расширение .php, и чтобы снова стать уязвимым к описанному в топике, нужно ручками добавить новое расширение и перезапустить php5-fpm :)
Как это сейчас выглядит для конфига в php 5.4.23
; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5
+1
Sign up to leave a comment.
Уязвимость связки PHP+nginx с кривым конфигом