Nginx + php 通过 X-Accel-Redirect 防止上传图片嵌入脚本攻击方法

在允许用户上传图片的场景下,如何防止用户恶意上传一些包含恶意脚本的文件上传并执行是必须考虑的问题。

如果上传文件放在第三方文件api上,比如aws或阿里云专门的文件存储api或者七牛云存储,服务商一般会帮助处理这类问题;如果文件是放在服务器上,就不得不自己防范这类风险了。

这里记录一下实践中使用过的比较靠谱的一种做法:使用 X-Accel-Redirect。

关于Nginx的此特性,其它服务容器如apache也有类似的,不过作者没用过,大家需要自己去尝试,这里只以nginx为例说明。

用户要访问自己上传的文件,最简单的做法莫过于把文件放在一个web可访问的目录里,直接通过构造url路径访问。但这样做一方面不能保护比较隐密的数据,比如用户的实名认证图片,另一方面也容易被攻击,比如:

Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设置SCRIPT_FILENAME。当访问http://192.168.1.103/phpinfo.jpg/1.php这个URL时,$fastcgi_script_name会被设置为“phpinfo.jpg/1.php”,然后构造成SCRIPT_FILENAME传递给PHP CGI。如果PHP中开启了fix_pathinfo这个选项,PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将phpinfo.jpg作为PHP文件来解析了。

如果让所有访问过后台代码,这样可以加上权限控制,但是就需要php代码来读取图片返回给客户端,会给服务器造成很大的io压力。这时 X-Accel-Redirect 就可以派上用场了。

X-Accel-Redirect 的功能很简单,就是在用户需要访问静态内容的时候,通过后台设置header,将静态资源通过nginx直接返回到客户端。因为不过后台代码,所以即便文件内容中包含恶意脚本,也不可能会执行。要访问静态文件直接被访问到,还需要配合设置

        location /filedir/ {
                root   /home/foo/yourroot;
                internal;
        }

把静态文件所在的目录设置为inernal。

这样再配合后台的权限控制逻辑,就可以实现安全的文件访问了。示例代码如下:

$forbidden = false;
$mimeType = array(
    'png'  => 'image/png',
    'gif'  => 'image/gif',
    'jpg'  => 'image/jpeg',
    'jpeg' => 'image/jpeg',
    'pdf'  => 'application/pdf',
);
if (!isset($_GET['path']) || !isset($_GET['type'])) {
    $path = '';
    $forbidden = true;
} else {
    $path = 'filedir/'.trim($_GET['path'] . '.' . $_GET['type'], '/');// 补全路径
    if (!file_exists($path) || !isset($mimeType[$_GET['type']])) {
        $forbidden = true;
    } else {
        // 权限验证 todo
    }
}

header("Cache-Control: max-age=60");// 设置缓存时间
if (!$forbidden && !empty($path)) {
    $contentType = $mimeType[$_GET['type']];
    header("Content-Type: {$contentType}"); // 严格限制内容类型
    header("X-Accel-Redirect: /{$path}");
} else {
    header("Content-Type: image/gif");
    header("Location: /filedir/404.gif");
}
在生产中使用,效果良好。如果有其它问题,欢迎大家批评指出,一起讨论。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Nginx是一个高性能的开源Web服务器,同时也可以用作反向代理服务器、负载均衡器和流媒体服务器。Nginx的Rtmp-Module是一个第三方模块,它为Nginx服务器添加了RTMP(Real-Time Messaging Protocol)支持,使其可以充当一个流媒体服务器。FFmpeg是一个跨平台的音视频处理工具,它可以用来进行多媒体文件的转码、编解码、录制和流媒体输等操作。 引用中提到了使用Nginx Nginx-Rtmp-Module Ffmpeg搭建流媒体服务器的方法。具体配置可以查看conf/nginx.conf文件。首先需要解压文件,然后运行nginx_start.bat文件来启动Nginx服务器。这样就可以使用Nginx服务器提供的RTMP服务,通过FFmpeg推送一个RTMP流到Nginx,然后客户端可以通过访问Nginx来收看实时视频流。还可以使用HLS(HTTP Live Streaming)协议,通过HTTP协议来访问Nginx服务器并收看视频流,但是FFmpeg推送流仍然是RTMP的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [nginx+nginx-rtmp-module+ffmpeg搭建流媒体服务器服务器](https://blog.csdn.net/sinat_16643223/article/details/115108327)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ffmpeg+nginx+nginx-rtmp-module搭建个人直播平台](https://download.csdn.net/download/qq_29114677/13012815)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LeetJoe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值