漏洞介绍:nginx是一款高性能的web服务器,使用非常广泛,其不仅经常被用作反向代理,也可以非常好的支持PHP的运行。80sec发现其中存在一个较为严重的安全问题,默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析,这将导致严重的安全问题,使得恶意的攻击者可能攻陷支持php的nginx服务器。
漏洞分析:nginx默认以cgi的方式支持php的运行,譬如在配置文件当中可以以
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
} |
的方式支持对php的解析,location对请求进行选择的时候会使用URI环境变量进行选择,其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定,而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的,这里就是产生问题的点。而为了较好的支持PATH_INFO的提取,在PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出真正的脚本名。
那么假设存在一个http://www.80sec.com/80sec.jpg,我们以如下的方式去访问
http://www.80sec.com/80sec.jpg/80sec.php
将会得到一个URI
/80sec.jpg/80sec.php
经过location指令,该请求将会交给后端的fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为
/scripts/80sec.jpg/80sec.php
而在其他的webserver如lighttpd当中,我们发现其中的SCRIPT_FILENAME被正确的设置为
/scripts/80sec.jpg
所以不存在此问题。
后端的fastcgi在接受到该选项时,会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理,一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为
/scripts/80sec.jpg和80sec.php
最后,以/scripts/80sec.jpg作为此次请求需要执行的脚本,攻击者就可以实现让nginx以php来解析任何类型的文件了。
POC: 访问一个nginx来支持php的站点,在一个任何资源的文件如robots.txt后面加上/80sec.php,这个时候你可以看到如下的区别:
访问http://www.80sec.com/robots.txt
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:05:30 GMT
Content-Type: text/plain
Content-Length: 18
Last-Modified: Thu, 20 May 2010 06:26:34 GMT
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes |
访问访问http://www.80sec.com/robots.txt/80sec.php
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:06:49 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.6 |
其中的Content-Type的变化说明了后端负责解析的变化,该站点就可能存在漏洞。
漏洞厂商:http://www.nginx.org
解决方案:
我们已经尝试联系官方,但是此前你可以通过以下的方式来减少损失
关闭cgi.fix_pathinfo为0
或者
if ( $fastcgi_script_name ~ \..*\/.*php ) {
return 403;
} |
另外发现php 4.xx不存在cgi.fix_pathinfo,同时测试也没发现此漏洞可用
本文来自:http://www.80sec.com/nginx-securit.html
张宴《实战Nginx:取代Apache的高性能Web服务器》pdf电子书下载
目录介绍:
第1部分 基础篇
第1章 Nginx简介
1.1 常用的Web服务器简介
1.2 Nginx简介
1.3 选择Nginx的理由
1.4 Nginx与Apache、Lighttpd的综合对比
第2章 Nginx服务器的安装与配置
2.1 安装Nginx服务器所需要的系统资源
2.2 Nginx的下载
2.3 Nginx的安装
2.4 Nginx的启动、停止、平滑重启
2.5 Nginx的平滑重启
2.6 Nginx的信号控制
2.7 Nginx的平滑升级
第2部分 进 阶 篇
第3章 Nginx的基本配置与优化
3.1 Nginx的完整配置示例
3.2 Nginx的虚拟主机配置
3.3 Nginx的日志文件配置与切割
3.4 Nginx的压缩输出配置
.3.5 Nginx的自动列目录配置
3.6 Nginx的浏览器本地缓存设置
第4章 Nginx与PHP(FastCGI)的安装、配置与优化
4.1 获取相关开源程序
4.2 安装PHP 5.2.10(FastCGI模式)
4.3 安装Nginx 0.8.15
4.4 配置开机自动启动Nginx + PHP
4.5 优化Linux内核参数
4.6 在不停止Nginx服务的情况下平滑变更Nginx配置
4.7 编写每天定时切割Nginx日志的脚本
第5章 Nginx与JSP、ASP.NET、Perl的安装与配置
5.1 Nginx与JSP(Tomcat)在Linux上的安装、配置
5.2 Nginx与ASP.NET(Mono+FastCGI)在Linux上的安装、配置
5.3 Nginx与Perl(FastCGI)在Linux上的安装、配置
第6章 Nginx HTTP负载均衡和反向代理的配置与优化
6.1 什么是负载均衡和反向代理
6.2 常见的Web负载均衡方法
6.3 Nginx负载均衡与反向代理的配置实例
6.4 Nginx负载均衡的HTTP Upstream 模块
6.5 Nginx负载均衡服务器的双机高可用
第7章 Nginx的Rewrite规则编写实例
7.1 什么是Nginx的Rewrite规则
7.2 Nginx Rewrite规则相关指令
7.3 PCRE正则表达式语法
7.4 Nginx的Rewrite规则编写实例
7.5 Nginx与Apache的Rewrite规则实例对比
第8章 Nginx模块开发
8.1 Nginx模块概述
8.2 Nginx模块编写实践
第9章 Nginx的Web缓存服务与新浪网的开源NCACHE模块
9.1 什么是Web缓存?
9.2 Nginx的Web缓存服务
9.3 新浪网开源软件项目——基于Nginx的NCache网页缓存系统
第3部分 实战篇
第10章 Nginx在国内知名网站中的应用案例
10.1 Nginx反向代理与负载均衡类网站应用案例
10.2 Nginx+PHP类网站应用案例
第11章 Nginx的非典型应用实例
11.1 用HTTPS(SSL)构建一个安全的Nginx Web服务器
11.2 采用Nginx搭建FLV视频服务器
11.3 Nginx+PHP+MySQL在小内存VPS服务器上的优化
11.4 采用Nginx搭建正向代理服务器
第4部分 模块篇
第12章 Nginx的核心模块
12.1 主模块指令
12.2 主模块变量
12.3 事件模块指令
第13章 Nginx的标准HTTP模块
13.1 HTTP的核心模块
13.2 HTTP Upstream模块
13.3 Http Access 模块
13.4 HTTP Auth Basic 模块
13.5 Http Autoindex 模块
13.6 Http Browser 模块
13.7 Http Charset 模块
13.8 Http Empty Gif模块
13.9 Http Fcgi 模块
13.10 geo 模块
13.11 Gzip 模块
13.12 Http Headers模块
13.13 Http Index模块
13.14 HTTP Referer模块
13.15 Http Limit Zone模块
13.16 Http Limit Req模块
13.17 Http Log模块
13.18 Http Map模块
13.19 Http Memcached模块
13.20 Http Proxy模块
第14章 Nginx的其他HTTP模块
14.1 Http Addition模块
14.2 Embedded Perl模块
14.3 Flv Stream模块
14.3 flv 指令
14.4 Http Gzip Static模块
14.5 Http Random Index模块
14.6 Http Geo IP模块
14.7 Http RealIp模块
14.8 Http SSL模块
14.9 Http Stub Status模块
14.10 Http Sub模块
14.11 Http Dav模块
14.12 Google Perftools模块
14.13 Http XSLT模块
14.14 Http Secure Link模块
14.15 Http Image Filter模块
第15章 Nginx的邮件模块
15.1 Nginx邮件核心模块
15.2 Nginx邮件认证模块
15.3 Nginx邮件代理模块
15.4 Nginx邮件SSL模块
15.5 Nginx邮件模块配置实例
索引
参考资料
之前写过一篇blog是《利用lighttpd的mod_secdownload实现防盗链》,最近看到nginx也有类似功能,叫secure_link_module模块也试验了一把。
nginx需要打一个补丁才能实现跟lighttpd一样,通过时间戳来控制url过期。
1.给nginx打补丁,下载《nginx-secure-link-ttl》:
cd nginx-0.7.62
patch -p1 < ../nginx-secure-link-ttl.patch |
2.编译nginx的时候加上“–with-http_secure_link_module”
3.配置nginx:
location /down/ {
secure_link_secret "sbear.cn"; //密钥
secure_link_ttl on;
root /data/test/down;
if ($secure_link = "") {
return 403;
}
rewrite ^ /$secure_link break;
} |
4.php demo:
<?php
define(URL_TIMEOUT, 3600); //这里设置过期时间单位是秒
$prefix = "http://www.sbear.cn/down";
$protected_resource = "test.exe";
$secret = "sbear.cn"; //密钥
$time = pack('N', time() + URL_TIMEOUT);
$timeout = bin2hex($time);
$hashmac = md5( $protected_resource . $time . $secret );
$url = $prefix . "/" . $hashmac . $timeout . "/" . $protected_resource;
echo "<a href=" . $url . ">down</a>";
echo time();
?> |
官方模块介绍:http://wiki.nginx.org/NginxHttpSecureLinkModule