Nginx + php 通过 X-Accel-Redirect 防止上传图片嵌入脚本攻击方法
2018-03-02 15:51
671 查看
在允许用户上传图片的场景下,如何防止用户恶意上传一些包含恶意脚本的文件上传并执行是必须考虑的问题。
如果上传文件放在第三方文件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");
}在生产中使用,效果良好。如果有其它问题,欢迎大家批评指出,一起讨论。
如果上传文件放在第三方文件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");
}在生产中使用,效果良好。如果有其它问题,欢迎大家批评指出,一起讨论。
相关文章推荐
- PHP中通过语义URL防止网站被攻击的方法分享
- PHP中通过语义URL防止网站被攻击的方法分享
- php上传图片得到路径给表单字段赋值的通用方法
- PHP Fckeditor上传文件(或图片)中文显示为乱码的解决方法
- PHP+MYSQL如何防止脚本注入攻击
- 在PHP中通过POST方法实现文件上传功能
- php实现防止图片盗链采集的方法
- php上传图片得到路径给表单字段赋值的通用方法
- PHP防止跨站攻击的脚本
- php 异步上传图片几种方法总结
- php 图片上传进度条代码方法
- PHP设置图片文件上传大小的具体实现方法
- PHP上传真彩图片缩略图质量失真解决方法 推荐
- 通过Fckeditor把图片上传到独立图片服务器的方法
- 考虑使用AntiXss.HtmlEncode方法来防止跨站点脚本攻击
- 一个自己写的真正判断文件格式,文件大小,而并不仅仅从扩展名来进行判断的上传方法,进一步加强防止软件或恶意的木马图片上传
- Asp.net MVC防止图片盗链的实现方法,通过自定义RouteHandler来操作
- nginx+php 上传含有php脚本的木马图片文件的漏洞解决
- 基于php上传图片重命名的6种解决方法的详细介绍
- 一个自己写的真正判断文件格式,文件大小,而并不仅仅从扩展名来进行判断的上传方法,进一步加强防止软件或恶意的木马图片上传