[Vulhub] Nginx漏洞

文章目录


Nginx 解析漏洞

0x00 漏洞描述

访问http://your-ip/uploadfiles/nginx.pnghttp://your-ip/uploadfiles/nginx.png/.php即可查看效果。Nginx拿到文件路径(更专业的说法是URI)/nginx.png/.php后,一看后缀是.php,便认为该文件是php文件,转交给php去处理。php一看/nginx.png/.php不存在,便删去最后的/.php,又看/nginx.png存在,便把/nginx.png当成要执行的文件了。


0x01 影响版本

该漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞。


0x02 靶场环境

Nginx 1.x 最新版:https://vulhub.org/#/environments/nginx/nginx_parsing_vulnerability/


0x03 漏洞分析

1、由于nginx.conf的如下配置导致nginx把以.php结尾的文件交给fastcgi处理,为此可以构造http://ip/uploadfiles/nginx.png/.php(url结尾不一定是.php,任何服务器端不存在的php文件均可,比如a.php),其中nginx.png是我们上传的包含PHP代码的图片马。

default.conf配置文件如下:

server {
	listen 80 default_server;
	listen [::]:80 default_server;

	root /usr/share/nginx/html;

	index index.html index.php;

	server_name _;

	location / {
		try_files $uri $uri/ =404;
	}
	
	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;
	}
}

2、但是fastcgi在处理.php文件时发现文件并不存在,这时php.ini配置文件中cgi.fix_pathinfo=1 发挥作用,这项配置用于修复路径,如果当前路径不存在则采用上层路径。为此这里交由fastcgi处理的文件就变成了nginx.png

3、最重要的一点是php-fpm.conf中的security.limit_extensions配置项限制了fastcgi解析文件的类型(即指定什么类型的文件当做代码解析),此项设置为空的时候才允许fastcgi将.png等文件当做代码解析。
[Vulhub] Nginx漏洞
注:限制fpm允许解析的脚本扩展名。此设置可以预防web服务器配置的错误。应当限制fpm仅仅解析.php扩展名,阻止恶意用户使用其他扩展名运行php代码。默认值:.php

4、漏洞防御:

  1. php.ini文件中的cgi.fix_pathinfo的值设置为0,这样php再解析1.jpg/1.php这样的目录时,只要1.php不存在就会显示404页面
  2. php-fpm.conf中的security.limit_extensions后面的值设置为.php

参考链接:https://www.cnblogs.com/yuzly/p/11208742.html(nginx解析漏洞复现)


0x04 漏洞复现

访问靶场地址,正常上传php文件被拦截:
[Vulhub] Nginx漏洞
上传jpg文件,得到上传后文件路径:
[Vulhub] Nginx漏洞
访问文件路径,正常显示:
[Vulhub] Nginx漏洞
文件路径加入/.php,成功解析成php文件,证明上传代码不存在漏洞,但利用解析漏洞即可getshell:
[Vulhub] Nginx漏洞
如果将php-fpm.conf中的security.limit_extensions后面的值设置为.php,限制fpm仅仅解析.php扩展名,阻止恶意用户使用其他扩展名运行php代码。则不会将.jpg文件当作php代码解析。
[Vulhub] Nginx漏洞


Nginx 文件名逻辑漏洞(CVE-2013-4547)

0x00 漏洞描述

这一漏洞的原理是非法字符空格和截止符\0会导致Nginx解析URI时的有限状态机混乱,危害是允许攻击者通过一个非编码空格绕过后缀名限制。

正常情况下,只有.php后缀的文件才会被发送给fastcgi解析。
这里却错误地解析了请求的URI


0x01 影响版本

Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7


0x02 靶场环境

Nginx:https://vulhub.org/#/environments/nginx/CVE-2013-4547/


0x03 漏洞分析

这个漏洞其实和代码执行没有太大关系,其主要原因是错误地解析了请求的URI,错误地获取到用户请求的文件名,导致出现权限绕过、代码执行的连带影响。

举个例子,比如,Nginx匹配到.php结尾的请求,就发送给fastcgi进行解析,常见的写法如下:

location ~ \.php$ {
    include        fastcgi_params;

    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
    fastcgi_param  DOCUMENT_ROOT /var/www/html;
}

正常情况下(关闭pathinfo的情况下),只有.php后缀的文件才会被发送给fastcgi解析。

而存在CVE-2013-4547的情况下,我们请求1.gif[0x20][0x00].php,这个URI可以匹配上正则\.php$,可以进入这个Location块;但进入后,由于00截断,Nginx却错误地认为请求的文件是1.gif[0x20],就设置其为SCRIPT_FILENAME的值发送给fastcgi。

fastcgi根据SCRIPT_FILENAME的值进行解析,最后造成了解析漏洞。

所以,我们只需要上传一个空格结尾的文件,即可使PHP解析。

再举个例子,比如很多网站限制了允许访问后台的IP:

location /admin/ {
    allow 127.0.0.1;
    deny all;
}

