GMTC深圳站售票最后一周,点击查看最新日程>> 了解详情
写点什么

五个常见的 Nginx 配置错误

  • 2021 年 3 月 29 日
  • 本文字数:3580 字

    阅读完需:约 12 分钟

五个常见的Nginx配置错误

作为互联网上最常用的 Web 服务器之一,Nginx 因轻巧、模块化并且有对用户友好的配置格式而广受欢迎。一旦 Nginx 出现错误配置,那么你的网站就很危险。Detectify 分析了从 GitHub 下载的近 50000 个不重复的 Nginx 配置文件,发现了一些常见的错误配置:

  • 根目录位置丢失

  • off-by-slash

  • 不安全的变量使用

  • 原始后端响应读取

  • merge_slashes设置为 off

根目录位置丢失

server {        root /etc/nginx;
location /hello.txt { try_files $uri $uri/ =404; proxy_pass http://127.0.0.1:8080/; }}
复制代码


root 指令指定 Nginx 的根文件夹。在上面的示例中,根文件夹是/etc/nginx,这意味着我们可以访问该文件夹中的文件。上面的配置没有针对/ (location / {...})的位置,只有/hello.txt的位置。因此,root 指令会被设置为全局,这意味着对/的请求会将你带到本地路径/etc/nginx


GET /nginx.conf这样简单的请求都能显示存储在/etc/nginx/nginx.conf中 Nginx 配置文件的内容。如果将根设置为/etc,则对/nginx/nginx.confGET请求将显示配置文件。在某些情况下,访问者可能会访问其他配置文件、访问日志甚至 HTTP 基本身份验证的加密凭据。


在我们收集的近 50000 个 Nginx 配置文件中,最常见的根路径如下:



经常配置错误的 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/; }}
复制代码


这个配置错误指的是由于缺少一个斜杠,所以有可能沿路径上移一步。OrangeTsai 在 Blackhat 演讲 “Breaking Parser Logic!”中让这项技术广为人知。


在这个演讲中,他展示了如何结合一条缺少尾斜杠的location指令与一条alias指令,来读取 Web 应用程序的源代码。鲜为人知的是,它还可以与其他指令(例如proxy_pass)一起使用。我们来分解一下究竟发生了什么事情,以及为什么它能起作用。


