ToB企服应用市场:ToB评测及商务社交产业平台

标题: HTTP协议安全头部X-Content-Type-Options引入的问题 [打印本页]

作者: 忿忿的泥巴坨    时间: 2024-3-11 11:12
标题: HTTP协议安全头部X-Content-Type-Options引入的问题
本文于2016年4月完成,发布在个人博客网站上。 考虑个人博客因某种原因无法修复,于是在博客园安家,之前发布的文章逐步搬迁过来。
前段时间测试MM反馈了一个问题,在富文本编辑器里上传的图片无法正常呈现。因为Jackie在本机的环境上没有观察类似的现象,而恰好那天测试环境的某个重要配项被改错了,于是Jackie想当然的归类为配置项错误引入的问题。但修改完测试环境的配置项后,测试反馈富文本编辑器内图片无法呈现的现象依然存在。
这下就有点麻烦了,问题是在版本上线的前一天晚上发现的,如果问题不能尽快处理,势必对第二天的版本上线产生影响。虽然逢上线必加班至深夜,但也不能让问题挂在Jackie手里。
时间紧急,问题诡异,Jackie马上放下手头的工作,全力投入分析工作中。
排查过程

幸运的是提交记录不多,10分钟之内被Jackie扫描了一遍;大部分提交记录都是清白了,唯一可疑的提交记录来自于Jackie本人,果然这个问题只能由Jackie来定位和分析。为了解决AppScan报告中提到的“HTTP响应缺少安全头部”的警告,Jackie在发现问题的那天早上修改了Tomcat的配置,增加了安全头部相关的过滤器,而晚上留在办公室加班,目的就是要确认前述的警告是否已消除。
为了确认前述问题和HTTP安全头部的相关性,Jackie手工修改测试环境上Tomcat的配置,去掉了增加安全头部的过滤器,重启Tomcat后尝试重现问题,惊喜的发现,富文本编辑器内的图片恢复正常呈现,这说明HTTP响应增加安全头部之后,对基本功能产生了影响。
当前启用了HTTP协议的安全头部的如下几个:
范围比较小,逐个排查之后,发现前述问题现象和X-Content-Type-Options相关,因此决定仍然启用HTTP安全头部的输出,但禁用X-Content-Type-Options,富文本编辑器内的图片可以正常呈现,同时不会对安全性造成很大的影响。
本来觉得修改Tomcat的配置和业务不相关,不会有什么问题,也没有过基本功能,结果偏偏天不遂人愿,还真让测试MM发现个诡异问题。看来侥幸心理不能有,该做的工作不能省,否则就得加班、加倍的补回来。
下面使用最少的样例代码来说明问题是如何发生的。
问题是如何发生的

准备复现环境

jsp页面
  1. <%@ page session="false" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
  2. <!DOCTYPE html>
  3. <html lang="en">
  4.     <head>
  5.         <meta charset="UTF-8" />
  6.         <title><%=request.getServletContext().getServerInfo() %></title>
  7.     </head>
  8.         
  9.             <img alt="FileDownload" src="https://www.cnblogs.com/<%=request.getContextPath()%>/GetPicture">
  10.         
  11.     <body>
  12.         
  13.     </body>
  14. </html>
复制代码
GetPicture的实现

如下这段代码的实现存在问题,使用流方式返回数据时,没有显式指定Content-Type。
  1. package com.struts2.servlets;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import org.apache.commons.io.IOUtils;
  12. public class GetPictureServlet extends HttpServlet {
  13.         private static final long serialVersionUID = -5935833295545479697L;
  14.         @Override
  15.         protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  16.                         throws ServletException, IOException {                       
  17.                 String path = req.getServletContext().getRealPath("");
  18.                 byte[] buffer = new byte[4096];
  19.                 int count = 0;
  20.                 InputStream is = null;
  21.                 OutputStream os = null;
  22.                 try
  23.                 {
  24.                         is = new FileInputStream(new File(path, "tomcat.png"));
  25.                         os = resp.getOutputStream();
  26.                        
  27.                         while ((count = is.read(buffer)) > 0) {
  28.                                 os.write(buffer, 0, count);
  29.                         }
  30.                 }
  31.                 catch (IOException e)
  32.                 {
  33.                         e.printStackTrace();
  34.                 }
  35.                 finally
  36.                 {
  37.                         IOUtils.closeQuietly(is);
  38.                         IOUtils.closeQuietly(os);
  39.                 }
  40.         }
  41. }
复制代码
web.xml
  1. <servlet>
  2.     <servlet-name>GetPictureServlet</servlet-name>
  3.     <servlet-class>com.struts2.servlets.GetPictureServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6.     <servlet-name>GetPictureServlet</servlet-name>
  7.     <url-pattern>/GetPicture</url-pattern>
  8. </servlet-mapping>   
复制代码
使用浏览器观察

重温一些安全相关的HTTP响应头中对X-Content-Type-Options的介绍。
互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:"text/html"代表html文档,"image/png"是PNG图片,"text/css"是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。
使用浏览器调试面板来观察HTTP响应的头部,对上文做验证。
结论

按照减少 MIME 类型的安全风险的介绍,IE的行为受X-Content-Type-Options的影响,如果Web应用没有返回Content-Type,那么IE9、IE11将拒绝加载相关资源。
如果服务器发送响应头 "X-Content-Type-Options: nosniff",则 script 和 styleSheet 元素会拒绝包含错误的 MIME 类型的响应。这是一种安全功能,有助于防止基于 MIME 类型混淆的攻击。
从前述的测试结果看,的确证实了X-Content-Type-Options对IE9、IE11的影响。
但仍有不明之事,文章减少 MIME 类型的安全风险只提到了script和stylesheet标签,没有提到img标签,不了解为什么X-Content-Type-Options对图片的加载也会产生影响。后来使用Windows 10的Edge做验证,发现Edge也存在相同的问题,只要启用了X-Content-Type-Options,那么图片必定呈现不出来。Jackie猜,这也许是文档太旧了,或者是Jackie没有找到最新的文档。
另外按照Jerry Qu的文章一些安全相关的HTTP响应头的描述,X-Content-Type-Options应该会影响Chrome的行为,但从测试结果看,使用img标签加载图片时,如果Web应用没有返回Content-Type,无论是否启用X-Content-Type-Options,Chrome都可以正常呈现图片,这一点比较奇怪。
参考资料


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4