我们可以请求如下URI:/test[0x20]/../admin/index.php,这个URI不会匹配上location后面的/admin/,也就绕过了其中的IP验证;但最后请求的是/test[0x20]/../admin/index.php文件,也就是/admin/index.php,成功访问到后台。(这个前提是需要有一个目录叫“test ”:这是Linux系统的特点,如果有一个不存在的目录,则即使跳转到上一层,也会爆文件不存在的错误,Windows下没有这个限制)

参考:https://www.freesion.com/article/8137557774/(NGINX不一样的逻辑漏洞)


0x04 漏洞复现

访问http://your-ip:8080/即可看到一个上传页面

// Check filesize
if(!is_uploaded_file($_FILES['file_upload']['tmp_name'])) {
    die('File is not uploaded file');
}

$ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION);
if (empty($ext) || in_array($ext, ['php', 'php3', 'php5', 'phtml'])) {
    die('Unsupported filetype uploaded.');
}

这里对上传的文件做了黑名单限制,上传图片马"test.jpg " ,注意后缀后面有空格:
[Vulhub] Nginx漏洞
访问http://your-ip:8080/uploadfiles/test.jpg[0x20][0x00].php,发现PHP已成功解析:

注意:[0x20]是空格,[0x00]\0,这两个字符都不需要编码。
抓包将.php前增加[0x20][0x00]两个字节,nginx识别到.php文件,但由于00截断fastcgi会解析test.jpg[0x20]文件
[Vulhub] Nginx漏洞
如果security.limit_extensions限制了值为.php则无法解析,可见security.limit_extensions威力强大,一招破万法。


Nginx越界读取缓存漏洞(CVE-2017-7529)

0x00 漏洞描述

如果请求中包含Range头,Nginx会根据指定的start和end位置,返回指定长度的内容。攻击者可以构造两个负的位置来获取响应中的缓存文件头部信息。在某些配置中,缓存文件头可能包含后端服务器的IP地址或其它敏感信息,比如缓存文件中位于HTTP返回包体前的文件头、HTTP返回包头,从而导致信息泄露。


0x01 影响版本

Nginx version 0.5.6 - 1.13.2


0x02 靶场环境

Nginx:https://vulhub.org/#/environments/nginx/CVE-2017-7529/


0x03 漏洞分析

由于对http header中range域处理不当造成。

主要代码是ngx_http_range_parse函数中的循环。

Nginx在反向代理站点的时候,通常会将一些文件进行缓存,特别是静态文件。缓存的部分存储在文件中,每个缓存文件包括“文件头”+“HTTP返回包头”+“HTTP返回包体”。如果二次请求命中了该缓存文件,则Nginx会直接将该文件中的“HTTP返回包体”返回给用户。

如果我们的请求中包含Range头,Nginx将会根据我指定的start和end位置,返回指定长度的内容。而如果我构造了两个负的位置,如(-600, -9223372036854774591),将可能读取到负位置的数据。如果这次请求又命中了缓存文件,则可能就可以读取到缓存文件中位于“HTTP返回包体”前的“文件头”、“HTTP返回包头”等内容。当Nginx服务器使用代理缓存的情况下,攻击者通过利用该漏洞可以拿到服务器的后端真实IP。

正向代理和反向代理
正向代理类似一个跳板机,代理访问外部资源:(正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端)

  1. 访问原来无法访问的资源,如google
  2. 可以做缓存,加速访问资源
  3. 对客户端访问授权,上网进行认证
  4. 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器:(反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端)

  1. 保证内网的安全,阻止web攻击,大型网站,通常将反向代理作为公网访问地址,Web服务器是内网
  2. 负载均衡,通过反向代理服务器来优化网站的负载

参考链接:
https://www.cnblogs.com/cute-puli/p/13282355.html
https://www.cnblogs.com/taostaryu/p/10547132.html


0x04 漏洞复现

访问http://your-ip:8080/index.html,即可查看到Nginx默认页面,这个页面实际上是反向代理的8081端口的内容。
[Vulhub] Nginx漏洞
调用python3 poc.py http://your-ip:8080/,读取返回结果:
[Vulhub] Nginx漏洞
可见,越界读取到了位于“HTTP返回包体”前的“文件头”、“HTTP返回包头”等内容。
如果读取有误,调整poc.py中的偏移地址(605)。


Nginx 配置错误导致漏洞

Mistake 1. CRLF注入漏洞

0x00 漏洞描述

CRLF注入
回车换行(CRLF)注入攻击是一种当用户将CRLF字符插入到应用中而触发漏洞的攻击技巧。CRLF字符(%0d%0a)在许多互联网协议中表示行的结束,包括HTML,该字符解码后即为\ r\ n。这些字符可以被用来表示换行符,并且当该字符与HTTP协议请求和响应的头部一起联用时就有可能会出现各种各样的漏洞,包括http请求走私(HTTP RequestSmuggling)和http响应拆分(HTTP Response Splitting)。

