三个案例看 Nginx 配置安全

原文:https://paper.seebug.org/335/

之前在Sec-News中推荐了一个开源程序,作用是来检测 Nginx 配置文件中存在的问题。正好 Pwnhub 上周的比赛也出现了一道题,包含由 Nginx 配置错误导致的漏洞。

所以我挑选我觉得比较有趣,而且很有可能犯错误的三个典型案例,来说说 Nginx 配置文件的安全。

另外,本文所涉及的三个案例,均已上线到Vulhub,阅读本文的同时可以自己动手测试。

  • $uri导致的CRLF注入漏洞

下面两种情景十分常见:

用户访问http://example.com/aabbcc, 自动跳转到 https://example.com/aabbcc 用户访问http://example.com/aabbcc, 自动跳转到 http://www.example.com/aabbcc

比如我的博客,访问 http://www.leavesongs.com/other/tinger.html ,将会301跳转到 https://www.leavesongs.com/other/tinger.html 。随着现在 https 的普及,很多站点都强制使用 https 访问,这样的跳转非常常见。

第二个场景主要是为了统一用户访问的域名,更加有益于 SEO 优化。

在跳转的过程中,我们需要保证用户访问的页面不变,所以需要从 Nginx 获取用户请求的文件路径。查看 Nginx 文档,可以发现有三个表示 uri 的变量:

  1. $uri
  2. $document_uri
  3. $request_uri

解释一下,1和2表示的是解码以后的请求路径,不带参数;3表示的是完整的URI(没有解码)。那么,如果运维配置了下列的代码:

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

因为$uri是解码以后的请求路径,所以可能就会包含换行符,也就造成了一个CRLF注入漏洞。(关于CRLF注入漏洞,可以参考我的老文章.

这个 CRLF 注入漏洞可以导致会话固定漏洞、设置 Cookie 引发的 CSRF 漏洞或者 XSS 漏洞。其中,我们通过注入两个 \r\n 即可控制 HTTP 体进行 XSS,但因为浏览器认为这是一个300跳转,所以并不会显示我们注入的内容。

这个情况下,我们可以利用一些技巧:比如使用 CSP 头来 iframe 的地址,这样浏览器就不会跳转,进而执行我们插入的 HTML :

关于上述利用方法,可以参考我的另一篇文章《Bottle HTTP 头注入漏洞探究》。

如何修复这个 CRLF 漏洞?正确的做法应该是如下:

location / {
    return 302 https://$host$request_uri;
}

另外,由$uri导致的 CRLF 注入漏洞不仅可能出现在上述两个场景中,理论上,只要是可以设置 HTTP 头的场景都会出现这个问题。

  • 目录穿越漏洞

这个常见于 Nginx 做反向代理的情况,动态的部分被 proxy_pass 传递给后端端口,而静态文件需要 Nginx 来处理。

假设静态文件存储在 /home/ 目录下,而该目录在 url 中名字为 files ,那么就需要用 alias 设置目录的别名:

location /files {
    alias /home/;
}

此时,访问http://example.com/files/readme.txt, 就可以获取/home/readme.txt文件。

但我们注意到,url上/files没有加后缀/,而alias设置的/home/是有后缀/的,这个/就导致我们可以从/home/目录穿越到他的上层目录:

进而我们获得了一个任意文件下载漏洞。

这个有趣的漏洞出现在了 Pwnhub 上一期比赛《寻找 SNH48》中,@Ricter师傅的题目。

如何解决这个漏洞?只需要保证location和alias的值都有后缀/或都没有这个后缀。

  • Http Header被覆盖的问题

众所周知,Nginx 的配置文件分为 Server、Location、If 等一些配置块,并且存在包含关系,和编程语言比较类似。如果在外层配置的一些选项,是可以被继承到内层的。

但这里的继承也有一些特性,比如 add_header,子块中配置后将会覆盖父块中的 add_header 添加的所有 HTTP 头,造成一些安全隐患。

如下列代码,Server 块添加了 CSP 头:

server {
    ...
    add_header Content-Security-Policy "default-src 'self'";
    add_header X-Frame-Options DENY;

    location = /test1 {
        rewrite ^(.*)$ /xss.html break;
    }

    location = /test2 {
        add_header X-Content-Type-Options nosniff;
        rewrite ^(.*)$ /xss.html break;
    }
}

但 /test2 的 location 中又添加了 X-Content-Type-Options 头,导致父块中的 add_header 全部失效:

此时,test2 的 csp 就完全失效了,我们成功触发 XSS :

  • 总结

Nginx配置文件造成的漏洞绝不止这三种,比如之前特别火的解析漏洞,也和 Nginx 的配置有一定关系。

解决这类漏洞,最根本的方法是仔细阅读官方文档,文档里说明了很多配置文件错误和正确的用法。最忌去百度网上的一些解决方法,很多错误就是一传十十传百,最后流传开来的。

另外,本文开头提到的工具 gixy ,我们也可以利用起来,网站上线前进行一下扫描,也许就能发现一些可能存在的问题。


原文发布于微信公众号 - nginx(nginx-study)

原文发表时间:2018-05-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

TCP/IP(七)之玩转HTTP协议

前言   前面一篇的博文简单的介绍了一下属于应用层的HTTP协议,这一篇我将详细的学习HTTP协议,这也是做Web开发中一定要用到的协议。虽然我是做大数据的,但...

31090
来自专栏散尽浮华

Git忽略规则.gitignore梳理

对于经常使用Git的朋友来说,.gitignore配置一定不会陌生。废话不说多了,接下来就来说说这个.gitignore的使用。 首先要强调一点,这个文件的完整...

20570
来自专栏小勇DW3

亿级流量场景下,大型缓存架构的虚拟机环境搭建

静态模板是固定的 数据库中的数据全量喧嚷到模板中,下次请求来了直接返回,速度也很快;

21340
来自专栏跟着阿笨一起玩NET

windows批量创建用户

  建立用户:net  user  用户名 密码  /add           (如:net user test 123 /add)   提升权限:net  ...

59910
来自专栏Java帮帮-微信公众号-技术文章全总结

02.线程阻塞状态/线程控制

02.线程阻塞状态/线程控制 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型。下面分别看下引起Java线程阻塞的主要方法。 1....

40650
来自专栏后端技术探索

Nginx从入门到学会--5.必会的重要概念

在nginx中connection就是对tcp连接的封装,其中包括连接的socket,读事件,写事件。利用nginx封装的connection,我们可以很方便的...

12630
来自专栏张善友的专栏

使用WinSCP软件在windows和Linux中进行文件传输

当我们的开发机是Windows,服务器是Linux时,如何在windows操作系统和linux操作系统之间进行文件传输呢?大部分使用ScureCRT或者putt...

394100
来自专栏糊一笑

谈谈webpack2的一些事

从v1迁移到v2 1. 配置类型 在webpack1的时候,主要是通过导出单个object来进行配置。例如下面的配置: // webpack1 导出方式 mod...

31350
来自专栏后端技术探索

Nginx从入门到学会--5.必会的重要概念

在nginx中connection就是对tcp连接的封装,其中包括连接的socket,读事件,写事件。利用nginx封装的connection,我们可以很方便的...

13320
来自专栏从零学习云计算

Centos7.2学习记录(3)——搭建本地yum仓库

入职以来,由于公司云主机运行在内网环境下,在搭建kubernetes和openshift集群时都需要进行离线安装,这里粗略记录一下本地yum仓库的搭建过程。 ...

44800

扫码关注云+社区

领取腾讯云代金券