0x00 前言

这段时间做了好几道Nginx配置不当的题目,集中学习一下这方面的知识。

0x01 基础

Nginx的主配置文件为nginx.conf,在任何情况下Nginx都会加载该文件。nginx.conf文件结构分明,由多个模块构成,如下:

20190418163927-79fddd08-61b5-1

用代码表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...              #全局块     -->main

events { #events块
...
}

http #http块
{
... #http全局块
server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN] #另一个location块
{
...
}
}
}

解析

Nginx层级分明,每个层级都有自己的指令。子块会继承父块的配置,如果二者配置的指令不同,则子块会覆盖父块的配置。指令格式如下:

1
指令名 参数1 参数2 参数3;

nginx.conf还可以引入其他的配置文件,如include /etc/nginx/mime.types;就包含了各种支持的Content-type。另外,开发者不可能把服务都写在nginx.conf里,对应的.conf文件也会被包含。

一个server块表示一个host,可以在server块中添加或者更改nginx服务监听的端口、存放网页文件的位置、以及虚拟主机配置(开反向代理)。
一个location块代表一个路由映射规则。

0x02 alias配置不当 · 目录穿越

条件其一

nginx.conf文件的server块中加入:autoindex on;,可以添加目录浏览功能,但是也会产生安全问题,如本节的alias配置不当引起的一系列漏洞。具体配置如下:

1
2
3
4
server {
autoindex on;
...
}

在该代码块的基础上会导致目录遍历,可以访问设置的根目录下的文件。

条件其二

在nginx做反向代理的时候,我们通常会把动态部分传递给后方解析的服务器,由nginx来处理静态文件
当使用alias来对文件路径进行配置时,有可能会造成目录穿越漏洞

正常配置

1
2
3
location /files/ {
alias /etc/nginx/txtpath/;
}

正常访问http://your_ip/files/pax.txt,便会读取/etc/nginx/txtpath/pax.txt文件。

配置不当

1
2
3
ocation /files {
alias /etc/nginx/txtpath/;
}

/files/变成了/files,第二个斜杠没有了,那么攻击者就可以读取正常文件夹之外的文件。

当访问http://your_ip/files../pax.txt,便会读取/etc/nginx/pax.txt文件。

同时满足

条件一允许我们读取该目录下的所有目录及文件;条件二允许我们返回到上级目录。若同时满足这两个条件,我们便可以读取该目录的上级目录下的所有目录和文件。

alias指定的目录足够上层(到根目录的下级目录),我们就可以穿梭到根目录。

20190418164249-f26df0de-61b5-1

对应题目:CTFHub->历年真题->web->afr-2

0x03 反代配置不当 · SSRF

Nginx经常拿来做反向代理服务器。反向代理服务器其实就是一台负责转发的代理服务器,实现了转发的作用,然后从真正的服务器获取数据并转发给客户端。

正常配置

1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name 192.168.1.2:8080;

location / {
proxy_pass http://192.168.1.2:8080;
}
#......
}

配置不当

1
2
3
location /([a-zA-Z0-9.:%]+) {   
proxy_pass http://$1
}

分析

$1:正则匹配的第一个括号的内容。

如果访问的url是服务端的内网,因为$1等于url,所以Nginx会代理到服务端的内网,实现SSRF

防御思路

  • 输入验证:确保只允许合法的外部地址。
  • 白名单:限制可访问的 IP 地址。
  • 监控日志:及时发现异常请求。

0x04 重定向配置不当 · CRLF

当一个网站使用https协议的时候,很多站点会强制用户使用https进行访问。当用户访问http的时候会302跳转到https页面。

配置不当:

1
2
3
location /302 {
return 302 https://$host$uri;
}

Nginx中 ,$uri指的是请求的文件和路径,不包含后面请求的数据(即?和#后面的数据),Nginx服务器会对$uri进行解码。当$uri后面添加%0d%0a,便可以污染HTTP头的数据。

比如,访问http://your_ip/302/pax.php302跳转到https://your_ip/302/pax.php,这是正常的302跳转。但是如果访问http://your_ip/302/pax.php%0d%0a%0d%0aman=1302跳转会指向https://your_ip/302/pax.php并且POST一个参数 man=1,比如下图例子:

20190418164304-fb29d2c4-61b5-1

如此便达成了CRLF

0x05 子块覆盖父块不当

在nginx配置文件中子块是可以继承父块的配置的。但是当我们在父块中设置了add_header头,然后再在子块中设置另一个add_header头时,子块会覆盖掉父块中的add_header头的设置。

假如配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
...
add_header X-Frame-Options DENY;
add_header Content-Security-Policy "default-src 'self'";

location = /safe {
return /xss.html;
}

location = /dangerous {
add_header X-Content-Type-Options nosniff;
return /xss.html;
}
}

须知:

  • add_headerNginx 配置指令,用于向 HTTP 响应中添加自定义 HTTP 头部。
  • X-Frame-Options DENYContent-Security-Policy "default-src 'self'"用来抵御一般的XSS攻击。
  • X-Content-Type-Options 是一个 HTTP 响应头,用于防止浏览器对内容类型进行嗅探。其常见的值是 nosniff

如果访问http://your_ip/safe,采用父块的add_header,不会触发XSS

但是如果访问http://your_ip/dangerous,子块的add_header覆盖了父块的add_header,对xss的防御不再生效,成功触发xss

0x06 Reference

https://xz.aliyun.com/t/4855

Nginx错误配置alias导致目录遍历漏洞 | BlackWolf (blackwolfsec.cc)