Nginx 是為世界上三分之一的網站提供的 Web 服務器。檢測眾包已檢測到一些常見的 Nginx 錯誤配置,如果不加檢查,則會使您的網站容易受到攻擊。下面介紹如何在攻擊者利用它們之前找到一些最常見的錯誤配置。
更新:檢測安全顧問弗朗斯·羅森(Frans Rosen)發表了一些研究,深入探討了他在帖子中關於檢測實驗室的一些新穎的 Web 服務器錯誤配置:中間件、無處不在的中間件 - 以及許多用於修復的配置錯誤
Nginx 是互聯網上最常用的 Web 服務器之一,因為它重量輕、模塊化且具有用戶友好的配置格式。在檢測時,我們為成千上萬的客戶掃描 Nginx 中的配置錯誤和安全漏洞。我們的眾包網絡定期提交影響 Nginx 的新且有趣的漏洞,然后我們將這些漏洞作為安全測試實施到我們的 Web 應用掃描儀中。
我們分析了從 GitHub 下載的近 50,000 個獨特的 Nginx 配置文件與谷歌 BigQuery。有了這些數據,我們可以找出不同的配置錯誤有多常見。
本文將揭示以下 Nginx 配置錯誤:
-
Missing root location
-
Unsafe variable use
-
Raw backend response reading
-
merge_slashes set to off
缺少根位置;
server {
root /etc/nginx;
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
根指令指定了 Nginx 的根文件夾。在上述示例中,根文件夾是/等/nginx,這意味着我們可以到達該文件夾內的文件。上述配置沒有位置/(位置/{...),僅用於/你好.txt。因此,根指令將在全球范圍內設置,這意味着請求/將帶您到本地路徑/等/nginx。
像GET /nginx.conf一樣簡單的請求將揭示存儲在/等/nginx/nginx.com 中的 Nginx配置文件的內容。如果根被設置為/等, GET請求/nginx/nginx.com將顯示配置文件。在某些情況下,可以訪問其他配置文件、訪問日志,甚至加密憑據以進行 HTTP 基本身份驗證。
在我們收集的近 50,000 個 Nginx 配置文件中,最常見的根路徑如下:
Off-By-Slash
server {
listen 80 default_server;
server_name _;
location /static {
alias /usr/share/nginx/static/;
}
location /api {
proxy_pass http://apiserver/v1/;
}
}
由於Off-By-Slash錯誤,由於缺少斜線,可以沿着路徑前進一步。奧蘭治蔡使這項技術眾所周知,在他的黑帽談話"打破帕瑟邏輯! 在這次談話中,他展示了位置指令中缺少的尾隨斜線與別名指令如何能夠讀取 Web 應用程序的源代碼。鮮為人知的是,這也適用於其他指令,如proxy_pass。讓我們細分正在發生的事情以及為什么這行得通。
location /api {
proxy_pass http://apiserver/v1/;
}
Nginx 服務器運行以下可在服務器上訪問的配置,因此可能假定只能訪問http://apiserver/v1/下的路徑。
http://server/api/user -> http://apiserver/v1//user
請求http://server/api/user時,Nginx 將首先使 URL 正常化。然后,它會查看前綴/api是否與 URL 匹配,在這種情況下,它確實符合 URL。然后從 URL 中刪除前綴,以便留下路徑/用戶。然后將此路徑添加到proxy_pass URL 中,從而產生最終的 URL http://apiserver/v1//user。請注意,URL 中有雙斜線,因為位置指令不會以斜線結束,而proxy_pass URL 路徑以斜線結束。大多數網絡服務器都會將http://apiserver/v1//user正常化到http://apiserver/v1/user,這意味着即使配置錯誤,一切都將如預期的那樣工作,而且可能會被忽視。
這種配置錯誤可以通過請求http://server/api../來利用,這將導致Nginx請求將URL http://apiserver/v1/../規范化為http://apiserver/。 這可以產生的影響取決於當利用此錯誤配置時可以達到什么效果。例如,它可能導致 Apache 服務器狀態暴露在 URL http://server/api../server-status中,或者它可能使無法公開訪問的路徑變得可訪問。
Nginx 服務器存在此錯誤配置的一個跡象是,當刪除 URL 中的斜線時,服務器仍然返回相同的響應。例如,如果兩者都http://server/api/user並返回相同的響應,則服務器可能很脆弱。這將導致發送以下請求:http://server/apiuser
http://server/api/user -> http://apiserver/v1//user
http://server/apiuser -> http://apiserver/v1/user
不安全的可變使用
某些框架、腳本和 Nginx 配置不安全地使用 Nginx 存儲的變量。這可能導致諸如 XSS、繞過 HttpOn 保護、信息披露,在某些情況下甚至 RCE 等問題。
SCRIPT_NAME
配置如下:
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
主要問題是,Nginx 將向 PHP 翻譯發送任何 URL,以.php結束,即使光盤上不存在文件。這是許多Nginx配置中常見的錯誤,如Nginx創建的"陷阱和常見錯誤"文檔中所概述的那樣。
如果 PHP 腳本嘗試根據SCRIPT_NAME定義基本 URL,則將發生XSS;
<?php
if(basename($_SERVER['SCRIPT_NAME']) ==
basename($_SERVER['SCRIPT_FILENAME']))
echo dirname($_SERVER['SCRIPT_NAME']);
?>
GET /index.php/<script>alert(1)</script>/index.php
SCRIPT_NAME = /index.php/<script>alert(1)</script>/index.php
使用$uri可導致 CRLF 注射
與Nginx變量相關的另一個錯誤配置是使用$uri或$document_uri,而不是$request_uri。$uri和$document_uri包含規范化的 URI,而 Nginx 中的規范化包括 URL 解碼 URI。 Volema發現,在 Nginx 配置中創建重定向時,通常使用$uri,從而導致 CRLF 注射。
易受攻擊的Nginx配置的一個例子是:
location / {
return 302 https://example.com$uri;
}
HTTP 請求的新行字符為\r(運輸返回)和\n(線路饋送)。URL編碼新的行字符導致以下表示字符%0d%0a。當這些字符包含在http://localhost/%0d%0aDetectify:%20clrf到配置錯誤的服務器的請求中時,服務器將使用名為"檢測"的新標題進行響應,因為$uri變量包含 URL 解碼的新行字符。
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf
了解更多關於 CRLF 注射的風險和反應分裂在https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/。
任何變量
在某些情況下,用戶提供的數據可以被視為 Nginx 變量。目前還不清楚為什么會發生這種情況,但這不是那么罕見或容易測試,因為在這個H1報告中看到。如果我們搜索錯誤消息,我們可以看到它被發現在SSI過濾器模塊,從而揭示這是由於SSI。
測試此值的一種方法是設置引用器標題值:
$ curl -H 'Referer: bar' http://localhost/foo$http_referer | grep 'foobar'
我們掃描了此錯誤配置,並發現了幾個用戶可以打印 Nginx 變量值的實例。已發現的脆弱實例數量已經減少,這可能表明這是修補的。
原始后端響應讀數
隨着Nginx的proxy_pass,有可能攔截由后端創建的錯誤和HTTP頭。這是非常有用的,如果你想隱藏內部錯誤消息和標題,所以他們反而由Nginx處理。Nginx 將自動提供自定義錯誤頁面,如果后端答案與一個。但是, 如果 Nginx 不明白這是 Http 的反應呢?
如果客戶向 Nginx 發送無效的 HTTP 請求,該請求將按照原樣轉發到后端,后端將對其原始內容進行回答。然后,Nginx 不會理解無效的 HTTP 響應,只需將其轉發給客戶端。想象一下這樣的 uwsgi 應用程序:
def application(environ, start_response):
start_response('500 Error', [('Content-Type',
'text/html'),('Secret-Header','secret-info')])
return [b"Secret info, should not be visible!"]
並在 Nginx 中提供以下指令:
http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
如果后端的響應狀態大於 300,則proxy_intercept_errors將提供自定義響應。在上面的 uWSGI 應用程序中,我們將發送一個500 錯誤,該錯誤將被 Nginx 截獲。
proxy_hide_header幾乎是自我解釋的:它將向客戶端隱藏任何指定的HTTP標頭。
如果我們發送一個正常的GET請求,Nginx 將返回:
HTTP/1.1 500 Internal Server Error
Server: nginx/1.10.3
Content-Type: text/html
Content-Length: 34
Connection: close
但是,如果我們發送無效的 HTTP 請求,例如:
GET /? XTTP/1.1
Host: 127.0.0.1
Connection: close
我們將獲得以下響應:
XTTP/1.1 500 Error
Content-Type: text/html
Secret-Header: secret-info
Secret info, should not be visible!
merge_slashes出發了
默認情況下,merge_slashes指令設置為"開啟",這是將兩個或多個向前斜線壓縮成一個的機制,因此///將成為/。如果 Nginx 被用作反向代理,並且正在提交的應用程序易受本地文件包含的影響,則在請求中使用額外的斜線可能會為開發它留出空間。這是丹尼羅賓遜和羅特姆酒吧詳細描述。
我們發現了33個nginx配置文件,merge_slashes設置為"關閉"。
自己試試
我們創建了一個 GitHub 存儲庫,您可以使用 Docker 設置您自己的易受攻擊的 Nginx 測試服務器,其中討論了本文中討論的一些錯誤配置,並嘗試自己找到它們!
https://github.com/detectify/vulnerable-nginx
進一步閱讀:
結論
Nginx 是一個非常強大的 Web 服務器平台,它很容易理解為什么它被廣泛使用。但是,通過靈活的配置,您可以做出可能具有安全影響的錯誤。不要讓攻擊者通過不檢查這些常見的錯誤配置來破解您的網站太容易。
轉發來源:https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/
文章來源:劉俊濤的博客 歡迎關注公眾號、留言、評論,一起學習。
__________________________________________________________________________________
若有幫助到您,歡迎點擊推薦,您的支持是對我堅持最好的肯定(*^_^*)


