nginx文件类型错误解析漏洞

本文介绍了一种利用Nginx与PHP配置不当导致的安全漏洞,即通过特定URL格式使Nginx错误地将非PHP文件当作PHP脚本执行。文章详细解释了漏洞原理,并提供了多种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题简介:
nginx是一款高性能的web服务器,使用非常广泛,其不仅经常被用作反向代理,也可以非常好的支持PHP的运行。nginx默认以cgi的方式支持php的运行,而为了较好的支持PATH_INFO的提取,在PHP的配置选项里存在cgi.fix_pathinfo选项,其目的是为了从SCRIPT_FILENAME里取出真正的脚本名,而攻击者则利用这点可以将任何类型的文件以PHP的方式进行解析。
影响版本:0.5.*, 0.6.*, 0.7 <= 0.7.65, 0.8 <= 0.8.37  ,目前我们版本在1.1以上。

 

举例说明:
假设test.king.com是一个论坛,可以上传图片操作(后台有bug并没有对图片进行判断处理),用户已经上传一张包含php脚本的图片abc.jpg

现将test.king.com修定本地
浏览器访问test.king.com/abc.jpg,此时会显示无法浏览此图片
现访问test.king.com/abc.jpg/c.php 或者test.king.com/abc.jpg%00.php 则会将abc.jpg当做脚本文件直接运行,会显示出abc.jpg里的脚本代码phpinfo()信息
(以上只限测试,如有人想尝试,可在虚拟机上运行)
原理:
nginx在接受请求后会得到一个地址URL/abc.jpg/c.php
在经过location指令,将请求交给fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为/abc.jpg/c.php
后端的fastcgi在接受到该选项时,会根据PHP的fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理,一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,

所以该选项一般配置开启。Php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离SCRIPT_FILENAME和PATH_INFO分别为/scripts/abc.jpg和c.php
最后,以/scripts/abc.jpg作为此次请求需要执行的脚本,攻击者就可以实现让nginx以php来解析任何类型的文件了。

解决:

关闭php.ini里的cgi.fix_pathinfo为0
或者
if ( $fastcgi_script_name ~ ..*/.*php ) {
return 403;
}
前两个可能会导致一些伪静态网页或者特殊的路径无法显示

宴哥提供了一个方法可写在fcgi.conf文件中,便于多个虚拟主机引用
if ($request_filename ~* (.*).php) {
    set $php_url $1;
}
if (!-e $php_url.php) {
    return 403;
}
### Java 实现本地图片存储并由 Nginx 进行代理的服务 #### 一、Java 应用程序中的文件上传处理逻辑 为了支持图片的上传功能,在Spring Boot应用程序中,需要配置MultipartFile处理器以及设置保存路径。 ```java import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; public class ImageUploadController { private static final String SAVE_PATH = "/path/to/save/images/"; @PostMapping("/upload") public String handleFileUpload(@RequestParam("file") MultipartFile file) { if (!file.isEmpty()) { try { byte[] bytes = file.getBytes(); File dir = new File(SAVE_PATH); if (!dir.exists()) dir.mkdirs(); // Create the file on server File serverFile = new File(dir.getAbsolutePath() + File.separator + file.getOriginalFilename()); BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile)); stream.write(bytes); stream.close(); return "You successfully uploaded " + file.getName(); } catch (IOException e) { return "Failed to upload " + file.getName() + ". Error: " + e.getMessage(); } } else { return "Failed to upload because the file was empty."; } } } ``` 此代码片段展示了如何接收来自客户端提交的文件,并将其保存至服务器上的特定位置[^1]。 #### 二、Nginx 配置以提供静态资源访问 为了让外部能够通过HTTP请求获取这些已上传的图像,需调整Nginx配置使其作为反向代理服务器工作: ```nginx server { listen 80; server_name localhost; location /images/ { alias /path/to/save/images/; auto_index off; # 关闭目录列表显示 expires max; # 设置缓存策略 } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } ``` 上述配置使得任何针对`http://yourdomain.com/images/*`模式URL发出的GET请求都将被映射到实际存放于磁盘上相应子目录内的文件[^2]。 当用户尝试浏览某个具体图片链接时(例如:`http://example.com/images/example.jpg`),Nginx会直接从指定的物理路径读取该文件并向浏览器返回其内容而不必经过后端应用层转发。 #### 三、确保安全性考虑 考虑到安全因素,在开放对外接口之前应当仔细审查权限控制机制。对于生产环境而言,建议启用HTTPS协议加密传输通道;同时限制允许上传的内容类型仅限于合法格式如JPEG, PNG等;另外还需注意防范潜在的安全漏洞比如XSS攻击等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值