Comments 109
полезно, в избранное. Пошел править конфиги.
ТС спасибо
особенное изображение, которое будет одновременно проходить валидацию размеров GD и исполняться php интерпретатором, будет иметь права на исполнение произвольного кода на сервере с правами php процесса.
А реально такое изображение создать? Ведь в начале каждого img идет бинарный header
зачем? Можно просто после конца gif вставить сколько надо и какой хочешь информации, вполне будет валидная картинка
А еще валиднее — EXIF! Очень семантично, валидаторастам на радость!
А что? После тела идет нужный мусор. Я так, в сове время, делал гигабайтные прозрачные гифки 1x1 пиксель ;)
если картинка обрабатывается с помощью функций PHP работы с изображениями, то вся EXIF-информация будет удалена
google://rarjpeg
перфоманс у вас тоже не возникает, однако
MVC хорошая, красивая архитектура. Но, например, тот же Шетухин (вы знаете кто это?) ругался на нее.
Далее, я не понимаю, зачем использовать index.php; php!; для отдачи просто статической картинки?
Далее, я не понимаю, зачем использовать index.php; php!; для отдачи просто статической картинки?
Да хотя бы так: RewriteRule !\.(js|gzip|gz|css|ico|gif|jpe?g|png|zip|txt|xml|htm?l|rar|exe|php|tar|bin)$ index.php [L]
А в папках с графикой запрет на выполнение чего-либо интерпретатором.
А в папках с графикой запрет на выполнение чего-либо интерпретатором.
Это не проблема nginx; это проблема тех, кто читает howto и делает по ним, вместо того, что бы прочитать документацию, которая, в основном, на русском!
проблема именно в cgi.fix_pathinfo — fpm тоже не при чём
по-мойму это проблема в недопонимание инструментов, что используют
Проблема как всегда в 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 и он был сильно специфичнее в использовании).
И вот, наконец, костылики с хрустом начали ломаться обнажая все проблемы что были скрыты все эти годы.
да, забыл добавить.
сама реализация cgi.fix_pathinfo достаточно тормозная — на каждый запрос проверяется каждая компонента пути — не скрипт ли это.
так что её стоит выключать также и по соображениям производительности.
сама реализация cgi.fix_pathinfo достаточно тормозная — на каждый запрос проверяется каждая компонента пути — не скрипт ли это.
так что её стоит выключать также и по соображениям производительности.
The WWW Common Gateway Interface Version 1.1 8 января 1996 года. PATH_INFO уже есть. Более древних упомининай не нашёл, но уже видно что дела давних дней. Очень давних.
Спасибо! Заэксплуатируем, пока не закрыли.
Что использовать вы хотите? Что закрывать?
Не будут закрывать.
Конструкции вроде /wiki/index.php/Заглавная никто не отменял, да и переход на интерпретатор по *.php тоже.
Конструкции вроде /wiki/index.php/Заглавная никто не отменял, да и переход на интерпретатор по *.php тоже.
вы мне скажите, в чем ошибка-то?
Ошибки нет, это не баг, а фича (фичи), поэтому в самом коде nginx по этому поводу, скорее всего, ничего менять не будут. Ошибка если и есть, то в конфигах отдельных конфигураций. А фичи эти вполне часто используемые (те же самые /wiki/index.php/Заглавная).
«Не будут закрывать» == «Пальцем не пошевелят по этому поводу»
«Не будут закрывать» == «Пальцем не пошевелят по этому поводу»
Я правильно понимаю, что если за nginx стоит apache, он обработает либо запрос /scripts/1px.gif/test.php либо /scripts/1px.gif и в любом случае не станет выполнять картинку как php-скрипт?
Да. Поведение nginx ровно такое, как его просил автор конфига. Все что кончается на .php выполнять там. Я не пониманию, почему это ошибка.
Как минимум по тому, что просят выполнить .../img/test.gif/.php, а он по факту выполняет .../img/test.gif как PHP.
Покажите мне debug log
Да, это действительн php меняет pathinfo, а не nginx.
тогда топикстартер просто провокатор! Который громко крикнул и убежал в кусты
=)) Ну во-первых, не в кусты, а на обед.
Во-вторых я не писал, что это уязвимость nginx. Читайте внимательно.
Ну и в третьих проблема мне кажеться в том, что оказывается в переменной $fastcgi_script_name. У лайти такого например нету.
Во-вторых я не писал, что это уязвимость nginx. Читайте внимательно.
Ну и в третьих проблема мне кажеться в том, что оказывается в переменной $fastcgi_script_name. У лайти такого например нету.
Всетаки ошибка в том, что nginx по умолчанию делает то, что ему делать не следовало бы, правит pathinfo. Как он вообще догадывается, что нужно проверить существование файла? Там четко написано — если запрос заканчивается на php. Про файлы там вообще ничего нет.
Статику вообще надо держать на отдельном server{}, где нет никаких средств исполнения. И будет счастье.
Катап решил эпично всех завоевать в этом топике!
Писал когда то по просьбе знакомого описание наиболее распространенных уязвимостей: recoilme.ru/blog/comments/237
Как ни пытался не получается ошибку воспроизвести. Всё время пишет «No input file specified.»
Ах да, у меня используются unix socket'ы
У вас точно cgi.fix_pathinfo установлена в 1?
Она у меня вообще нигде не прописана, даже в 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 поднят в виртуальной среде
Т.е. 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; уже к виртуальной машине.
А какая версия пхп и с какими ключами собрана?
Судя по 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.
5.2.11
Вот ключи:
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'
Ах да, у меня еще PHP 5.2.x
Бугога =) Капитан очевидность. Баге этой сто лет в обед.
уязвимость связки? м… э…


ещё есть аналогичный «нюанс» с путями вида httр://........./image.gif%00.php
Можно просто проверить существует ли файл и вернуть, например, 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 ...;
}
вообще тут нужно с умом подойти. в nginx есть куча способов от этой вещи отмазаться, но если у вас генерятся картинки (sic!) или что-то другое на лету, тут надо думать
Я везде использую такую конструкцию, проверяющую наличие файла:
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; }
где-то в рассылке nginx пробегало, что конструкции с if лучше избегать.
Ого, я вижу, что кусок моего конфига ушел в пост. Мелочь, а приятно :))
Что для меня всегда было загадкой, так это возможность upload'ить картинки в каталог "/scripts/".
Спасибо! Закрыл. Правда говоря трюк с php.ini почему-то не прошел. Сделал через конфиги nginx'а.
хм… топик обновлен.
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}
а чем этого мало?
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
}
а чем этого мало?
Желто.
С ужасом сейчас обнаружил, что в дефолтном php-правиле у cherokee таки есть эта уязвимость.
«Починил», добавив к выполнению *.php файлов условие File Exists :) Теперь нормально.
«Починил», добавив к выполнению *.php файлов условие File Exists :) Теперь нормально.
Немного апну тему :)
Не работает на свежей связке nginx + php-fpm, так как в конфиге php-fpm есть строчка
;security.limit_extensions = .php .php3 .php4 .php5
Которая не даст выполнить другие файлы.
Не работает на свежей связке nginx + php-fpm, так как в конфиге php-fpm есть строчка
;security.limit_extensions = .php .php3 .php4 .php5
Которая не даст выполнить другие файлы.
На всякий случай уточню, что не работает не из-за наличия вышеупомянутой строчки (";" в начале означает, что строка закомментирована), а из-за применения самого подхода с белым списком в конфиге — по умолчанию разрешено только расширение .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
Sign up to leave a comment.
Уязвимость связки PHP+nginx с кривым конфигом