漏洞复现之Nginx配置漏洞

配置漏洞是指用户配置不当导致的漏洞,在Nginx中存在众多的配置漏洞

CLRF头部注入攻击

CLRF是Carriage-Return Line-Feed的缩写,即回车换行,用字节来表示的话是\r\n,字节码表示就是0x0d0x0a。在HTTP请求头部中,头部参数之间通过CRLF来分割,头部参数与消息体通过两个CRLF来分割:

Post / HTTP/1.1[\r\n]
Host: 127.0.0.1:8080[\r\n]
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0[\r\n]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8[\r\n]
Accept-Language: en-US,en;q=0.5[\r\n]
Accept-Encoding: gzip, deflate[\r\n]
Connection: close[\r\n]
Upgrade-Insecure-Requests: 1[\r\n]
[\r\n]
[\r\n]
***********************body**************************

CRLF头部注入指的是向请求头部参数注入回车换行符,如果服务器接收后没有能够正确对其进行处理则可能把我们注入的CRLF识别为头部参数分割符相应的把CRLF后面的数据识别为头部参数。

http://127.0.0.1/abc.php[\r\n]Set-Cookie:abc=1232

我们知道头部中有Referer参数用来指示发起此请求的页面是谁,如果我们通过上述链接访问另一个页面admin.php时这是头部参数则可能如下:

GET / HTTP/1.1[\r\n]
Host: 127.0.0.1:8080[\r\n]
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0[\r\n]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8[\r\n]
Accept-Language: en-US,en;q=0.5[\r\n]
Accept-Encoding: gzip, deflate[\r\n]
Referer:http://127.0.0.1/abc.php[\r\n]Set-Cookie:abc=1232[\r\n]
Connection: close[\r\n]
Upgrade-Insecure-Requests: 1[\r\n]

后台服务器接收到这个请求后如果没有正确处理头部值中的CRLF则可能出现如下情况:

GET / HTTP/1.1[\r\n]
Host: 127.0.0.1:8080[\r\n]
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0[\r\n]
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8[\r\n]
Accept-Language: en-US,en;q=0.5[\r\n]
Accept-Encoding: gzip, deflate[\r\n]
Referer:http://127.0.0.1/abc.php[\r\n]
Set-Cookie:abc=1232[\r\n]
Connection: close[\r\n]
Upgrade-Insecure-Requests: 1[\r\n]

这时我们就向头部中注入了Set-Cookie这个头部参数。当然上面的演示也只是为了演示,向服务器注入头部参数没有任何意义,接下来我们看实际的例子。
这里我们以Vulhub提供的Nginx配置漏洞环境进行演示。此环境中导致漏洞的配置如下,此配置实现了强制跳转的功能,当用户访问nginx服务器时由于此配置的存在我们会被强制跳转到以https协议访问我们之前访问的链接:

#nginx.conf
location / {
      return 302 https://$host$uri;
     }

上述配置的关键利用点有两个,一是配置中的$uri是我们可以控制的,这样我们就可以在$uri中填入CRLF然后对服务器进行访问实现头部注入。二是服务器会返回一个302跳转给用户,所以我们注入的头部参数又会返回到客户这边。
CRLF
如上图所示,我们在漏洞环境中成功的实现了CRLF头部注入。不过这时候302跳转是返回给了我本人,这不是自我攻击吗?那么还记得反射型XSS吗?这个漏洞也可以当成一个反射型漏洞。那么这个漏洞到底要怎么应用呢,这就得看具体注入的什么头部参数了,比如说你可以通过注入Set-Cookie进行会话固定攻击,具体流程如下:

  1. 攻击者访问目标网站获得会话ID(用于追踪用户会话状态)
  2. 攻击者使用自己的会话ID构造如上述漏洞演示中的触发头部注入漏洞的URL
  3. 攻击者将构造好的URL发送给受害者
  4. 受害者点击,浏览器返回带有Set-Cookie的302跳转,这时受害者拥有和攻击者相同欧冠你的会话ID
  5. 受害者登录目标网站,服务器将用户状态与会话ID绑定
  6. 攻击这使用会话ID访问目标网站,这时服务器会把攻击者识别为受害者并返回受害者的用户状态给攻击者

我们知道现在浏览器还引入了XSS-Filter技术来防止XSS攻击,但是当HTTP头部存在X-XSS-Protection:0时,浏览器则会关闭XSS-Filter,为此我们可以注入此头部防止浏览器拦截XSS。

目录遍历

目录遍历这个配置漏洞就比较简单了,当Nginx存在如下配置时我们可以浏览目录信息。

#nginx.conf
 autoindex on;

目录遍历

目录穿越