就http请求走私而言,这种漏洞通常出现在当服务器接收http请求并将该请求转发给其他服务器时,比如说代理和防火墙,这种漏洞将造成如下问题:

  1. 缓存毒化–攻击者可以修改缓存中的内容然后不显示正常页面而显示恶意页面。
  2. 防火墙逃逸–攻击者通过构造数据包来逃避安全检查,通常会利用CRLF和构造超大的数据包。
  3. 请求劫持–攻击者可以通过该利用获取HttpOnly的cookie和http认证数据,类似于xss但是不需要攻击者和黑客进行交互。

测试
CRLF注入漏洞的检测也和XSS漏洞的检测差不多。通过修改HTTP参数或URL,注入恶意的CRLF,查看构造的恶意数据是否在响应头中输出。主要是在看到有重定向或者跳转的地方,可以在跳转的地址添加?url=http://baidu.com/xxx%0a%0dSet-Cookie:%20test123=123测试一下,通过查看响应包的数据查看结果。

如果利用成功的话,响应包会出现一行Set-Cookie: test123=123 数据。

防御方式
服务端收到前端过来的参数,在加入Location之前,需要过滤 \r\n 之类的行结束符,避免输入的数据污染其它HTTP首部字段。

参考文章:
https://xz.aliyun.com/t/7501
https://zhuanlan.zhihu.com/p/22953209
https://www.cnblogs.com/mysticbinary/p/12560080.html


0x01 漏洞分析

Nginx会将$uri进行解码,导致传入%0a%0d即可引入换行符,造成CRLF注入漏洞。

错误的配置文件示例(原本的目的是为了让http的请求跳转到https上)

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

0x02 漏洞复现

利用Payload:http://your-ip:8080/%0a%0dSet-Cookie:%20test123=123,可注入Set-Cookie头:
[Vulhub] Nginx漏洞
利用Payload,http://your-ip:8080/%0a%0dSet-Cookie:%20test123=123%0d%0a%0d%0a<img src=1 οnerrοr=alert(/xss/)>,可构造一个xss漏洞:
[Vulhub] Nginx漏洞


Mistake 2. 目录穿越漏洞

0x00 漏洞描述

目录遍历/穿越漏洞是一个WEB安全漏洞,黑客可以利用该漏洞读取运行在服务器上的任意文件。文件可以是应用程序代码,或者数据,后端系统的凭证以及敏感的操作系统文件。在某些情况下,黑客可以在服务器上传任意文件然后允许他们修改应用程序数据行为,从而最终完全控制服务器。

在window上../..\都是有效的目录遍历序列

利用目录穿越漏洞的常见障碍
如果应用程序从用户提供的文件名中剥离或阻止目录穿越,则可以用多种技术绕过这种防御。

  1. 可以使用文件系统根目录中的绝对路径(filename=/etc/passwd)直接引用文件,无需任何的文件目录遍历。
  2. 使用嵌套的遍历序列,比如….//或者…./,当内部序列被剥离时,它们会被还原为简单的遍历序列
  3. 可以使用各种非标准编码(…%c0af或…%252f)来绕过输入过滤器
  4. 如果应用程序要求用户提供文件名必须以所需的基本文件夹(/var/www/images)开头,则可以包括所需的基本文件夹,后跟适当的遍历序列。例如:filename=/var/www/images/../../../etc/passwd
  5. 如果应用程序需要用户提供的文件名必须以某种要求的文件扩展名如。jpg结尾,则可以使用空子节有效终止要求的扩展名之前的文件路径比如:filename=../../../etc/passwd%00.jpg

防御方式
防止目录文件穿越攻击最有效的方法是避免将用户提供的输入完全传递给文件系统API。可以重写许多执行此操作的应用程序功能,以更安全的方式提供相同的行为。

如果认为将用户输入的信息传递给文件系统API是无法避免的,那么可以使用两层防御来防止攻击:应用程序将在处理之前验证用户输入。理想情况下,验证应与允许值中的白名单进行比较,如果所需功能无法做到这一点,则验证输入内容仅包含允许内容,例如纯字母数字字符。

参考链接:https://bbs.zkaq.cn/t/4315.html


0x01 漏洞分析

Nginx在配置别名(Alias)的时候,如果忘记加/,将造成一个目录穿越漏洞。

错误的配置文件示例(原本的目的是为了让用户访问到/home/目录下的文件):

location /files {
    alias /home/;
}

0x04 漏洞复现

Payload:http://your-ip:8081/files../ ,成功穿越到根目录:
[Vulhub] Nginx漏洞


Mistake 3. add_header被覆盖

0x00 漏洞描述

Nginx配置文件子块(server、location、if)中的add_header,将会覆盖父块中的add_header添加的HTTP头,造成一些安全隐患。


0x01 漏洞分析

如下列代码,整站(父块中)添加了CSP头:

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全部失效:


0x02 漏洞复现

访问/test1:
[Vulhub] Nginx漏洞
访问/test2:
[Vulhub] Nginx漏洞
XSS可被触发:
[Vulhub] Nginx漏洞


上一篇:WEB服务与NGINX(21)- nginx 的fastcgi反向代理功能


下一篇:CGI,FastCGI和PHP-FPM之间的关系和区别。