Назад | Перейти на главную страницу

Nginx, PATH_INFO и переопределение URL-адресов: мне что-то не хватает

Я переключаюсь с Apache на Nginx / fcgi, и у меня возникла небольшая проблема при попытке настроить правила перезаписи приложений.

Код обрабатывает маршруты с помощью PATH_INFO, например, example.com/foo/bar/ будет перенаправлен на example.com/index.php/foo/bar/

Я изменил конфигурацию сервера, чтобы передать PATH_INFO:

location ~ \.php$ {
      include /etc/nginx/fastcgi_params;
      fastcgi_pass   127.0.0.1:9000;
      fastcgi_index  index.php;

      fastcgi_split_path_info ^(.+\.php)(.*)$;
      fastcgi_param SCRIPT_FILENAME  /var/www/public$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
      fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
}

И обработчик перезаписи:

location / {
      root   /var/www/public;
      index  index.html index.htm index.php;

      if (!-f $request_filename) {
        rewrite ^(.*)/(.*)$ /index.php/$2 break;
      }
    }

С участием 'rewrite_log на', URL-адрес правильно маршрутизируется:

[error]: *2 open() "/var/www/public/index.php/test" failed (20: Not a directory), client: 192.168.0.254, server: example.com, request: "GET /test HTTP/1.1", host: "example.com", referrer: "http://example.com/index.php"

Однако, похоже, он ищет каталог «test». Как я могу заставить его запросить index.php, передав скрипту / test?

Что ж, у вас много проблем, во-первых, вы следуете дерьмовому руководству, которое сильно устарело. if (!-f обычно не рекомендуется, если вместо него предлагается try_files.

Во-вторых, у вас есть директивы в местоположении / контексте, которые должны быть в контексте сервера, чтобы вы могли избежать дублирования пути в переменной SCRIPT_FILENAME.

Во-вторых, вы используете флаг прерывания в своей перезаписи, это фактически означает, что он не должен повторно оценивать сопоставление местоположения. Это фактически заставляет запрос никогда не покидать местоположение / блок и вместо этого обрабатывается как запрос статического файла.

В-третьих. Посмотри на свой location ~ \.php$ {

Nginx сопоставляет местоположения с URI, и вы специально указываете Nginx обрабатывать только те URI, которые заканчиваются на .php, но если вы перепишете в index.php / test /, он не сработает.

Наконец. Вы используете PATH_INFO, в то время как должны использовать REQUEST_URI. Разница в том, что для того, чтобы PATH_INFO работал, вы должны указать Nginx передать любой запрос с .php в PHP, а затем PHP должен найти нужный файл.

Это означает, что вы разрешаете отправлять в PHP такие запросы, как example.org/uploads/image.jpg/index.php, а также разрешаете PHP выполнять файл /uploads/image.jpg. Если злонамеренный пользователь загрузил этот файл с PHP в нем, теперь на вашем сервере выполняется произвольный код. Это очень реальный эксплойт, которому я лично видел, как люди уязвимы.

Пожалуйста, прекратите использование руководств в случайном порядке, потому что 90% из них - сплошной мусор, вместо этого прочтите вики. Возможно, вам будет сложно узнать об используемом вами веб-сервере, но альтернативой является взлом вашего сервера.