在如下配置中设置目录别名时/files配置为/home/的别名那么当我们访问/files…/时,nginx实际处理的路径是/home/…/从而实现了穿越目录。

#nginx.conf
location /files {
        alias /home/;
    }

目录穿越

add_headers被覆盖

除了上述配置漏洞外还存在Nginx配置文件中父块配置被子块配置覆盖的而引发安全问题的情况,比如如下配置:

#nginx.conf
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;
}

首先介绍上述文件中以下几点:

  1. Content-Security-Policy头,其称为内容安全策略用于限制网站是否可以包含某些资源的内容,上述配置中此项的值设置为"default-src ‘self’",这表示页面只能加载同源资源。除此之外其还默认禁止内联代码的执行,关于协议的详细介绍可以参考这篇文章
  2. X-Content-Type-Options头,官方文档对于这个头部的介绍我是看不懂了!我的理解是富文本内容中由各类资源组成,每类资源对应不同的MIME用于指示资源类型比如纯文本是text/plain,JS文件是application/javascript等。一些浏览器在接收到没有明确MIME的情况下会根据具体资源判断其类型并进行相应处理。设置这个头部可以关掉浏览器自动判断资源类型并进行相关处理的功能。
  3. Nginx配置文件中子块配置会覆盖父块配置

有了上述知识后假设在上述配置环境中运行如下代码:

//static/app.js
window.onload = function() {
    var m = document.getElementById('m');
    m.innerHTML = decodeURI(location.hash.substr(1));
}
<!--xss.html-->
<!DOCTYPE html>
<html>
<head>
<title>XSS Vulnerability</title>
<script src="static/app.js"></script>
</head>
<body>
<p id="m"></p>
</body>
</html>

为此在访问上述代码时会出现下面两种情况:

  1. 当你访问http://server-ip/test1#<img src=1 alert(1)>时由于存在Content-Security-Policy所以不可以执行内联代码故不能导致XSS。
    XSS
  2. 但是访问http://server-ip/test2#<img src=1 alert(1)>时由于子块的add_header覆盖了父块的,为此只有X-Content-Type-Options头被设置,但这不妨碍我们的XSS。
    xss
    对于上面提到的两个安全头部是不是可以使用CRLF头部参数注入通过注入相同头部来进行绕过,比如如下图所示。但是对于头部参数重复的情况目前还没有一个具体的处理规范,这取决于浏览器的具体实现,这就代表着通过CRLF绕过这些安全的头部参数是存在可能的!!!
    CRLF

文件名解析漏洞

由配置缺陷导致的文件漏洞的利用逻辑可以分为三步

  1. 首先由于nginx.conf的如下配置导致nginx把以’.php’结尾的文件路径交由fastcgi处理,为此可以构造http://target-ip/uploadfiles/test.png/.php(URL末尾不一定是’.php’,任何服务器端不存在php文件均可,比如’abc.php’),其中test.png是我们上传的包含PHP代码的照片文件。
#nginx.conf
location ~ \.php$ {
		fastcgi_index index.php;

		include fastcgi_params;

		fastcgi_param  REDIRECT_STATUS    200;
		fastcgi_param  SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
		fastcgi_param  DOCUMENT_ROOT /var/www/html;
		fastcgi_pass php:9000;
	}
  1. 但是fastcgi在处理’.php’文件时发现其并不存在,这时php.ini配置文件中的如下配置发挥作用,这项配置用于修复路径,如果当前路径不存在则会采用上层路径。为此这里交由fastcgi处理的文件就变成了’/test.png’。
#php.ini
cgi.fix_pathinfo=1

Provides real PATH_INFO/ PATH_TRANSLATED support for CGI. PHP’s previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok what PATH_INFO is. For more information on PATH_INFO, see the CGI specs. Setting this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting of zero causes PHP to behave as before. It is turned on by default. You should fix your scripts to use SCRIPT_FILENAME rather than PATH_TRANSLATED.

  1. 最重要的一点是php-fpm.conf中的security.limit_extensions配置项限制了fastcgi解析文件的类型(即指定什么类型的文件当做代码解析),此项设置为空的时候才允许fastcgi将’.png’等文件当做代码解析。
#php-fpm.conf
security.limit_extensions = 

限制 FPM 允许解析的脚本扩展名。 此设置可以预防 web 服务器配置的错误。 应当限制 FPM 仅仅解析 .php 扩展名,阻止恶意用户使用其他扩展名运行 php 代码。 默认值: .php .phar

在上述三个情况都满足的情况下我们就可以利用其文件解析漏洞:
phpinfo
nginx.png内容如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Blood_Pupil/article/details/88580260
今日推荐