Nginx

Nginx、PATH_INFO 和 url 重寫:我一定遺漏了一些東西

  • October 7, 2021

我正在從 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 on ”,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提供更好的替代品)。你有很多問題:

首先location /,您在上下文中有應該在上下文中的指令server,因此您可以避免SCRIPT_FILENAME變數中的路徑重複。

其次,您break在重寫中使用標誌;這意味著它不應該重新評估位置匹配。這有效地使請求永遠不會離開location /塊,而是被視為靜態文件請求。

第三,看看您的location ~ \.php$ {: Nginx 將位置與 URI 匹配,並且您明確告訴 Nginx 僅處理以 結尾的 URI .php,但如果您重寫,index.php/test/則不會觸發。

最後,你正在使用PATH_INFO,而你應該使用REQUEST_URI。不同之處在於,要使 PATH_INFO 工作,您必須告訴 Nginx 將其中.php的任何請求傳遞給 PHP,然後 PHP 必須找到正確的文件。

這意味著您允許將請求example.org/uploads/image.jpg/index.php發送到 PHP,並且您還允許 PHP 執行該文件/uploads/image.jpg。如果惡意使用者上傳了包含 PHP 的文件,他們現在可以在您的伺服器上執行任意程式碼。這是一個非常真實的漏洞,我個人看到人們容易受到攻擊。

請停止使用隨機Google搜尋的教程,因為其中 90% 完全是垃圾,而是去閱讀wiki。實際了解您正在使用的 Web 伺服器可能會很麻煩,但另一種方法是讓您的伺服器受到損害。

引用自:https://serverfault.com/questions/223860