0x00 运行环境

ubuntu进入/vulhub-master/nginx/insecure-configuration目录

执行以下命令,运行环境。

docker-compose up -d

运行成功后,Nginx将会监听8080/8081/8082三个端口,分别对应三种漏洞。

0x01 CRLF注入漏洞

1.前提

下面两种跳转情景十分常见:

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

http状态码301和302详解及区别:https://blog.csdn.net/zhouchangshun_666/article/details/79354193

第一种跳转随着现在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注入漏洞,可以参考文章 :https://www.leavesongs.com/PENETRATION/Sina-CRLF-Injection.html

2.CRLF的介绍

CRLF是”回车 + 换行”(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。

CRLF是比XSS危害更大的安全问题,对于CRLF最简单的利用方式是注入两个\r\n,之后在写入XSS代码,来构造一个xss。

举个例子,一般网站会在HTTP头中用Location: http://baidu.com这种方式来进行302跳转,所以我们能控制的内容就是Location:后面的XXX某个网址。

一个正常的302跳转包如下图:

1.png

http://192.168.189.139:8080/%0aSet-cookie:JSPSESSID%3Ddrops

repeater模式下修改包的内容(注入一个换行,在http头里注入了cookie,如下图)与url直接(上面)访问抓包,他们的返回包都是一样的。
此时的返回包如下图:

2.png

这个时候这样我们就给访问者设置了一个SESSION,造成一个“会话固定漏洞”。

当然,CRLF并不仅限于会话固定,通过注入两个CRLF就能造成一个无视浏览器Filter的反射型XSS。

比如一个网站接受url参数http://192.168.189.137:8080/?url=xxx,xxx放在Location后面作为一个跳转。如果我们输入的是:

http://192.168.189.137:8080/?url=%0d%0a%0d%0a<img src=1 onerror=alert(/xss/)>

我们的返回包就会变成这样:

7.png

之前说了浏览器会根据第一个CRLF把HTTP包分成头和体,然后将体显示出来。于是我们这里这个标签就会显示出来,造成一个XSS。

为什么说是无视浏览器filter的,这里涉及到另一个问题。

浏览器的Filter是浏览器应对一些反射型XSS做的保护策略,当url中含有XSS相关特征的时候就会过滤掉不显示在页面中,所以不能触发XSS。

怎样才能关掉filter?一般来说用户这边是不行的,只有数据包中http头含有X-XSS-Protection并且值为0的时候,浏览器才不会开启filter。

方法一

说到这里应该就很清楚了,HRS不正是注入HTTP头的一个漏洞吗,我们可以将X-XSS-Protection:0注入到数据包中,再用两个CRLF来注入XSS代码,这样就成功地绕过了浏览器filter,并且执行我们的反射型XSS。

所以说HRS的危害大于XSS,因为它能绕过一般XSS所绕不过的filter,并能产生会话固定漏洞。

4.png

http://192.168.189.139:8080/url=%0aX-XSS-Protection:%200%0a%0d%0a%0d<img%20src=1%20onerror=alert(/xss/)>

输入上面的url访问,返回如下结果(其他浏览器也是这样),这种方法我没有成功。

8.png

方法二

利用字符编码来绕过XSS Filter的方法,当编码是is-2022-kr时浏览器会忽略%0f,这样我们在onerror后面加个%0f就能绕过filter,前提是注入一个<meta charset=ISO-2022-KR>,输入下面的url后返回结果和上面的一样,也是没有成功。哭哭哭

http://192.168.189.139:8080/url=%0a%0d%0a%0d%0a<meta%20charset=ISO-2022-KR><img%20src=x%20onerror%0f=alert(1)>

修复HRS漏洞的方法是过滤\r 、\n之类的换行符,避免输入的数据污染到其他HTTP头

回到本题

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

这个情况下,我们可以利用一些技巧:比如使用CSP头来iframe的地址,这样浏览器就不会跳转,进而执行我们插入的HTML:
这个方法看文章没看懂,太菜了,不会用啊,哭哭哭。

关于上述利用方法,可以参另一篇文章:https://www.leavesongs.com/PENETRATION/bottle-crlf-cve-2016-9964.html

如何修复这个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/目录穿越到他的上层目录:

修改请求为http://example.com/files../,可以成功跳转到上一层目录下。如下图所示

9.png

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

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

add_header被覆盖

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

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

如下列代码,整站(父块中)添加了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;
    }
}

父块在这里插入图片描述
test1
11.png
/test2的location中又添加了X-Content-Type-Options头,导致父块中的add_header全部失效:
在这里插入图片描述
此时,test2的csp就完全失效了,我们成功触发XSS:

http://192.168.189.139:8082/test2#<img src=1 onerror=alert(1)>

在IE浏览器中测试
在这里插入图片描述

测试中test1也能触发
14.png
在火狐和google结果都一样,没有成功。
在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