IIS CGI HTTP_PROXY 標頭要求可能被重新導向

徵狀

當您使用 IIS 通用閘道介面 (CGI) 功能主控可執行程式時,其會使用特定程式庫以重新導向要求,但這些要求可能會因為 "PROXY" 要求標頭的存在而被導向不正確位置。目前已知有數個 Web 應用程式平台使用此程式庫,包括 PHP、Python 和 Go 等等。

發生的原因

CGI 是一種介面,可讓 Web 伺服器主控以可執行處理序形式執行的應用程式。當 Web 伺服器收到要求時,伺服器會啟動新的處理序,以處理該單一要求。要求完成後,該處理序便會結束。為了讓該處理序能夠存取要求資料,會將要求標頭納入為環境變數,並在名稱前面加上 "HTTP_"。因此,對於包含名為 “Proxy” 標頭的要求,其 CGI 處理序的 “HTTP_PROXY” 環境變數值會和要求標頭的值相同。

cURL 命令列和程式庫通常是用來使各種應用程式,對各種伺服器 (包括 Web 伺服器) 提出要求。您可使用命令列參數來設定此程式庫,或是從主機處理序環境變數讀取該程式庫的組態參數。"HTTP_PROXY" 是 cURL 所使用的許多組態參數其中一種。cURL 會使用 "HTTP_PROXY" 經由設定的 Proxy 傳送 HTTP 要求。

注意:這與以用戶端要求標頭呈現的 "HTTP_PROXY" 無關。

當 cURL 在 CGI 處理序中主控時,該處理序會包含名為 "HTTP_PROXY" 的環境變數,cURL 會使用其值透過 HTTP Proxy 傳送要求的資料,該值則是在環境變數中指定的。因為 cURL 預期 "HTTP_PROXY" 是組態指示詞,且不是用戶端要求標頭,所以才會發生此情形。

其他可行方案

若要解決此問題,請勿在執行 IIS 的伺服器上使用 CGI。CGI 是一種幾乎淘汰的介面,且已替換成更新且與效能更相關的介面。具體來說,PHP、Python 和 Go 應透過 FastCGI 裝載在 IIS 上。FastCGI 不會針對用戶端要求標頭使用環境變數,而且也無此問題。但如果是 PHP,則部分應用程式可能會使用 PHP getenv() 函數來擷取環境變數。即使沒有在 CGI 處理序中主控 PHP,PHP 也會將要求標頭值注入其 getenv() 函數可取得的資料集,藉此複製該 CGI 行為。如果您使用的 PHP 應用程式會以此方法擷取 HTTP_PROXY,則以下使用 PROXY 標頭清除標頭值或拒絕要求的防護措施可有效作用。

如果您基於某些原因必須使用 CGI,則可以封鎖含有名為 "Proxy" 要求標頭的要求,或是清除標頭值。這是因為 "Proxy" 並非標準要求標頭名稱,而且瀏覽器通常不會傳送它。

若要封鎖含有 Proxy 標頭的要求 (慣用的解決方案),請執行以下命令列:
appcmd set config /section:requestfiltering /+requestlimits.headerLimits.[header='proxy',sizelimit='0']

注意:appcmd.exe 通常不在路徑中,而是會在 %systemroot%\system32\inetsrv 目錄中找到。

若要清除標頭值,可以使用以下的 URL 重寫規則:
<system.webServer>
<rewrite>
<rules>
<rule name="Erase HTTP_PROXY" patternSyntax="Wildcard">
<match url="*.*" />
<serverVariables>
<set name="HTTP_PROXY" value="" />
</serverVariables>
<action type="None" />
</rule>
</rules>
</rewrite>
</system.webServer>

注意:此 URL 重寫規則是可下載至 IIS 的增益集,且未包含在預設的 IIS 安裝中。
內容

文章識別碼:3179800 - 最後檢閱時間:2016年8月2日 - 修訂: 1

意見反應