Nginx常见的错误配置举例
nginx是当前主流的web服务。 以下是一些最常见的错误配置。
missing root location
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.conf的get请求将显示配置文件。 在某些情况下,可能会访问其他配置文件,访问日志甚至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配置错误,由于缺少/,因此有可能沿路径上移一步。 orange tsai在blackhat的演讲“ breaking parser logic!”中使这项技术广为人知。 在本次演讲中,他展示了location指令与alias指令结合使用的缺失斜杠如何使读取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中删除该前缀,因此保留/user路径。 然后将此路径添加到proxy_pass
url中,从而得到最终url http://apiserver/v1//user。 请注意,url中存在双斜杠,因为location指令不以斜杠结尾,并且proxy_pass
url路径以斜杠结尾。 大多数web服务器会将http://apiserver/v1//user user标准化为http://apiserver/v1/user,这意味着即使配置错误,所有内容仍将按预期运行,并且可能不会引起注意。
通过请求http://server/api../可以利用这种错误配置,这将导致nginx请求标准化为http://apiserver/v1/../的url 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
unsafe variable use
一些框架、脚本和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创建的pitfalls and common mistakes文档中罗列的许多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
usage of $uri can lead to crlf injection
与nginx变量有关的另一个错误配置是使用$uri或$document_uri而不是$request_uri。 $uri和$document_uri包含标准化的uri,而nginx中的标准化包括对uri进行解码的url。 volema 发现,在nginx配置中创建重定向会导致crlf注入时,通常使用$uri。
易受攻击的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报告所示,这种情况并不罕见或不容易测试。 如果搜索错误消息,我们可以看到它在 ssi filter module中找到,从而表明这是由于ssi引起的。
测试方法如下:
$ curl -h ‘referer: bar' http://localhost/foo$http_referer | grep ‘foobar'
raw backend response reading
使用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, 将提供自定义响应。在上面的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 set to off
默认情况下,merge_slashes
指令设置为on
,这是一种将两个或多个正斜杠压缩为一个的机制,因此///
将变为/
。 如果nginx用作反向代理,并且被代理的应用程序容易受到本地文件包含的影响,则在请求中使用额外的斜杠可能会留出利用空间。 danny robinson and rotem bar对此进行了详细描述。
以上就是nginx常见的错误配置举例的详细内容,更多关于nginx 错误配置的资料请关注其它相关文章!
下一篇: 浅谈java如何生成分享海报工具类