【问题标题】:Is it safe to rely on Content-Type: text/plain to mitigate malicious javascript execution in response?依赖 Content-Type: text/plain 来缓解恶意 javascript 执行响应是否安全?
【发布时间】:2015-09-03 01:26:56
【问题描述】:

我们有一个返回的网络应用程序


HTTP/1.1 400 Bad Request
...
Content-Type: text/plain;charset=UTF-8
Content-Length: 57
Date: Tue, 14 Apr 2015 19:24:54 GMT
Connection: close

Invalid project area item id 

<script>alert(1086)</script>

据我了解,仅依靠 Content-Type: text/plain;charset=UTF-8 作为防止 javascript 执行的防御是不够的。相反,应该对输出进行编码,并且应该对输入进行输入验证并丢弃垃圾。

我正在寻找的是关于处理内容类型已设置为 text/plain 的 javascript 的响应的正确方法的一些清晰且官方的答案。

任何人都有此场景的官方示例的链接(或答案)以及处理它的正确方法?或者是否只需要 Content-Type: text/plain;charset=UTF-8?

【问题讨论】:

  • 是什么在消耗这个错误信息?你输出什么或如何输出并不重要,这完全取决于它在另一端的使用方式。

标签: javascript xss content-type


【解决方案1】:

https://www.rfc-editor.org/rfc/rfc2046 'text/plain' 不应该处理指令种类,并且被简单地视为字符的线性序列。

【讨论】:

    【解决方案2】:

    这里有两种情况。

    顶级 XSS

    如果攻击者可以操纵顶级 URL 来响应格式错误的请求,例如

    HTTP/1.1 400 Bad Request
    ...
    <script>alert(document.cookie)</script>
    

    然后设置Content-Type: text/plain 缓解 XSS 攻击(请参阅下面的详细答案)。

    AJAX XSS

    但是,如果攻击者可以操纵目标网页中的某些 AJAX 函数并欺骗它执行类似$("#result").html(xss_request_result) 的操作,那么这会有效地将文本加载到 Web 上下文中,并由浏览器(包括 JS)解析,并且所有赌注都取消了

    明智的做法是entity-encodetag-strip 回复此类错误消息。


    关于第一种情况,根据w3.org

    文本的主要子类型是“普通”。这表示纯文本(未格式化)。 Internet 邮件的默认 Content-Type “text/plain; charset=us-ascii”描述了现有的 Internet 实践,即它是 RFC 822 定义的正文类型。

    这意味着 text/plain 不应被解释和处理。但是,Google(2011 年 3 月 30 日更新)声明,

    如果 Content-Type 匹配通用值之一,例如 application/octet-stream、application/unknown,甚至 text/plain,许多浏览器会将其视为允许对基于上述信号的价值,并尝试提出更具体的东西。此步骤的基本原理是一些配置不当的 Web 服务器在所有返回的内容上都回退到这些类型。

    根据一项名为Is HTML sniffed on text/plain documents (with or without file extension in URL)? 的浏览器嗅探调查,结果如下:

    • Internet Explorer 9+:否
    • FireFox:否
    • 歌剧:没有
    • 铬:否
    • Android:否
    • Safari:

    所以是的,将内容类型设置为 text/plain 并设置显式字符集将减轻 XSS 攻击,但从上述调查来看,Safari 可能会被阻止。

    测试您的浏览器是否存在此漏洞。转到更慷慨的在线 PHP fiddle 站点(例如 http://phptester.net/)并执行以下命令。你不应该得到一个弹出窗口。

    <?php
    header("Content-Type: text/plain");
    echo "<script>alert(1)</script>";
    

    更多阅读 Content-sniffing XSS attacks (PDF)

    【讨论】:

    • Safari 似乎不再在 text/plain 上嗅探 HTML
    【解决方案3】:

    上面 Drakes 的回答让我很困扰,所以我创建了一个简单的概念证明来看看我是否正确。我是。即使使用Content-Type: text/plain;charset=UTF-8,应用程序也可能受到简单的 XSS 攻击。

    原因,正如我第一次尝试在下面解释的那样,重要的是数据处理,以及数据的最终目的地和呈现上下文。交通没有那么重要。我创建了一个简单的 servlet,它像 OP 一样返回响应,包括 Content-Type 标头。回复如下:

    HTTP/1.1 400 Bad Request
    Server: Apache-Coyote/1.1
    Cache-Control: no-cache
    Content-Type: text/plain;charset=UTF-8
    Content-Length: 73
    Date: Thu, 18 Jun 2015 22:49:01 GMT
    Connection: close
    
    
    Invalid project area item id <iframe src=javascript:alert(1)></iframe> 
    

    这是结果的图像。请注意,攻击有效载荷已执行: https://flic.kr/p/uRnSgo

    同样,原因很简单。数据不是在 AJAX 请求中呈现,而是在消费 Web 应用程序页面中呈现,该页面一个 HTML 页面。

    无论如何,我希望这可以消除对在某些情况下易受攻击的任何疑虑......尤其是当响应是对将在消费页面中呈现的 AJAX 请求时。

    ----- 以下是我的原始回复。 -----

    带有错误消息的 400 响应对我来说是 REST API 响应的味道。

    如果这是一个 REST 请求(请求标头中的 X-Requested-With: XMLHttpRequestAccept: application/json),那么您将面临一个严重的问题。尽管此响应不受影响,但数据可能会被消费页面拾取并显示在最终用户的 UI 中。由于未正确编码,它执行。您不必总是担心这种响应,而是攻击有效载荷的最终处置。假设这是对 XMLHttpRequest 或 REST 调用的响应,这是一个严重的错误。

    您可以使用&lt;iframe src=javascript:alert(1)&gt;&lt;/iframe&gt; 的攻击负载进行测试,我敢打赌您会在消费应用程序中看到该弹窗。

    我建议: Invalid project area item id忽略无效值。最便宜的解决方案。

    所以,一般来说,你不能依靠Content-Type 来拯救你。数据可能会显示在它执行的另一个上下文中。

    始终验证输入并正确处理输出,其中可能包括某种格式的编码,具体取决于渲染的上下文。任何告诉您其他情况的人都试图摆脱一些必要的工作。 :-)

    【讨论】:

    • 如果您将任何网络响应通过管道传输到网络上下文中,那么当然它将在网络上下文中进行解析。那就是web 101。如果你直接伪造一个无效的请求,结果中得到了JS,而且上下文是text/plain,那我的答案就成立了。
    • OP 的问题: 还是只需要 Content-Type: text/plain;charset=UTF-8? 答案: 不,这还不是全部。您需要考虑数据的使用位置,并进行适当的编码。 Drakes,您上面的新答案得到了改进,谢谢。说没有什么可担心的原始答案具有误导性。
    猜你喜欢
    • 2012-05-19
    • 1970-01-01
    • 2016-01-23
    • 2021-06-22
    • 2019-05-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多