location /api {                proxy_pass http://apiserver/v1/;        }
复制代码


如果一个 Nginx 服务器运行能在 server 访问的以下配置,则可以假定访问者只能访问http://apiserver/v1/下的路径。


http://server/api/user -> http://apiserver/v1//user
复制代码


当请求http://server/api/user时,Nginx 将首先规范化 URL。然后,它会查看前缀/api是否与 URL 匹配,本例中是匹配的。


然后,服务器从 URL 中删除该前缀,保留/user路径。再将此路径添加到proxy_pass URL 中,从而得到最终 URL http://apiserver/v1//user


请注意,这个 URL 中存在双斜杠,因为 location 指令不以单斜杠结尾,并且proxy_pass URL 路径以单斜杠结尾。大多数 Web 服务器会将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/userhttp://server/apiuser返回相同的响应,则服务器可能容易受到攻击。这将导致发送以下请求:


http://server/api/user -> http://apiserver/v1//userhttp://server/apiuser -> http://apiserver/v1/user
复制代码

不安全的变量使用

一些框架、脚本和 Nginx 配置会不安全地使用 Nginx 存储的变量。这可能会导致诸如 XSS、绕过 HttpOnly 保护、信息泄露,甚至在某些情况下的 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 会将所有 URL 发送到以.php结尾的 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.phpSCRIPT_NAME = /index.php/<script>alert(1)</script>/index.php
复制代码

使用 $uri 可导致 CRLF 注入

与 Nginx 变量有关的另一个错误配置是使用$uri$document_uri代替$request_uri$uri$document_uri包含标准化的 URI,而 Nginx 中的normalization包括对 URI 解码的 URL。Volema 发现,在 Nginx 配置中创建重定向时经常会使用$uri,结果导致 CRLF 注入。


一个易受攻击的 Nginx 配置的示例如下:


location / {return 302 https://example.com$uri;}
复制代码


HTTP 请求的换行符为\r(回车)和\n(换行)。对换行符进行 URL 编码将导致以下字符表示形式%0d%0a。如果将这些字符包含在对配置错误的服务器的一个请求中(例如http://localhost/%0d%0aDetectify:%20clrf),则该服务器将使用一个名为Detectify的新标头进行响应,因为 $uri 变量包含 URL 解码的换行符。


HTTP/1.1 302 Moved TemporarilyServer: nginx/1.19.3Content-Type: text/htmlContent-Length: 145Connection: keep-aliveLocation: https://example.com/Detectify: clrf
复制代码

Any 变量

在某些情况下,用户提供的数据可以视为 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 Error,Nginx 将拦截该错误。


proxy_hide_header可以自解释;它将从客户端隐藏任何指定的 HTTP 标头。


如果我们发送一个普通的 GET 请求,则 Nginx 将返回:


HTTP/1.1 500 Internal Server ErrorServer: nginx/1.10.3Content-Type: text/htmlContent-Length: 34Connection: close
复制代码


但是,如果我们发送一个无效的 HTTP 请求,例如:


GET /? XTTP/1.1Host: 127.0.0.1Connection: close
复制代码


我们将收到以下答复:


XTTP/1.1 500 ErrorContent-Type: text/htmlSecret-Header: secret-infoSecret info, should not be visible!
复制代码

merge_slashes 设置为 off

默认情况下,merge_slashes指令设置为“on”,这是一种将两个或多个正斜杠压缩为一个的机制,因此///将变为/。如果 Nginx 用作反向代理,并且被代理的应用程序容易受到本地文件包含内容的影响,则在请求中使用额外的斜杠可能会留出恶意利用空间。


我们发现 33 个 Nginx 配置文件的merge_slashes设置为“off”。

自己尝试一下

我们创建了一个GitHub存储库,你可以在其中使用 Docker 来设置你自己的易受攻击的 Nginx 测试服务器,以及本文中讨论的一些错误配置,然后尝试自己找到它们。

总结

Nginx 是一个非常强大的 Web 服务器平台,很好理解为什么它会被广泛使用。但是,灵活的配置意味着你更容易犯错误,而这些错误可能会对安全性产生影响。请不要使用这些常见的错误配置,以免攻击者轻易地入侵你的网站。


原文链接:


https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/?fileGuid=xVX6hcx8WXCYPVGd

2021 年 3 月 29 日 13:573900
用户头像
王强 技术是文明进步的力量

发布了 643 篇内容, 共 239.8 次阅读, 收获喜欢 1401 次。

关注

评论

发布
暂无评论
发现更多内容

工厂模式 (一)简单的工厂模式概念以及示例代码

LSJ

[GitHub] 跟我一起白嫖 GitHub Pages 做个人站点 ?

猴哥一一 cium

git GitHub GitHub Pages

软件开发生产率改进之我见(一)

清水

团队管理 软件工程 技术管理

Golang热更新原理

我心依然

Go nginx Linux 信号

[Git] Git 可以这么学

猴哥一一 cium

git

游戏夜读 | 如何避免乏味?两则

game1night

简单聊聊什么是苹果生态

李俊辰

专业的力量

无量靠谱

淘宝 美团 专业 专业主义 大前研一

Zabbix实战指南

橙子冰

技术 运维 监控 运维自动化 zabbix

学计算机你后悔了吗?

陈辰

学习 技术 前端

ARTS - Week One

shepherd

js algorithm

「开放」对协作效率的影响

Tony Wu

产品 产品设计

2020年2月北京BGP机房网络质量评测报告

博睿数据

APM 机房 评测 世纪互联

Elasticsearch 实战

代码诗人

Kubectl exec 的工作原理解读

米开朗基杨

Kubernetes kubelet

给学妹的 Java 学习路线

武培轩

Java 学习 程序员 程序媛

Lean UX 教你设计如何驱动产品

Yanel 说敏捷产品

产品 敏捷 设计

Flutter的staggered GridView详细使用

潘珉

flutter

有价值的产品=设计思维+精益创业+敏捷方法

行叔

Scrum 敏捷开发 Agile 设计思维 精益创业

翻译敏捷行业专业外文,不只是谷歌翻译

行叔

翻译 Scrum 敏捷开发 Agile

关于问题的问题 —— 读《你的灯亮着吗?》

YoungZY

读书笔记 读书

内容比形式更重要

Winann

内容 生活 工作 形式主义

基于mysqldump聊一聊MySQL的备份和恢复

麦洛

MySQL

2020年2月北京BGP机房网络质量评测报告

博睿数据

听过很多道理,依然过不好这一生。

Neco.W

感悟 创业心态

数仓系列 | Flink 窗口的应用与实现

Apache Flink

大数据 flink 流计算 实时计算 大数据处理

李想解读《高效能人士的七个习惯》

我心依然

习惯 高效能人士的七个习惯 李想 汽车之家

重磅!Apache Flink 1.11 功能前瞻抢先看!

Apache Flink

大数据 flink 流计算 实时计算 大数据处理

五个“为什么” —— 读《精益创业》

YoungZY

读书笔记

实用贴丨正确的「递归」打开方式:让计算机像计算机一样去计算

博文视点Broadview

Python 递归

工厂模式(二)MyBatis中展示的简单的工厂模式

LSJ

mybatis 工厂模式

“你好,元宇宙”华为云联创营元宇宙高峰论坛

“你好,元宇宙”华为云联创营元宇宙高峰论坛

五个常见的Nginx配置错误-InfoQ