Nginx 是目前世界上使用最多的Web服务器,以下为大家详细讲解一下一些常见的Nginx配置会使你的网站容易受到攻击

以下最常见的错误配置常常被攻击者所利用

  • 缺少根目录
  • 不安全的变量使用
  • 原始后端响应读取
  • merge_slashes 设置为关闭

缺少根位置

server {
    root /etc/nginx;

    location /hello.txt {
            try_files $uri $uri/ =404;
            proxy_pass http://127.0.0.1:8080/;
    }
}

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

一个简单的请求GET /nginx.conf会显示存储在/etc/nginx/nginx.conf. 如果根设置为/etc,则GET请求/nginx/nginx.conf将显示配置文件。在某些情况下,可以访问其他配置文件、访问日志,甚至是用于 HTTP 基本身份验证的加密凭据

最常见的根目录:
image.png

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 错误配置,由于缺少斜线,可能会在路径上向上移动一步,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_passURL 中,从而生成最终 URL http://apiserver/v1//user。请注意,URL 中有一个双斜杠,因为 location 指令不以斜杠结尾,而proxy_pass URL 路径以斜杠结尾。大多数 Web 服务器将标准化http://apiserver/v1//userhttp://apiserver/v1/user,这意味着即使存在这种错误配置,一切都将按预期工作,并且可能会被忽视

可以通过请求来利用这种错误配置,http://server/api../这将导致 Nginx 请求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//user 
http://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即使该文件不存在。

如果 PHP 脚本尝试定义基于 的基本 URL,则会发生 XSS SCRIPT_NAME

<?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,而normalizationNginx 中的 包含对 URI 进行解码的 URL。Volema发现$uri在 Nginx 配置中创建重定向时常用,这会导致 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 Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf

Any variable

在某些情况下,用户提供的数据可以被视为 Nginx 变量。目前尚不清楚为什么会发生这种情况,但如H1 report所示,这种情况并不少见或易于测试。如果我们搜索错误消息,我们可以看到它是在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 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 用作反向代理并且被代理的应用程序容易受到本地文件包含的影响,则在请求中使用额外的斜杠可能会留下利用它的空间。

点赞(0)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部